Splunk Observability Cloud 用 .NET Azure WebJobs をインストルメンテーションする

OpenTelemetry .NET SDK を使用して、Azure WebJobs 上で実行されているアプリケーションまたはサービスをインストルメンテーションすることができます。開始するには、次の手順を実行します。

OpenTelemetry .NET SDK を使用して、Azure WebJobs 上で実行されているアプリケーションまたはサービスをインストルメンテーションすることができます。開始するには、次の手順を実行します。

環境変数の定義

アプリケーションに必要な環境変数を設定します。

  1. Azure Web App でアプリケーションを選択します。

  2. Settings > Configuration に進みます。

  3. New application setting を選択し、以下の設定を追加します:

    Name

    SPLUNK_ACCESS_TOKEN

    Splunk アクセストークン。アクセストークンを取得するには、「Splunk Observability Cloud を使用したユーザー API アクセストークンの取得と管理」を参照してください。

    SPLUNK_REALM

    Splunk Observability Cloud のレルム(us0 など)。レルムを見つけるには、「 Configure SSO integrations for Splunk Observability Cloud」を参照してください。

  4. その他必要な設定を追加します。「Splunk Distribution of OpenTelemetry .NET を設定する」を参照してください。

NuGetを使って必要なライブラリを追加する

Visual Studio の NuGet パッケージマネージャを使用して、以下のライブラリを追加します。

分離されたワーカープロセス機能

  1. Include prerelease 設定をアクティブ化します。

  2. 以下のライブラリの最新版をインストールします:

