Docs » Splunk Observability Cloud でサポートされているインテグレーション » バックエンドアプリケーションをインストルメンテーションして、スパンを Splunk APM に送信する » Splunk Observability Cloud (OpenTelemetry) 用 .NET アプリケーションのインストルメンテーション » Splunk Observability Cloud 用 .NET Azure WebJobs をインストルメンテーションする

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

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

環境変数の定義 🔗

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

  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。自分のレルムを見つけるには、レルムについての注意 を参照してください。

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

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

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

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

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

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

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

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

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Exporter;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.ResourceDetectors.Azure;
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();

        // See https://github.com/open-telemetry/opentelemetry-dotnet-contrib/tree/main/src/OpenTelemetry.ResourceDetectors.Azure
        // for other types of Azure detectors
        var resourceDetector = new AppServiceResourceDetector();

        builder.Services.AddOpenTelemetry()
            .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())
                .ConfigureResource(cfg => cfg
                    .AddService(serviceName: serviceName, serviceVersion: "1.0.0")
                    .AddDetector(resourceDetector))
                .AddConsoleExporter()
                .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()
                .ConfigureResource(cfg => cfg
                    .AddService(serviceName: serviceName, serviceVersion: "1.0.0")
                    .AddDetector(resourceDetector))
                .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);
    }
}

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

var builder = new HostBuilder()
.ConfigureWebJobs(context =>
{
    context.AddSplunkOpenTelemetry();
})

SplunkFunctionAttribute は、定義されたすべての WebJobs 関数で使用します。関数に適切に属性を設定する方法の例を参照してください。

public class Functions
{
    [SplunkFunction]
    public void ProcessTimer([TimerTrigger("1/5 * * * * *")] TimerInfo timerInfo, ILogger logger)
    {
        logger.LogInformation("Hello World!");
    }
}

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

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

トラブルシューティング 🔗

Splunk Observability Cloudをご利用のお客様で、Splunk Observability Cloudでデータを確認できない場合は、以下の方法でサポートを受けることができます。

Splunk Observability Cloudをご利用のお客様

見込み客および無料トライアルユーザー様

  • Splunk Answers のコミュニティサポートで質問し、回答を得る

  • Splunk #observability ユーザーグループの Slack チャンネルに参加して、世界中の顧客、パートナー、Splunk 社員とのコミュニケーションを図る。参加するには、Get Started with Splunk Community マニュアルの チャットグループ を参照してください。

This page was last updated on 2024年09月18日.