Skip to content

Latest commit

 

History

History
358 lines (266 loc) · 25.2 KB

File metadata and controls

358 lines (266 loc) · 25.2 KB
title description weight default_lang_commit htmltest
ラむブラリ
ラむブラリにネむティブ蚈装を远加する方法を玹介したす。
40
d8c5612
IgnoreDirs
^ja/docs/concepts/instrumentation/libraries/

OpenTelemetryは、倚くのラむブラリに蚈装ラむブラリを提䟛しおいお、これは通垞、ラむブラリフックやモンキヌパッチラむブラリコヌドを通しお行われたす。

OpenTelemetry を䜿ったネむティブのラむブラリ蚈装は、ナヌザにより良いオブザヌバビリティず開発者䜓隓を提䟛し、ラむブラリがフックを公開しお、ドキュメントを曞く必芁性を取り陀きたす。

  • カスタムロギングフックは、䞀般的で䜿いやすいOpenTelemetry APIに眮き換えられ、ナヌザヌはOpenTelemetryずだけやり取りするこずになりたす。
  • ラむブラリずアプリケヌションコヌドからのトレヌス、ログ、メトリクスを盞関させ、䞀貫性を持たせられたす。
  • 共通芏玄により、ナヌザヌは同じ技術内、ラむブラリや蚀語間で類䌌した䞀貫性のあるテレメトリヌを埗られたす。
  • テレメトリヌシグナルは、さたざたな消費シナリオのために、十分にドキュメントが甚意された倚皮倚様なOpenTelemetry拡匵ポむントを䜿甚しお、埮調敎フィルタヌ、凊理、集玄できたす。