コード内でOpenTelemetryを初期化する

  1. 依存関係を追加したら、アプリケーション用の OpenTelemetry ヘルパーを作成します:
    JAVASCRIPT
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Host;
    using Microsoft.Extensions.DependencyInjection;
    using OpenTelemetry.Exporter;
    using OpenTelemetry.Metrics;
    using OpenTelemetry.Resources;
    using OpenTelemetry.Trace;
    using System.Diagnostics;
    
    namespace <YourNamespaceHere>.Helpers;
    
    internal static class SplunkOpenTelemetry
    {
        private static readonly string AccessToken;
        private static readonly string Realm;
    
        static SplunkOpenTelemetry()
        {
            AccessToken = Environment.GetEnvironmentVariable("SPLUNK_ACCESS_TOKEN")?.Trim()
                ?? throw new ArgumentNullException("SPLUNK_ACCESS_TOKEN");
    
            Realm = Environment.GetEnvironmentVariable("SPLUNK_REALM")?.Trim()
                ?? throw new ArgumentNullException("SPLUNK_REALM");
        }
    
        public static IWebJobsBuilder AddSplunkOpenTelemetry(this IWebJobsBuilder builder)
        {
            // Get environment variables from function configuration
            // You need a valid Splunk Observability Cloud access token and realm
            var serviceName = Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME") ?? "Unknown";
            var enableTraceResponseHeaderValue = Environment.GetEnvironmentVariable("SPLUNK_TRACE_RESPONSE_HEADER_ENABLED")?.Trim();
    
            builder.Services.AddOpenTelemetry()
                .ConfigureResource(cfg => cfg
                    // See https://github.com/open-telemetry/opentelemetry-dotnet-contrib/tree/main/src/OpenTelemetry.Resources.Azure
                    // for other types of Azure detectors
                    .AddAzureAppServiceDetector()
                    .AddService(serviceName: serviceName, serviceVersion: "1.0.0"))
                .WithTracing(t => t
                    // Use Add[instrumentation-name]Instrumentation to instrument missing services
                    // Use Nuget to find different instrumentation libraries
                    .AddHttpClientInstrumentation(opts =>
                    {
                        // This filter prevents background (parent-less) http client activity
                        opts.FilterHttpWebRequest = req => Activity.Current?.Parent != null;
                        opts.FilterHttpRequestMessage = req => Activity.Current?.Parent != null;
                    })
                    // Use AddSource to add your custom DiagnosticSource source names
                    //.AddSource("My.Source.Name")
                    // Automatically creates the root span with function start
                    .AddSource(SplunkFunctionAttribute.ActivitySourceName)
                    .SetSampler(new AlwaysOnSampler())
                    .AddOtlpExporter(opts =>
                    {
                        opts.Endpoint = new Uri($"https://ingest.{Realm}.signalfx.com/v2/trace/otlp");
                        opts.Protocol = OtlpExportProtocol.HttpProtobuf;
                        opts.Headers = $"X-SF-TOKEN={AccessToken}";
                    }))
                .WithMetrics(m => m
                    // Use Add[instrumentation-name]Instrumentation to instrument missing services
                    // Use Nuget to find different instrumentation libraries
                    .AddHttpClientInstrumentation()
                    .AddRuntimeInstrumentation()
                    .AddProcessInstrumentation()
                    .AddOtlpExporter(opts =>
                    {
                        opts.Endpoint = new Uri($"https://ingest.{Realm}.signalfx.com/v2/datapoint/otlp");
                        opts.Headers = $"X-SF-TOKEN={AccessToken}";
                    }));
    
            return builder;
        }
    }
    
    internal class SplunkFunctionAttribute : FunctionInvocationFilterAttribute
    {
        public const string ActivitySourceName = "Splunk.Azure.WebJob";
    
        private static readonly ActivitySource ActivitySource = new(ActivitySourceName);
    
        private Activity? _currentActivity;
    
        public override Task OnExecutingAsync(FunctionExecutingContext executingContext, CancellationToken cancellationToken)
        {
            _currentActivity = ActivitySource.StartActivity(executingContext.FunctionName, ActivityKind.Server);
            _currentActivity?.AddTag("faas.name", executingContext.FunctionName);
            _currentActivity?.AddTag("faas.instance", executingContext.FunctionInstanceId);
    
            return base.OnExecutingAsync(executingContext, cancellationToken);
        }
    
        public override Task OnExecutedAsync(FunctionExecutedContext executedContext, CancellationToken cancellationToken)
        {
            if (!executedContext.FunctionResult.Succeeded)
            {
                if (executedContext.FunctionResult.Exception != null)
                {
                    _currentActivity?.SetStatus(Status.Error.WithDescription(executedContext.FunctionResult.Exception.Message));
                    _currentActivity?.RecordException(executedContext.FunctionResult.Exception);
                }
                else
                {
                    _currentActivity?.SetStatus(Status.Error);
                }
            }
    
            _currentActivity?.Stop();
    
            return base.OnExecutedAsync(executedContext, cancellationToken);
        }
    }
  2. Program.cs ファイルで作成したヘルパーを使用します:
    CODE
    var builder = new HostBuilder()
    .ConfigureWebJobs(context =>
    {
        context.AddSplunkOpenTelemetry();
    })
  3. SplunkFunctionAttribute は、定義されたすべての WebJobs 関数で使用します。関数に適切に属性を設定する方法の例を参照してください。
    JAVA
    public class Functions
    {
        [SplunkFunction]
        public void ProcessTimer([TimerTrigger("1/5 * * * * *")] TimerInfo timerInfo, ILogger logger)
        {
            logger.LogInformation("Hello World!");
        }
    }

データが入力されていることを確認する

関数を実行し、Splunk APM でスパンを検索します。詳細については、「トレース内でのスパンの表示およびフィルタリング」を参照してください。

トラブルシューティング

If you are a Splunk Observability Cloud customer and are not able to see your data in Splunk Observability Cloud, you can get help in the following ways.

Available to Splunk Observability Cloud customers

Available to prospective customers and free trial users

  • Ask a question and get answers through community support at Splunk Answers.

  • Join the Splunk community #observability Slack channel to communicate with customers, partners, and Splunk employees worldwide.