> Source: https://www.ymotongpoo.com/works/oteps/trace/otep-0220/


# OTEP-0220: メッセージングシナリオにおけるスパン構造

本OTEPは、メッセージングシナリオに対して作成すべきスパンと、それらのスパン同士の関係性についての一貫した規約を定義することを目的としています。

本OTEPは[OTEP 0173](0173-messaging-semantic-conventions.md)に基づいています。
OTEP 0173は基本的な用語を定義し、メッセージング向けセマンティック規約によってサポートされるべきメッセージングシナリオを記述しています。
また、本OTEPは既存の[セマンティック規約](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/messaging/messaging-spans.md#context-propagation)で示され、[OTEP 0205](0205-messaging-semantic-conventions-context-propagation.md)で詳細に説明されているコンテキスト伝播の要件にも依拠しています。

* [用語](#terminology)
* [動機](#motivation)
* [メッセージの生成と消費の段階](#stages-of-producing-and-consuming-messages)
* [トレース構造](#trace-structure)
* [メッセージング向けセマンティック規約に対する変更・追加の提案](#proposed-changes-and-additions-to-the-messaging-semantic-conventions)
  - [操作名](#operation-name)
  - [スパン種別](#span-kind)
  - [スパンの関係性](#span-relationships)
* [未解決の問題](#open-issues)
* [今後の可能性](#future-possibilities)
  - [仲介者の計装](#intermediary-instrumentation)
* [先行技術](#prior-art)
* [例](#examples)

## 用語 {#terminology}

本文書で使用する用語については、[OTEP 173](0173-messaging-semantic-conventions.md#terminology)を参照してください。

## 動機 {#motivation}

分散システムを通過する個々のメッセージの経路を追跡することには、いくつかの課題があります。
メッセージングシステムは非同期のワークフローを可能にしますが、これはメッセージの生成と消費の段階が、かなりの時間差（数分、数時間、あるいは数日にわたることもあります）によって隔てられうることを意味します。
さらに、メッセージに触れるシステムのすべての部分にわたって一貫した計装が行われていることを前提にすることはできません。
プロデューサーとコンシューマーの段階を相関付けることは、その間でメッセージを転送する仲介者が計装されていない場合であっても求められます。
最後に、メッセージのバッチ化は、メッセージ処理ワークフローの様々な部分（バッチ発行、バッチ受信、バッチ処理、バッチ決済のいずれであっても）で発生する可能性があります。

こうした課題があるにもかかわらず、メッセージングシナリオの計装に対する要求は高いものです。
メッセージの異なる処理段階をモデル化するスパンを相関付けることに加えて、メッセージ処理のエンドツーエンドのレイテンシーを判定できることも求められます。
仲介者が計装されていない場合でも、これがプロデューサーとコンシューマーの段階の相関に影響を与えるべきではありません。
一方で、仲介者が計装されている場合には、仲介者の計装によるスパンはプロデューサーとコンシューマーの計装とシームレスに統合されるべきです。
この統合は、プロデューサーやコンシューマーの計装に対する変更を必要としてはならず、また、プロデューサーとコンシューマーのスパンの関係性に対して変更を引き起こしてもなりません。
さらに、ユーザーによる追加のカスタム計装を必要とすることなく、メッセージングSDKからすぐに使えるトレーシング計装を提供できることが望ましいです。

本OTEPは、メッセージングフローの各段階をモデル化するスパンを作成し、それらを相関付けるための一貫したガイドラインを提案することを目的としています。
これにより、上述の要求を、メッセージングシナリオや異なるメッセージングシステム全体を通じて一貫した方法で満たせるようにします。

## メッセージの生成と消費の段階 {#stages-of-producing-and-consuming-messages}

[OTEP 173](0173-messaging-semantic-conventions.md#scenarios)で既に説明したように、メッセージの生成と消費には5つの段階が関わります。

```mermaid
flowchart LR;
  subgraph PRODUCER
  direction TB
  CR[Create] --> PU[Publish]
  end
  subgraph INTERMEDIARY
  direction TB
  end
  subgraph CONSUMER
  direction TB
  RE[Receive] --> PR[Process]
  PR --> SE[Settle]
  end
  PU --> INTERMEDIARY
  INTERMEDIARY --> RE
  SE -..- INTERMEDIARY
```

1. プロデューサーがメッセージを作成します。
2. プロデューサーがメッセージを仲介者に発行します。
3. コンシューマーが仲介者からメッセージを受信します。
4. コンシューマーがメッセージを処理します。
5. コンシューマーは、メッセージが処理されたことを仲介者に通知することでメッセージを決済します。
   一部のケース（fire-and-forgetのシナリオ、またはブローカー上で決済が行われる場合）では、決済段階は存在しません。

以下のセマンティック規約は、これらの段階をスパンでどのようにモデル化するかを定義します。

## トレース構造 {#trace-structure}

### プロデューサー {#producer}

プロデューサーは、生成コンテキストをメッセージに注入する責任を負います。
後続のコンシューマーは、このコンテキストを使ってコンシューマー側のトレースをプロデューサー側のトレースにリンクします。
理想的には、各メッセージには一意で個別の生成コンテキストが割り当てられます。

しかし、コンテキストはスパンを参照しなければならないため、これはメッセージごとに個別のスパンを作成することを要求することになり、すべてのシナリオで実現可能とは限りません。
多数のメッセージが大きなバッチで生成・発行されるようなバッチ処理シナリオでは、メッセージ1つ1つに対してスパンを作成するとトレースが分かりづらくなってしまうため、望ましくありません。
したがって、計装ライブラリと自動計装は、既定ではメッセージごとに一意で個別のコンテキストを作成するべきですが（should）、この既定の動作を変更するための設定やその他の手段をサポートしてもよいでしょう（may）。
後者は、スパンの数を削減し、過度に冗長なトレースを避けるのに役立ちます。

各プロデューサーのシナリオに対して、"Publish" スパンを作成する必要があります。
このスパンは、仲介者への送信または発行のためにメッセージを提供する呼び出しまたは操作の期間を計測します。
この呼び出しまたは操作（および関連する "Publish" スパン）は、単一のメッセージを指すことも、複数のメッセージのバッチを指すこともできます。

生成コンテキストをメッセージに注入する方法には、以下の4通りのシナリオがあります。

1. ユーザーが、発行されるメッセージに対して、本文書で説明されているどのスパンも参照しないカスタムの生成コンテキストを提供します。
   これにより、ユーザーはカスタムのシナリオをモデル化する柔軟性を得られます。
   この場合、"Publish" スパン以外の追加のスパンを作成するべきではありません（should）。
   "Publish" スパンは、提供された生成コンテキストにリンクするべきです（should）。
2. メッセージに対してカスタムの生成コンテキストが提供されない場合、メッセージごとに "Create" スパンを作成し、そのコンテキストをメッセージに注入することが推奨されます。
   "Create" スパンは、"Publish" スパンの子として、"Publish" 操作の実行中に作成できます。
3. 上記のシナリオのバリエーションとして、"Create" スパンは "Publish" 操作とは独立して作成することもできます。
   例えば、メッセージが "Publish" 操作に渡される前に作成されるケースです。
   この場合、"Publish" スパンは "Create" スパンにリンクするべきです（should）。
4. 単一メッセージのシナリオ、またはスパンの数が多くなることが問題となる場合には、"Publish" スパンのコンテキストをメッセージに注入し、それを生成コンテキストとして扱うことができます。
   この場合、"Publish" スパン以外のスパンを作成するべきではありません（should）。

### コンシューマー {#consumer}

既存のセマンティック規約は、プロデューサー側のトレースとコンシューマー側のトレースを相関付けるために[「Process」スパンの使用を規定しています](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/messaging/messaging-spans.md#span-name)。
しかし、多くのユースケースでは "Process" スパンの存在に依拠することはできません。
専用の処理操作を特定できないケースや、処理が受信や配送とは異なるトレース内で行われるケースがあるためです。
さらに、処理操作はメッセージングライブラリやSDKによってカバーされることは少なく、多くの場合アプリケーションコード内で行われます。
"Processing" 操作に対して一貫してスパンを作成するには、アプリケーションの所有者がこれらの操作を正しく計装するための労力か、メッセージングライブラリやSDKの追加機能（例えば、処理コールバックのためのフックであり、これによりライブラリやSDKが計装を行えるようになるもの）のいずれかが必要になります。

特定のケースでは "Process" スパンを作成し、それらをコンシューマー側のトレースと相関付けることは可能ですが、これを一般的に要求できるものではありません。
したがって、プロデューサーとコンシューマーを相関付けるためには、（プッシュ型のAPIに対する）"Deliver" スパン、または（プル型のAPIに対する）"Receive" スパンの作成を要求する方が実現可能性が高いといえます。

#### プッシュ型シナリオの計装 {#instrumenting-push-based-scenarios}

プッシュ型のコンシューマーシナリオでは、メッセージの配送はアプリケーションコードによって開始されるものではありません。
代わりに、コールバックまたはハンドラーが登録され、メッセージングSDKによって呼び出され、メッセージがアプリケーションに転送されます。

"Deliver" スパンは、そのようなコールバックまたはハンドラーの呼び出しをカバーし、そのそれぞれの呼び出しによって転送されるすべてのメッセージの生成コンテキストにリンクするべきです（should）。

#### プル型シナリオの計装 {#instrumenting-pull-based-scenarios}

プル型のコンシューマーシナリオでは、メッセージはアプリケーションコードによって能動的にリクエストされます。
これは通常ブロッキング呼び出しを伴い、完了時に0個以上のメッセージを返します。

"Receive" スパンは、そのような呼び出しをカバーし、そのそれぞれの呼び出しによって転送されるすべてのメッセージの生成コンテキストにリンクするべきです（should）。
これをイディオマティックな方法で実現するためには、スパン作成後にリンクを追加できるようにする必要がありますが、これは現時点ではサポートされていません（[未解決の問題](#open-issues)を参照）。

#### プッシュ型・プル型双方に共通する一般的な考慮事項 {#general-considerations-for-both-push-based-and-pull-based-scenarios}

"Deliver" または "Receive" スパンによってモデル化される操作は、厳密には仲介者からメッセージを受信することを指すのではなく、アプリケーションが処理のためにメッセージを受け取ることを指します。
メッセージが仲介者から取得され、一度にアプリケーションに転送される場合、操作全体が1つの "Deliver" または "Receive" スパンでカバーされることがあります。
しかし、ライブラリやSDKは仲介者からメッセージを事前にフェッチしてキャッシュし、後になってからアプリケーションにメッセージを転送することがあります。
この場合、事前フェッチとキャッシュの操作は "Deliver" または "Receive" スパンでカバーするべきではありません（should not）。

"Deliver" または "Receive" によってカバーされる操作は、0個のメッセージ（処理可能なメッセージがないことをアプリケーションに通知する場合など）、1個のメッセージ、または複数のメッセージ（メッセージのバッチ）を転送することがあります。
"Deliver" と "Receive" スパンは、転送されるメッセージの生成コンテキストにリンクするべきであり（should）、したがって、これらのスパンは0個、1個、または複数のプロデューサー側スパンにリンクすることになります。

単一メッセージのシナリオで、かつ "Deliver" または "Receive" スパンが新しいトレースのルートスパンになる場合には、生成コンテキストをリンクとして追加することに加えて、それらの操作の親として使用してもよいでしょう（may）。
単一メッセージの操作を同一のトレース内に保つことで、ユーザー体験を大きく向上させることができます。

#### 決済 {#settlement}

メッセージはさまざまな方法で決済されます。

* 仲介者がメッセージをコンシューマーに送信した時点で決済します。
  コンシューマー側で決済操作は発生しません。
* コンシューマーは、仲介者からの確認応答を待たずにメッセージを決済します。
* コンシューマーは、仲介者からの確認応答を待ってメッセージを決済します。
  これはコンシューマーと仲介者の間の往復のやり取りを伴います。

コンシューマー側の決済操作は、ユーザーによって手動でトリガーされることもあれば、コールバックの戻り値に基づいてメッセージングSDKによって自動的にトリガーされることもあります。

コンシューマー側で発生するすべての決済操作（at-least-onceおよびexactly-once）に対して、"Settle" スパンを作成するべきです（should）。
SDKは、場合によっては、コールバックを介してメッセージが配送されるプッシュ型シナリオにおいて、メッセージを自動的に決済します。

"Settle" スパンは、可能な場合には、決済されるメッセージの生成コンテキストにリンクするべきです（should）。

コンシューマー側で決済操作を伴わない決済シナリオに対しては、決済スパンを作成するべきではありません（should not）。

## メッセージング向けセマンティック規約に対する変更・追加の提案 {#proposed-changes-and-additions-to-the-messaging-semantic-conventions}

このセクションは、[トレース構造](#trace-structure)セクションで説明した内容の、簡潔かつ規範的な定義を含みます。
以下の各サブセクションはセマンティック規約にマージされることを想定しており、本OTEPの[トレース構造](#trace-structure)セクションにおける詳細な説明は、解説および将来の参考資料としての役割を果たします。

### 操作名 {#operation-name}

これらのセマンティック規約では、メッセージに関連する以下の操作をカバーします。

| Operation name | Description |
| -------------- | ----------- |
| `publish` | 1つ以上のメッセージが、仲介者への発行のために提供されます。 |
| `create` | メッセージが作成されます。 |
| `receive` | 1つ以上のメッセージがコンシューマーによってリクエストされます。 |
| `deliver` | 1つ以上のメッセージがコンシューマーに渡されます。 |
| `settle` | 1つ以上のメッセージが決済されます。 |

これらの各操作の詳細については、[トレース構造についてのセクション](#trace-structure)を参照してください。

### スパン種別 {#span-kind}

[スパン種別](../../specification/trace/api.md#spankind)は、スパンが記述する操作に基づき、以下の表に従って設定されるべきです（SHOULD）。

| Operation name | Span kind |
| -------------- | --------- |
| `publish` | `PRODUCER`。ただし `create` スパンが存在しない場合。 |
| `create` | `PRODUCER` |
| `receive` | `CONSUMER` |
| `deliver` | `CONSUMER` |
| `settle` | （下記参照） |

`settle` スパンの種別は、[スパン種別に関する一般的な仕様](../../specification/trace/api.md#spankind)に従って設定されるべきです。
例えば、`settle` スパンが仲介者への同期呼び出しをモデル化する場合には `CLIENT` に設定するべきです。

この表に従ってスパン種別を設定することで、コンシューマーとプロデューサーの間のスパンリンクが、常にプロデューサー側の `PRODUCER` スパンとコンシューマー側の `CONSUMER` スパンの間に存在することが保証されます。
これにより、分析ツールは追加のセマンティックなヒントを必要とせずに、リンクされたトレースを解釈できるようになります。

### スパンの関係性 {#span-relationships}

#### プロデューサースパン {#producer-spans}

仲介者への送信または発行のためにメッセージを提供する操作に対しては、"Publish" スパンを作成するべきです（SHOULD）。
単一の "Publish" スパンは、単一のメッセージに対応することも、（バッチでメッセージを提供する場合には）複数のメッセージに対応することもできます。
"Create" スパンは作成してもよいでしょう（MAY）。
単一の "Create" スパンは単一のメッセージのみに対応するべきです（SHOULD）。
"Create" スパンは、関連する "Publish" スパンの子であるか、それにリンクされるべきです（SHOULD）。

メッセージに対して "Create" スパンが存在する場合、そのコンテキストはメッセージに注入されるべきです（SHOULD）。
"Create" スパンが存在しない場合、関連する "Publish" スパンのコンテキストがメッセージに注入されるべきです（SHOULD）。

#### コンシューマースパン {#consumer-spans}

##### プッシュ型シナリオ {#push-based-scenarios}

アプリケーションコードによって開始されない、メッセージをアプリケーションに渡す操作に対しては、"Deliver" スパンを作成するべきです（SHOULD）。

##### プル型シナリオ {#pull-based-scenarios}

アプリケーションコードによって開始される、メッセージをアプリケーションに渡す操作に対しては、"Receive" スパンを作成するべきです（SHOULD）。

##### 一般的な考慮事項 {#general-considerations}

呼び出し元に転送されず、メッセージングライブラリやSDKによって事前フェッチまたはキャッシュされるメッセージに対しては、"Deliver" または "Receive" スパンを作成してはなりません（MUST NOT）。

単一の "Deliver" または "Receive" スパンは、単一のメッセージに対応することも、（メッセージが処理のためにバッチで渡される場合には）複数のメッセージに対応することも、（メッセージが受信されなかったことが通知される場合には）メッセージに全く対応しないこともできます。
対応する各メッセージについて、"Deliver" または "Receive" スパンは、そのメッセージの生成コンテキストにリンクするべきです（SHOULD）。
さらに、可能であれば、生成コンテキストを "Deliver" または "Receive" スパンの親として設定してもよいでしょう（MAY）。

#### 決済スパン {#settlement-spans}

手動または自動でトリガーされるすべての決済操作に対して、"Settle" スパンを作成するべきです（SHOULD）。
単一の "Settle" スパンは、単一のメッセージに対応することも、（メッセージが決済のためにバッチで渡される場合には）複数のメッセージに対応することもできます。
対応する各メッセージについて、"Settle" スパンはそのメッセージの生成コンテキストにリンクしてもよいでしょう（MAY）。

## 未解決の問題 {#open-issues}

本文書で提案された変更をメッセージング向けセマンティック規約に完全に統合するには、仕様にいくつかの追加と明確化が必要です。
それらを本セクションに列挙します。

* [open-telemetry/opentelemetry-specification#454](https://github.com/open-telemetry/opentelemetry-specification/issues/454)
  本文書で説明したプル型の "Receive" 操作を計装するには、スパンが作成された後にそのスパンにリンクを追加できるようにする必要があります。
  その理由は、"Receive" 操作の開始時点ではすべてのメッセージが揃っているとは限らないため、関連するコンテキストへのリンクをスパンの開始時点で追加できないからです。
* [open-telemetry/opentelemetry-specification#2176](https://github.com/open-telemetry/opentelemetry-specification/issues/2176)
  生成コンテキストが付与されていないメッセージをバッチの一部として消費する場合でも、無効なコンテキストを指すリンクの一部として、関連するメッセージ固有の属性を取得できることは有用です。
  しかし、仕様によれば、無効なコンテキストを指すリンクは無視される可能性があります。
  リンク上でメッセージ固有の属性を一貫して報告するためには、無効なコンテキストへのリンクを許可しサポートする必要があります。
* [open-telemetry/opentelemetry-specification#3172](https://github.com/open-telemetry/opentelemetry-specification/issues/3172)
  現在、仕様ではプロデューサーとコンシューマーのスパン間の関係をリンクによってモデル化できるかどうかが不明確であり、文言は親子関係であるべきことを示唆しています。
  仕様の文言は、これがリンクでもありうることを明確にする必要があります。
* 本OTEPは、必須とされているリンクの作成に加えて、プロデューサーとコンシューマーのスパン間に親子関係を作成することも許可しています。
  しかし、場合によっては、この親子関係を追加することが望ましくない結果（例えば、バッチが発行されるシナリオにおいてトレースが肥大化するなど）につながる可能性があります。
  本OTEPで提案された変更がセマンティック規約にマージされる際には、これらのシナリオにさらに注意を払う必要があります。

## 今後の可能性 {#future-possibilities}

### 仲介者の計装 {#intermediary-instrumentation}

仲介者の計装は本文書の規約で直接カバーされているわけではありませんが、プロデューサーやコンシューマーの計装とうまく統合できる形で、仲介者の計装を容易に追加できるように、提案された規約を拡張可能にしておくことは確かに必要です。

以下の図は、仲介者の計装をどのように追加できるかの例を示しています。
すべてのシナリオを通じてプロデューサーとコンシューマーが一貫してリンクによって相関付けられているという事実は、仲介者の計装を追加するための最大限の柔軟性を提供します。

```mermaid
flowchart LR;
  subgraph PRODUCER
  direction TB
  PM1[Publish m1]
  PM2[Publish m2]
  end
  subgraph CONSUMER
  direction TB
  D[Deliver]-.-PRM1[Process m1]
  D-.-PRM2[Process m2]
  end
  PM1-. link .-D;
  PM2-. link .-D;
  PM1-- parent -->INTERMEDIARY;
  PM2-- parent -->INTERMEDIARY;
  INTERMEDIARY-- parent -->D;

  classDef normal fill:green
  class PM1,PM2,D normal
  classDef additional opacity:0.4
  class INTERMEDIARY,PRM1,PRM2 additional
  linkStyle 0,1,4,5,6 opacity:0.4
  linkStyle 2,3 color:green,stroke:green
```

### "Process" 操作の計装 {#instrumentation-of-process-operations}

本OTEPは、あらゆるメッセージングシナリオに何らかの形で適用できる一貫した規約のセットに焦点を当てており、それらは何らかの形の "Publish" や "Create"、"Deliver" や "Receive"、そして "Settle" 操作をカバーしています。
これらの操作は、すべてのメッセージングシナリオを通じて共通の特性を共有しています。

一方で、"Process" 操作の特性は、メッセージングシナリオによってかなり異なります。
さらに、そうした操作に対して自動計装を提供することは、多くの場合困難、あるいは不可能でさえあります。
これらの理由から、"Process" 操作に対する規約は本OTEPのスコープ外とされました。

しかし、"Process" 操作の計装についても何らかの一貫性を達成したいという関心が、多方面から表明されています。
そのため、[open-telemetry/semantic-conventions#657](https://github.com/open-telemetry/semantic-conventions/issues/657)は、本OTEPが築く基盤の上に構築される、"Process" 操作のための規約を定義する取り組みをカバーしています。

## 先行技術 {#prior-art}

既存のメッセージング向けセマンティック規約には、[例のリスト](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/messaging/messaging-spans.md#examples)が含まれており、それぞれが与えられたメッセージングシナリオに対して作成されるべき属性と関係性を持つスパンを指定しています。

メッセージングシステムの計装を書く多くのユーザーが、それらの例について混乱を表明しました。
これらの例で定義されているスパン間の関係性は、十分に文書化された一貫したパターンに従っておらず、与えられた例のいずれにも当てはまらないユースケースを持つユーザーにとって混乱を招きます。
計装の作者は、一連の例から規約を推測するのではなく、一貫した規約のセットに頼ることができるべきです。

## 例 {#examples}

このセクションには、上記で概説した規約の使用を示す例のリストが含まれています。
緑色のボックスは、これらの規約に準拠するために存在することが必須とされるスパンを示します。
その他のボックスは、規約によって必須ともカバーもされていませんが、メッセージングスパンをトレースフロー全体にどのように統合できるかを理解する助けとなることを期待して示されているスパンです。
実線の矢印は親子関係を示し、点線の矢印はリンク関係を示します。

### プッシュ型シナリオ {#push-based-scenarios}

プロデューサーが単一のメッセージを作成・発行し、その単一のメッセージがコンシューマーに配送される場合。

```mermaid
flowchart LR;
  subgraph PRODUCER
  PM1[Publish m1]
  end
  subgraph CONSUMER
  DM1[Deliver m1]
  end
  PM1-. link .-DM1;

  classDef normal fill:green
  class PM1,DM1 normal
  linkStyle 0 color:green,stroke:green
```

単一のメッセージを消費する場合、"Deliver" スパンは生成コンテキストの子として親付けすることができます。

```mermaid
flowchart LR;
  subgraph PRODUCER
  PM1[Publish m1]
  end
  subgraph CONSUMER
  DM1[Deliver m1]
  end
  PM1-. link .-DM1;
  PM1-- parent -->DM1;

  classDef normal fill:green
  class PM1,DM1 normal
  linkStyle 0,1 color:green,stroke:green
```

コンシューマー側の決済操作に対してスパンを追加することが推奨されます。
これらのスパンは、手動で作成することも自動計装によって作成することもできます。

```mermaid
flowchart LR;
  subgraph PRODUCER
    direction TB
    PM1[Publish m1]
  end
  subgraph CONSUMER
    direction TB
    DM1[Deliver m1]-->S1[Settle m1]
  end
  PM1-. link .-DM1;
  PM1-. link .-S1;

  classDef normal fill:green
  class PM1,DM1,S1 normal
  linkStyle 0,1,2 color:green,stroke:green
```

プロデューサーがメッセージのバッチを発行し、単一のメッセージがコンシューマーに配送される場合。
"Create" スパンは "Publish" 操作の一部として作成されます。

```mermaid
flowchart LR;
  subgraph PRODUCER
  direction TB
  P[Publish]-->C1[Create m1]
  P-->C2[Create m2]
  end
  subgraph CONSUMER
  direction TB
  DM1[Deliver m1]
  DM2[Deliver m2]
  end
  C1-. link .-DM1;
  C2-. link .-DM2;

  classDef normal fill:green
  class P,C1,C2,DM1,DM2 normal
  linkStyle 0,1,2,3 color:green,stroke:green
```

単一のメッセージを消費する場合、"Deliver" スパンは生成コンテキストの子として親付けすることができます。

```mermaid
flowchart LR;
  subgraph PRODUCER
  direction TB
  P[Publish]-->C1[Create m1]
  P-->C2[Create m2]
  end
  subgraph CONSUMER
  direction TB
  DM1[Deliver m1]
  DM2[Deliver m2]
  end
  C1-. link .-DM1;
  C2-. link .-DM2;
  C1-- parent -->DM1;
  C2-- parent -->DM2;

  classDef normal fill:green
  class P,C1,C2,DM1,DM2 normal
  linkStyle 0,1,2,3,4,5 color:green,stroke:green
```

プロデューサーが単一のメッセージを作成・発行し、それがメッセージのバッチの一部としてコンシューマーに配送される場合。

```mermaid
flowchart LR;
  subgraph PRODUCER
  direction TB
  PM1[Publish m1]
  PM2[Publish m2]
  end
  subgraph CONSUMER
  direction TB
  D[Deliver]-.-PRM1[Process m1]
  D-.-PRM2[Process m2]
  end
  PM1-. link .-D;
  PM2-. link .-D;

  classDef normal fill:green
  class PM1,PM2,D normal
  classDef additional opacity:0.4
  class PRM1,PRM2 additional
  linkStyle 0,1 opacity:0.4
  linkStyle 2,3 color:green,stroke:green
```

### プル型シナリオ {#pull-based-scenarios}

プロデューサーが単一のメッセージを作成・発行し、その単一のメッセージがコンシューマーに配送される場合。
"Create" スパンは "Publish" 操作とは独立して作成されます。

```mermaid
flowchart LR;
  subgraph PRODUCER
  direction TB
  A[Ambient]-- parent -->CM1[Create m1]
  A-- parent -->CM2[Create m2]
  A-- parent -->P[Publish]
  end
  subgraph CONSUMER
  direction TB
  RM1[Receive m1]
  RM2[Receive m2]
  end
  CM1-. link .-RM1;
  CM2-. link .-RM2;
  CM1-. link .-P;
  CM2-. link .-P;

  classDef normal fill:green
  class CM1,CM2,P,RM1,RM2 normal
  classDef additional opacity:0.4
  class A additional
  linkStyle 0,1,2 opacity:0.4
  linkStyle 3,4,5,6 color:green,stroke:green
```

"Create" スパンが "Publish" 操作の一部として作成される場合。

```mermaid
flowchart LR;
  subgraph PRODUCER
  direction TB
  P[Publish]-- parent -->CM1[Create m1]
  P-- parent -->CM2[Create m2]
  end
  subgraph CONSUMER
  direction TB
  RM1[Receive m1]
  RM2[Receive m2]
  end
  CM1-. link .-RM1;
  CM2-. link .-RM2;

  classDef normal fill:green
  class P,CM1,CM2,RM1,RM2 normal
  linkStyle 0,1,2,3 color:green,stroke:green
```

プロデューサーが単一のメッセージを作成・発行し、それがメッセージのバッチの一部としてコンシューマーに配送される場合。
単一メッセージに対する "Process" スパンは作成できますが、これらの規約ではカバーされません。

```mermaid
flowchart LR;
  subgraph PRODUCER
  direction TB
  PM1[Publish m1]
  PM2[Publish m2]
  end
  subgraph CONSUMER
  direction TB
  A[Ambient]-- parent -->R[Receive]
  A-.-PRM1[Process m1]
  A-.-PRM2[Process m2]
  end
  PM1-. link .-R;
  PM2-. link .-R;

  classDef normal fill:green
  class PM1,PM2,R normal
  classDef additional opacity:0.4
  class A,PRM1,PRM2 additional
  linkStyle 0,1,2 opacity:0.4
  linkStyle 3,4 color:green,stroke:green
```

決済操作に対してスパンを追加することが推奨されます。
これらのスパンは、手動で作成することも自動計装によって作成することもできます。

```mermaid
flowchart LR;
  subgraph PRODUCER
  direction TB
  PM1[Publish m1]
  PM2[Publish m2]
  end
  subgraph CONSUMER
  direction TB
  A[Ambient]-- parent -->R[Receive]
  A-- parent -->SM1[Settle m1]
  A-- parent -->SM2[Settle m2]
  end
  PM1-. link .-R;
  PM2-. link .-R;
  PM1-. link .-SM1;
  PM2-. link .-SM2;

  classDef normal fill:green
  class PM1,PM2,SM1,SM2,R normal
  classDef additional opacity:0.4
  class A additional
  linkStyle 0,1,2 opacity:0.4
  linkStyle 3,4,5,6 color:green,stroke:green
```