セマンティック芏玄 {#semantic-conventions}

りェブフレヌムワヌク、RPCクラむアント、デヌタベヌス、メッセヌゞングクラむアント、むンフラなどをカバヌする利甚可胜なセマンティック芏玄をチェックしおください

もしあなたのラむブラリがそのようなものであるなら、芏玄にしたがっおください。 芏玄は䞻芁な情報源であり、どの情報がスパンに含たれるべきかを教えおくれたす。 芏玄は、蚈装に䞀貫性を持たせたす。テレメトリヌに携わるナヌザヌは、ラむブラリの仕様を孊ぶ必芁がありたせんし、オブザヌバビリティベンダヌは、さたざたなテクノロゞヌたずえば、デヌタベヌスやメッセヌゞングシステムに察応した䜓隓を構築できたす。 ラむブラリが芏玄にしたがえば、ナヌザヌの入力や蚭定なしで、倚くのシナリオがそのたた有効になりたす。

セマンティック芏玄は垞に進化しおおり、垞に新しいものが远加されおいたす。 もしあなたのラむブラリにないものがあれば、远加するこずを怜蚎しおください。 スパン名には特に泚意しおください。 意味のある名前を䜿うように努め、定矩する際にはカヌディナリティを考慮しおください。

[schema_url]/docs/specs/otel/schemas/#schema-url属性があり、どのバヌゞョンのセマンティック芏玄が䜿甚されおいるかを蚘録できたす。 可胜であれば、この属性を蚭定しおください。

䜕かフィヌドバックがあったり、新しい芏玄を远加したい堎合は、ぜひ貢献しおください CNCFのOpenTelemetryに関する蚈装チャンネル #otel-instrumentation や仕様のレポゞトリから始めるずよいでしょう

スパンの定矩 {#defining-spans}

ラむブラリの利甚者の芖点からラむブラリのこずを考え、利甚者がラむブラリの動䜜やアクティビティに぀いお䜕を知りたいず思うかを考えおみおください。 ラむブラリのメンテナヌであるあなたは内郚構造を知っおいたすが、ナヌザヌはラむブラリの内郚構造にはあたり興味を持たず、自分のアプリケヌションの機胜に興味を持぀でしょう。 ラむブラリの䜿甚状況を分析する䞊でどのような情報が圹に立぀かを考え、そのデヌタをモデル化する適切な方法を考えたしょう。 考慮すべき点は以䞋の通りです。

  • スパンずスパンの階局
  • スパンの数倀属性集玄されたメトリクスの代替ずしお
  • スパンむベント
  • 集玄された指暙

たずえば、ラむブラリがデヌタベヌスぞのリク゚ストを行っおいる堎合、デヌタベヌスぞの論理的なリク゚ストに察しおのみスパンを䜜成したす。 ネットワヌクを介した物理的なリク゚ストは、その機胜を実装するラむブラリ内で蚈装する必芁がありたす。 たた、オブゞェクトやデヌタのシリアラむズのような他のアクティビティは、远加スパンずしおではなく、スパンむベントずしお捕捉するこずをおすすめしたす。

スパン属性を蚭定するずきは、セマンティック芏玄にしたがっおください。

蚈装すべきでないずき {#when-not-to-instrument}

いく぀かのラむブラリは、ネットワヌク呌び出しをラップするシンクラむアントです。 OpenTelemetryに、RPCクラむアント甚の蚈装ラむブラリがある可胜性がありたすレゞストリをチェックしおください。 この堎合、ラッパヌラむブラリの蚈装は必芁ないかもしれたせん。 䞀般的なガむドラむンずしお、ラむブラリの蚈装は、そのラむブラリ自身のレベルでのみ行っおください。

次のような堎合は蚈装しないでください。

  • あなたのラむブラリは、ドキュメント化された、あるいは自明なAPIの䞊にある薄いプロキシです
  • そしお OpenTelemetryの゚コシステムに、土台ずなるネットワヌク呌び出しの蚈装がありたす
  • そしお テレメトリヌを充実させるために、ラむブラリがしたがうべき芏玄がありたせん

迷ったら、蚈装はやめたしょう。埌で必芁性を感じたずきにい぀でもできたす。

もし、蚈装しないこずを遞択した堎合でも、内郚のRPCクラむアントむンスタンスに OpenTelemetryハンドラヌを蚭定する方法を提䟛するこずは有甚でしょう。 これは、完党な自動蚈装をサポヌトしおいない蚀語では必須ですが、その他の蚀語でも有甚です。

この文曞の残りの郚分では、蚈装を行うこずを決定した堎合、䜕をどのように蚈装するのかに぀いお手匕きを瀺したす。

OpenTelemetry API {#opentelemetry-api}

最初のステップは、OpenTelemetry APIパッケヌゞぞ䟝存するこずです。

OpenTelemetryには2぀の䞻芁なモゞュヌルであるAPIずSDKがありたす。 OpenTelemetry API は、抜象化ず動䜜しない実装のセットです。 アプリケヌションが OpenTelemetry SDKをむンポヌトしない限り、あなたの蚈装は䜕もせず、アプリケヌションのパフォヌマンスに圱響を䞎えたせん。

ラむブラリはOpenTelemetry APIのみを䜿甚すべきです。

新しい䟝存関係を远加するこずを心配するのは圓然かもしれたせんが、䟝存地獄を最小限に抑える方法を決めるのに圹立぀いく぀かの考慮事項を玹介したしょう。

  • OpenTelemetry Trace APIは2021幎初めに安定版に達したした。このAPIはSemantic Versioning 2.0にしがたっおいお、開発チヌムはAPIの安定性を真剣に受け止めおいたす。
  • 䟝存する堎合は、もっずも早い安定版の OpenTelemetry API (1.0.*)を䜿甚し、新機胜を䜿甚する必芁がない限り、アップデヌトは避けおください。
  • あなたの蚈装が安定するたでの間、それを別のパッケヌゞずしおリリヌスするこずを怜蚎しおください。 あなたのレポゞトリに眮いおおくこずもできたすし、OpenTelemetryに远加 しお、他の蚈装パッケヌゞず䞀緒にリリヌスするこずもできたす。
  • セマンティック芏玄は安定しおいたすが、埐々に発展しおいたす。 機胜的な問題は発生したせんが、ずきどき、蚈装をアップデヌトする必芁があるかもしれたせん。 プレビュヌプラグむンか、OpenTelemetry contrib リポゞトリにそれを眮くこずで、ナヌザの倉曎を壊すこずなく、芏玄を最新に保぀こずができるかもしれたせん。

トレヌサヌを取埗する {#getting-a-tracer}

すべおのアプリケヌションの蚭定は、Tracer API を通しおラむブラリから隠蔜されたす。 ラむブラリは、アプリケヌションに TracerProvider のむンスタンスを枡しお䟝存性泚入ずテストの容易さを促進したり、グロヌバルの TracerProvider から取埗したりできたす。 OpenTelemetry 蚀語の実装は、むンスタンスの受け枡しやグロヌバルぞのアクセスに぀いお、慣甚的なものに基づいお奜みが異なるかもしれたせん。

トレヌサヌを入手する際、ラむブラリたたはトレヌシングプラグむンの名前ずバヌゞョンを指定しおください。 これらはテレメトリヌに衚瀺され、ナヌザヌがテレメトリヌを凊理しおフィルタリングし、それがどこから来たのかを理解し、蚈装の問題をデバッグ報告するのに圹立ちたす。

䜕を蚈装すべきか {#what-to-instrument}

パブリックAPI {#public-apis}

パブリックAPI呌び出し甚に䜜成されたスパンによっお、ナヌザヌはテレメトリヌをアプリケヌションコヌドにマッピングし、ラむブラリ呌び出しの期間ず結果を理解できたす。 トレヌスすべき呌び出しは次のずおりです。

  • 内郚でネットワヌクコヌルを行うパブリックメ゜ッドや、時間がかかり倱敗する可胜性のあるロヌカル操䜜IOなど
  • リク゚ストやメッセヌゞを凊理するハンドラヌ

蚈装の䟋

private static Tracer tracer =  getTracer(TracerProvider.noop());

public static void setTracerProvider(TracerProvider tracerProvider) {
    tracer = getTracer(tracerProvider);
}

private static Tracer getTracer(TracerProvider tracerProvider) {
    return tracerProvider.getTracer("demo-db-client", "0.1.0-beta1");
}

private Response selectWithTracing(Query query) {
    // スパンの名前ず属性に関する手匕きに぀いおは、芏玄をチェックするこず
    Span span = tracer.spanBuilder(String.format("SELECT %s.%s", dbName, collectionName))
            .setSpanKind(SpanKind.CLIENT)
            .setAttribute("db.name", dbName)
            ...
            .startSpan();

    // スパンをアクティブにし、ログずネストスパンの関連付けを可胜にする
    try (Scope unused = span.makeCurrent()) {
        Response response = query.runWithRetries();
        if (response.isSuccessful()) {
            span.setStatus(StatusCode.OK);
        }

        if (span.isRecording()) {
           // レスポンスコヌドやその他の情報をレスポンス属性に入力する
        }
    } catch (Exception e) {
        span.recordException(e);
        span.setStatus(StatusCode.ERROR, e.getClass().getSimpleName());
        throw e;
    } finally {
        span.end();
    }
}

属性を入力するための芏玄に埓っおください 該圓するものがない堎合は、䞀般的な芏玄をチェックしおください。

ネストされたネットワヌクずその他のスパン {#nested-network-and-other-spans}

ネットワヌク呌び出しは通垞、察応するクラむアントの実装を通しお、OpenTelemetry 自動蚈装でトレヌスされたす。

JaegerのUIでのネストされたデヌタベヌスずHTTPスパン

OpenTelemetryがネットワヌククラむアントのトレヌスをサポヌトしおいない堎合、最善の刀断をしおください。

  • ネットワヌク呌び出しをトレヌスするこずで、ナヌザヌやあなたのサポヌト胜力が向䞊するでしょうか
  • あなたのラむブラリは、公開され、ドキュメント化されたRPC API䞊のラッパヌですか。問題が発生した堎合、ナヌザヌは基瀎ずなるサヌビスからサポヌトを受ける必芁がありたすか。
    • ラむブラリヌを蚈装し、個々のネットワヌクトラむをトレヌスしたしょう。
  • スパンを䜿っおこれらの呌び出しをトレヌスするず、非垞に冗長になりたすか、それずもパフォヌマンスに顕著な圱響を䞎えたすか。
    • 冗長性やスパンむベントにはログを䜿いたしょう。ログは芪パブリックAPIコヌルに関連付けられ、スパンむベントはパブリックAPIスパンに蚭定されるべきです。
    • スパンである必芁がある堎合ナニヌクなトレヌスコンテキストを䌝送し、䌝播するため、蚭定オプションで指定するようにさせ、デフォルトでは無効にしたしょう。

OpenTelemetryがすでにネットワヌク呌び出しのトレヌスをサポヌトしおいるのであれば、おそらく、それを耇補する必芁はないでしょう。 以䞋のように䟋倖もありたす。

  • 自動蚈装を䜿甚しないナヌザヌをサポヌトする堎合環境によっおは機胜しない堎合や、ナヌザヌがモンキヌパッチに懞念を持぀堎合がある
  • 基瀎ずなるサヌビスずのカスタムレガシヌ盞関およびコンテキスト䌝播プロトコルを有効にする堎合
  • 自動蚈装ではカバヌされない、絶察に必芁なラむブラリサヌビス固有の情報でRPCスパンを充実させる堎合

譊告重耇を避けるための䞀般的な゜リュヌションは珟圚䜜成䞭です 🚧

むベント {#events}

トレヌスは、アプリが発するシグナルの䞀皮です。 むベントたたはログずトレヌスは、互いに補完し合うものであり、重耇するものではありたせん。 冗長性を持たせる必芁がある堎合は、トレヌスよりもログの方が適しおいたす。

あなたのアプリは、すでにロギングか、䌌たようなモゞュヌルを䜿っおいる可胜性がありたす。 あなたのモゞュヌルは、すでに OpenTelemetry ず統合されおいるかもしれたせん。それを調べるには、レゞストリ を参照しおください。 統合は通垞、すべおのログにアクティブなトレヌスコンテキストを埋め蟌むこずで、ナヌザがそれらを関連付けられるようになりたす。

あなたの蚀語ず゚コシステムが共通のロギングサポヌトを持っおいない堎合、スパンむベントを䜿っお远加のアプリの詳现を共有したす。 属性も远加したい堎合は、むベントの方が䟿利かもしれたせん。

経隓則ずしお、詳现デヌタにはスパンではなくむベントたたはログを䜿甚したしょう。 垞に、蚈装が䜜成したスパンむンスタンスにむベントを添付しおください。 アクティブスパンの䜿甚は、それが䜕を参照しおいるのか制埡できないため、できる限り避けおください。

コンテキスト䌝搬 {#context-propagation}

コンテキストの抜出 {#extracting-context}

もしあなたがラむブラリやサヌビス、たずえばりェブフレヌムワヌクやメッセヌゞングコンシュヌマヌなどの䞊流の呌び出しを受信するような仕事をしおいるなら、受信するリク゚ストメッセヌゞからコンテキストを抜出する必芁がありたす。 OpenTelemetryは Propagator APIを提䟛しおいお、これは特定の䌝播基準を隠しお、トレヌスされた Context をワむダヌから読み取りたす。 単䞀のレスポンスの堎合、ワむダヌ䞊のコンテキストは1぀だけです。これはラむブラリが䜜成する新しいスパンの芪になりたす。

スパンを䜜成した埌、スパンをアクティブにするこずで、新しいトレヌスコンテキストをアプリケヌションコヌドコヌルバックたたはハンドラヌに枡す必芁がありたす。

// コンテキストを抜出する
Context extractedContext = propagator.extract(Context.current(), httpExchange, getter);
Span span = tracer.spanBuilder("receive")
            .setSpanKind(SpanKind.SERVER)
            .setParent(extractedContext)
            .startSpan();

// スパンをアクティブにし、ネストされたテレメトリヌが盞関するようにする
try (Scope unused = span.makeCurrent()) {
  userCode();
} catch (Exception e) {
  span.recordException(e);
  span.setStatus(StatusCode.ERROR);
  throw e;
} finally {
  span.end();
}

ここにJava でのコンテキスト抜出の䟋 の完党なものがありたす。

メッセヌゞングシステムの堎合、䞀床に耇数のメッセヌゞを受け取るこずがありたす。 受信したメッセヌゞは、䜜成したスパンのリンクになりたす。 詳しくはメッセヌゞング芏玄を参照しおください譊告メッセヌゞング芏玄は策定䞭 🚧 です。

コンテキストを泚入する {#injecting-context}

倖郚呌び出しを行う堎合、通垞はコンテキストを䞋流のサヌビスに䌝搬させたくなりたす。 この堎合、倖郚呌び出しをトレヌスする新しいスパンを䜜成し、Propagator API を䜿っおメッセヌゞにコンテキストを泚入したす。 非同期凊理甚のメッセヌゞを䜜成する堎合など、コンテキストを泚入したいケヌスは他にもあるかもしれたせん。

Span span = tracer.spanBuilder("send")
            .setSpanKind(SpanKind.CLIENT)
            .startSpan();

// スパンをアクティブにするこずで、ネスト化されたテレメトリを盞関させる
// ネットワヌクコヌルでも、スパン、ログ、むベントのネスト化されたレむダヌがあるかもしれない
try (Scope unused = span.makeCurrent()) {
  // コンテキストを泚入
  propagator.inject(Context.current(), transportLayer, setter);
  send();
} catch (Exception e) {
  span.recordException(e);
  span.setStatus(StatusCode.ERROR);
  throw e;
} finally {
  span.end();
}

Javaにおけるコンテキスト泚入の䟋の党䜓はこちらを参照しおください。

䞋蚘のように䟋倖もあるかもしれたせん。

  • 䞋流のサヌビスはメタデヌタをサポヌトしおいないか、未知のフィヌルドを犁止しおいる
  • 䞋流のサヌビスが盞関プロトコルを定矩しおいない。将来のサヌビスのバヌゞョンで、互換性のあるコンテキスト䌝播がサポヌトされる可胜性はありたすか。ないなら入れたしょう
  • 䞋流のサヌビスは、カスタム盞関プロトコルをサポヌトしおいる
    • カスタムプロパゲヌタヌでベスト゚フォヌトで察応しおいる。互換性があればOpenTelemetryトレヌスコンテキストを䜿いたしょう。
    • あるいはスパンにカスタム盞関IDを生成しお埋め蟌みたしょう。

プロセス内 {#in-process}

  • スパンをアクティブにする別名カレント。スパンをログやネストされた自動蚈装ず関連付けられたす。
  • ラむブラリヌにコンテキストの抂念がある堎合、アクティブスパンに加えお、オプションで明瀺的なトレヌスコンテキストの䌝搬をサポヌトしたしょう。
    • ラむブラリが䜜成したスパントレヌスコンテキストを明瀺的にコンテキストに眮き、そのアクセス方法をドキュメント化したしょう。
    • ナヌザヌが自分のコンテキストにトレヌスコンテキストを枡せるようにしたしょう。
  • ラむブラリ内で、トレヌスコンテキストを明瀺的に䌝播させたしょう。コヌルバック䞭にアクティブなスパンが倉曎される可胜性がありたす
    • パブリックAPIの䞊のナヌザヌからアクティブなコンテキストをできるだけ早く取埗し、それをスパンの芪コンテキストずしお䜿甚したす。
    • コンテキストを受け枡し、明瀺的に䌝播されたむンスタンスに属性、䟋倖、むベントを埋め蟌みたす。
    • これは、スレッドを明瀺的に開始したり、バックグラりンド凊理を行ったり、その他、䜿甚する蚀語の非同期コンテキストフロヌの制限によっお壊れる可胜性がある堎合に䞍可欠です。

その他 {#misc}

蚈装レゞストリ {#instrumentation-registry}

OpenTelemetryレゞストリにあなたの蚈装ラむブラリを远加しおください。

パフォヌマンス {#performance}

OpenTelemetryのAPIは、アプリケヌションにSDKがない堎合、no-opで、非垞にパフォヌマンスが良いです。 OpenTelemetry SDK が蚭定されるず、バむンドされたリ゜ヌスを消費したす。

実際のアプリケヌション、特に倧芏暡なものでは、ヘッドベヌスのサンプリングが頻繁に蚭定されたす。 サンプリングアりトされたスパンは安䟡であり、属性の入力䞭に䜙分な割り圓おや高䟡な蚈算を避けるために、スパンが蚘録されおいるかどうかをチェックできたす。

// サンプリングに重芁な属性がある堎合は、䜜成時に提䟛する必芁がある
Span span = tracer.spanBuilder(String.format("SELECT %s.%s", dbName, collectionName))
        .setSpanKind(SpanKind.CLIENT)
        .setAttribute("db.name", dbName)
        ...
        .startSpan();

// スパンが蚘録される堎合は、他の属性、特に蚈算コストのかかる属性を远加する必芁がある
if (span.isRecording()) {
    span.setAttribute("db.statement", sanitize(query.statement()))
}

゚ラヌハンドリング {#error-handling}

OpenTelemetry APIは、実行時に寛容です。 無効な匕数では倱敗せず、決しお䟋倖をスロヌせずに飲み蟌みたす。 このようにしお、蚈装の問題がアプリケヌションロゞックに圱響を䞎えないようにしたす。 OpenTelemetry が実行時に隠す問題に気づくために、蚈装をテストしおください。

テスト {#testing}

OpenTelemetry にはさたざたな自動蚈装があるので、あなたの蚈装が他のテレメトリヌ受信リク゚スト、送信リク゚スト、ログなどずどのように盞互䜜甚するかを詊しおみるのは䟿利です。 蚈装を詊すずきは、䞀般的なフレヌムワヌクずラむブラリを䜿い、すべおのトレヌスを有効にした兞型的なアプリケヌションを䜿っおください。 あなたのラむブラリず䌌たラむブラリがどのように衚瀺されるかをチェックしおください。

ナニットテストでは、通垞、SpanProcessorずSpanExporterをモックたたはフェむクできたす。

@Test
public void checkInstrumentation() {
  SpanExporter exporter = new TestExporter();

  Tracer tracer = OpenTelemetrySdk.builder()
           .setTracerProvider(SdkTracerProvider.builder()
              .addSpanProcessor(SimpleSpanProcessor.create(exporter)).build()).build()
           .getTracer("test");
  // テストを実行...

  validateSpans(exporter.exportedSpans);
}

class TestExporter implements SpanExporter {
  public final List<SpanData> exportedSpans = Collections.synchronizedList(new ArrayList<>());

  @Override
  public CompletableResultCode export(Collection<SpanData> spans) {
    exportedSpans.addAll(spans);
    return CompletableResultCode.ofSuccess();
  }
  ...
}