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

OpenTelemetry .NET SDK を使って、Azure Web App Service 上で動作するアプリケーションやサービスをインストルメンテーションすることができます。開始するには、次の手順を実行します。

OpenTelemetry .NET SDK を使って、Azure Web App Service 上で動作するアプリケーションやサービスをインストルメンテーションすることができます。開始するには、次の手順を実行します。

環境変数の定義

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

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

  2. SettingsConfiguration にアクセスします。

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

    Name

    SPLUNK_ACCESS_TOKEN

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

    SPLUNK_REALM

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

    SPLUNK_TRACE_RESPONSE_HEADER_ENABLED

    Splunk RUM との統合を有効にするかどうか。デフォルト値は true です。

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

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

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

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

  1. Include prerelease 設定を有効にします。

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

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

依存関係を追加したら、アプリケーション用の OpenTelemetry ヘルパーを作成します:

using OpenTelemetry.Exporter;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using System.Diagnostics;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

namespace <YourNamespaceHere>.Extensions;

public static class SplunkOpenTelemetry
{
    private static readonly string AccessToken;
    private static readonly string Realm;

    static SplunkOpenTelemetry()
    {
        // Get environment variables from function configuration
        // You need a valid Splunk Observability Cloud access token and realm
        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 WebApplicationBuilder AddSplunkOpenTelemetry(this WebApplicationBuilder builder)
    {
        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;
                })
                .AddAspNetCoreInstrumentation(opts =>
                {
                    // Enables Splunk RUM integration when configuration contains SPLUNK_TRACE_RESPONSE_HEADER_ENABLED=True
                    if (bool.TryParse(enableTraceResponseHeaderValue, out bool isEnabled) && isEnabled)
                    {
                        opts.EnrichWithHttpRequest = (activity, request) =>
                        {
                            var response = request.HttpContext.Response;
                            ServerTimingHeader.SetHeaders(activity, response.Headers, (headers, key, value) =>
                            {
                                headers.TryAdd(key, value);
                            });
                        };
                    }
                })
                // Use AddSource to add your custom DiagnosticSource source names
                //.AddSource("My.Source.Name")
                .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
                .AddAspNetCoreInstrumentation()
                .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;
    }

    private static class ServerTimingHeader
    {
        private const string Key = "Server-Timing";
        private const string ExposeHeadersHeaderName = "Access-Control-Expose-Headers";

        public static void SetHeaders<T>(Activity activity, T carrier, Action<T, string, string> setter)
        {
            setter(carrier, Key, ToHeaderValue(activity));
            setter(carrier, ExposeHeadersHeaderName, Key);
        }

        private static string ToHeaderValue(Activity activity)
        {
            var sampled = ((int)activity.Context.TraceFlags).ToString("D2");
            return $"traceparent;desc=\"00-{activity.TraceId}-{activity.SpanId}-{sampled}\"";
        }
    }
}

Program.cs ファイルで作成したヘルパーを使用します:

var builder = WebApplication.CreateBuilder(args);
var app = builder
    .AddSplunkOpenTelemetry()
    .Build()

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

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

トラブルシューティング

__ ___ ___ _ ______ _____________ _____ ________ ___ ___ ___ ____ __ ___ ____ ____ __ ______ _____________ ______ ___ ___ ___ ____ __ ___ _________ _____

_________ __ ______ _____________ _____ _________

_________ __ ___________ _________ ___ ____ _____ _____

  • ___ _ ________ ___ ___ _______ _______ _________ _______ __ ______ ________

  • ____ ___ ______ ______________ ____ _____ _____ _______ __ ___________ ____ __________ _________ ___ ______ _________ __________ __ _____ ___ ____ _______