New Relicでは、明確な傾向が見られます。つまり、ますます多くの顧客が、オブザーバビリティの標準としてOpenTelemetryを熱心に採用しているのです。この採用は、Azure Functionsなどのサーバーレス環境にも急速に拡大しています。この強力な組み合わせが一般的になるにつれて、それを正しく設定することが重要になります。このガイドでは、OpenTelemetryを使用してDotNet Azure Functionsを計装し、New Relicで完全なエンドツーエンドの可視性を実現する方法について詳しく説明します。

始める前に、関数アプリを2つの別々の部分として考えると簡単です。最初はこの概念が少し難しいと感じましたが、これが何時間も何日もかけて理解することなく、すぐに理解するのに役立つことを願っています。

  1. Azure Functions ホスト: トリガー(HTTP 要求など)を受け取り、ライフサイクルを管理し、コードを呼び出すランタイムです。独自のテレメトリーシステムが組み込まれており、従来は独自の Application Insights パイプラインがデフォルトになっています。
  2. .NET分離ワーカープロセス: これはProgram.csと関数コードです。別のプロセスで実行されます。構成したOpenTelemetry SDKはここに保存されます。

これは、OpenTelemetryをAzure Functions環境と統合できるようにするために非常に重要です。

FunctionsホストでOpenTelemetryを有効にする

Azureによれば、この機能は現在プレビュー段階にあるとのことです。現時点では、OpenTelemetry出力では HTTP、Service Bus、および Event Hubsトリガーのみがサポートされています。

Azure Functionsを使用したOpenTelemetryを使用すると、ホストプロセスと言語固有のワーカープロセスの両方から、ログ、メトリクス、およびトレースなどのテレメトリーデータを収集してエクスポートできます。このデータは、New NelicのエッジOTLP準拠エンドポイントなど、OpenTelemetry準拠の任意のエンドポイントに送信できます。

既定では、Functionsホストとワーカープロセスはテレメトリーコンテキストを自動的に共有しません。これは後で重要な概念になります。

telemetryMode設定は、Azure Functionsホストに動作を変更するように指示する、 host.jsonファイル内のフラグです。「 OpenTelemetry 」に設定すると、デフォルトのアプリケーション洞察のデフォルトテレメトリーパイプラインの使用を停止するよう、ホストに指示することになります。代わりに、関数呼び出しデータ(開始/停止時間やトリガーの詳細など)をOpenTelemetryシグナルとして発行します。

この設定がない場合、ワーカー内のOpenTelemetry SDKは、関数の実行自体を本質的に「無視」することになります。ワーカーコード内で独自のトレース全体を手動で呼び出すことはいつでも可能ですが、関数の呼び出しを表すメインの親スパンが失われ、トレースが壊れたり不完全になったりすることになります。

設定方法

// host.js

{
  "version": "2.0",
  "telemetryMode": "OpenTelemetry"
}

留意点: ホストに組み込まれたテレメトリーはアプリケーションコードに対する抽象化されたレイヤーであるため、呼び出し関連のルートエントリスパンの実際の関数ランタイムに関係なく、 telemetry.sdk.languageは常に「 dotnet」と表示され、書き込み時点では、telemtrty.sdk.versionは「1.9.0」と表示されることを理解しておくことが非常に重要です。

Java Azure Functionsに「telemetry.sdk.language = dotnet」と表示されます。

アプリでOpenTelemetryを有効にする

OpenTelemetryを使用してアプリケーションのワーカープロセスを計装するには、特定のOpenTelemetryのニーズに合わせた方法が必要です。

OpenTelemetry.ioレジストリには、利用可能なさまざまな計装が見つかります。

開始するには、次の前提条件パッケージをインストールします。
Microsoft.Azure.Functions.Worker.OpenTelemetry
OpenTelemetry.Extensions.Hosting
OpenTelemetry.Exporter.OpenTelemetryProtocol

このデモでは、基本的なHTTPクライアント( System.Net.Http.HttpClientSystem.Net.HttpWebRequestなど)を使用して、送信 HTTP 要求のメトリックとトレースを収集する方法を説明します。独自の関数のニーズに固有のその他のOpenTelemetryパッケージに加えて、 OpenTelemetry.Instrumentation.Httpも必要になります。

dotnet add package Microsoft.Azure.Functions.Worker.OpenTelemetry --version  1.1.0-preview6
dotnet add package OpenTelemetry.Extensions.Hosting 
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
dotnet add package OpenTelemetry.Instrumentation.Http

OpenTelemetry を構成する方法は、プロジェクトのスタートアップでIHostBuilder使用するか、.NET 分離ワーカーモデル拡張機能の v2.x で導入されたIHostApplicationBuilder使用するかによって異なることに注意してください。

この例では、アプリがIHostApplicationBuilderを使用していることを前提としています。

// Program.cs

using Microsoft.Azure.Functions.Worker.Builder;
 using Microsoft.Azure.Functions.Worker.OpenTelemetry;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Hosting;
 using OpenTelemetry;
 using OpenTelemetry.Trace;

 var builder = FunctionsApplication.CreateBuilder(args);

builder.ConfigureFunctionsWebApplication();

builder.Services.AddOpenTelemetry()
     // Azure Functions固有のOpenTelemetryデフォルトを適用する
    .UseFunctionsWorkerDefaults()
    .WithTracing(traceBuilder => traceBuilder.AddHttpClientInstrumentation())
    .UseOtlpExporter();

var app = builder.Build();

app.Run();

この例では、アプリがIHostBuilderを使用していることを前提としています。これは、ホストを構成および作成するためのより従来の方法です。

// Program.cs

using System.Diagnostics;
using System.Net.Http.Headers;
using Microsoft.Azure.Functions.Worker.OpenTelemetry;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using OpenTelemetry;
using OpenTelemetry.Trace;

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(
        services =>
        {
            services
                .AddOpenTelemetry()
                 // Azure Functions 固有の OpenTelemetry デフォルトを適用する                .UseFunctionsWorkerDefaults()
                .WithTracing(tracing => tracing.AddHttpClientInstrumentation());
                .UseOtlpExporter()
        }
    )
    .Build();

host.Run();

しかし、メトリクスについてはどうでしょうか?

OpenTelemetry SDKは、送信されるすべてのHttpClient要求に対して、標準のメトリックセットの収集を自動的に開始します。これらのメトリックは、公式のOpenTelemetryセマンティック規則によって定義されており、パフォーマンスと信頼性の監視に非常に役立ちます。

自動的に取得される主なメトリクスは次のとおりです。

  • http.client.request.duration (ヒストグラム)
    • 概要: これは最も一般的かつ重要なメトリクスです。これは、各送信HTTPリクエストが送信されてから応答が完全に受信されるまでにかかる時間を測定します。
  • http.client.active_requests(アップダウンカウンター)
    • 概要: 新しいリクエストが開始されるたびに増加し、リクエストが終了すると減少するカウンターです。

興味深い情報があります: New Relicは、これらのメトリックをAPMのセマンティック規則に合わせて自動的に正規化します。これにより、費用がかからずさまざまなメリットが得られます。

  • 強化された APM UI エクスペリエンス: 正規化されたデータが標準のNew Relic APM UIに入力され、New RelicまたはOpenTelemetryで計装されているかどうかに関係なく、すべてのアプリケーションにわたって APM データとゴールデンメトリクスの一貫したクエリが可能になります。
  • 非破壊プロセス: この自動化されたプロセスは非破壊的であり、元の純粋な OpenTelemetry ソースデータへの継続的なアクセスを保証します。

残りの部分を単純な関数にまとめます。

// HttpTrigger.cs

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace Newrelic.Function;

public class HttpTrigger
{
    private readonly ILogger<HttpTrigger> _logger;
    private static readonly HttpClient _httpClient = new HttpClient();

    public HttpTrigger(ILogger<HttpTrigger> logger)
    {
        _logger = logger;
    }

    [Function("HttpTrigger")]
    public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
    {
        try
        {
            await _httpClient.GetStringAsync("http://example.com");

            return new OkObjectResult("Azure Functionsへようこそ。外部呼び出しは成功しました。");
        }
        catch (HttpRequestException ex)
        {
            return new BadRequestObjectResult($"エラーが発生しました: {ex.Message}");
        }
    }
}

データエクスポータの設定

host.jsonファイルで「 telemetryMode": "OpenTelemetry」が設定されているかどうかに関係なく、テレメトリーデータの実際の保存先は特定の環境変数によって制御されます。これらの設定は、ホストとプロセスワーカーの両方にテレメトリーデータを送信する場所を指示します。

次のアプリケーション設定( local.settings.json )を構成します。

  • OTEL_EXPORTER_OTLP_ENDPOINT: "https://otlp.nr-data.net:4317"
  • OTEL_EXPORTER_OTLP_HEADERS: "api-key=YOUR_INGEST_KEY"
  • OTEL_SERVICE_NAME: "service.name"
  • OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE: “delta”

重要: APPLICATIONINSIGHTS_CONNECTION_STRING

OpenTelemetryデータをNew Relic OTLPエンドポイントにのみ送信したい場合は、すべてのアプリケーション設定を確認し、デフォルトのAPPLICATIONINSIGHTS_CONNECTION_STRING環境変数を削除することを検討してください。そうしないと、アプリケーション洞察を通じて追加のコストが発生する可能性があります。

データのサンプリング

サンプリングはデフォルトでは有効になっていないことに注意してください。アプリケーション洞察のライブメトリクスの場合、既定値は1秒あたり約5リクエストになります。ただし、OpenTelemetryエクスポーターを直接設定する場合、サンプリング動作が異なり、ニーズに合わせて明示的な設定が必要になります。

Azure Functions で「telemetryMode」を「OpenTelemetry」に設定すると、ホストレベルでのサンプリングは、ワーカープロセスで行われたサンプリングの決定によって制御されます。Functionsホストは独自の独立したサンプリングルールを適用しません。代わりに、OpenTelemetry SDKから伝播されたサンプリング決定を尊重します

さらなるサンプリング構成については、アプリケーション設定、具体的にはlocal.settings.jsonを参照してください。OTEL_TRACES_SAMPLERおよびOTEL_TRACES_SAMPLER_ARGに許容される値については、一般的なSDK設定ドキュメントを参照してください。

全体の表示内容

New Relicの分散トレーシング

ホストとワーカープロセスのログは、トレースコンテキストtrace.id / span.idで自動的にキャプチャされ、コンテキスト化されます。

動的サービスマップビューとヘルス

まとめ

  • Program.csは、OTelサービスの登録と、テレメトリーデータを処理および送信する方法に関する設定が含まれています。
  • host.json 、関数アプリによって生成されたテレメトリデータ(ログ、メトリック、トレース)がFunctionsホストで収集およびエクスポートされる方法を構成します。

完全なエンドツーエンドのトレースエクスペリエンスを実現するには、両方が必要になります。