大規模なモノリシック アプリケーションでは、明確な所有権がないため、エラーの追跡と監視が効果的でないことがよくあります。このガイドでは、ドメイン注釈を通じて責任を割り当てる構造化されたアプローチを提案することで、この問題に対処します。
複数のチームで構成された大規模なモノリシック システムの効果的な監視を設定するのは難しい場合があります。明確な所有権がないと、エラー追跡は一般的なものになり、無視されることがよくあります。1 つの解決策は、オンコール エンジニアに監視アラームに応答するチームを特定させることです。ただし、より効率的なアプローチは、各ログと Datadog スパンにドメインとチームの情報を含めることです。
アプリケーションのさまざまな部分を担当するチームを追跡するために、ドメイン アノテーションと呼ばれるシステムを使用しています。ドメイン アノテーションは、アプリケーションのコードの各部分にラベルを付け、誰が何を担当しているかを明確に示します。これにより、責任の管理において明確な組織と説明責任が提供されます。
ドメイン アノテーションは、モノリシック アプリケーション内でチームの責任を追跡するための明確で体系的な方法を提供します。コードの一部にドメイン アノテーションをタグ付けすることで、次のことが可能になります。
効率的な監視と追跡可能性を確保するために、各 Web リクエストには適切なドメイン情報がタグ付けされます。これは、 DomainProvider
、 DomainSpanService
、 DomainMdcProvider
、 DomainHandlerInterceptor
などの複数のコンポーネントの連携によって実現されます。
次の図に、プロセスの概要を示します。
これらのコンポーネントの詳細な実装は共有ライブラリにカプセル化され、大規模なモノリシック アプリケーションで Web リクエストをタグ付けおよび監視するための再利用可能なソリューションを提供します。
クラス レベルでの所有権の定義は、ドメイン アノテーションを使用すると簡単です。トップレベルのアノテーションをメイン クラスに適用すると、所有権はそれらのクラス内のすべての詳細リソースに伝播します。各チームは、所有するクラスに適切なドメイン アノテーションのラベルを付けることができるため、すべてのメソッドにマークを付ける必要がなく、明確さと説明責任を確保できます。
複数のチームが 1 つのクラスのコードを所有しており、すぐにリファクタリングすることが適切でない場合は、クラス レベルのアノテーションよりも優先される異なるドメイン アノテーションを使用して個々のメソッドをマークできます。これにより、特定のメソッドを異なるチームに割り当てることができ、全体的な構造を複雑にすることなく柔軟性が得られます。
ドメイン アノテーションは非常に便利ですが、まれに使用できない場合もあります。たとえば、Quartz の AOP ロジックとドメイン アノテーションに使用される AOP ロジックが衝突したため、Quartz ジョブの作成がドメイン アノテーションとシームレスに機能しないという問題が発生しました。
直接注釈を付けることができないジョブとプロセスについては、ジョブ実装で DomainTagsService を直接使用しました。このアプローチにより、ジョブの実行ロジック内でドメイン タグを手動で追加できるようになりました。
以下は、DomainTagsService を Quartz ジョブに統合した例です。
final override fun execute(context: JobExecutionContext) { domainTagsService.invoke(domain) { withLoggedExecutionDetails(context, ::doExecute) } }
各チームに別々のサービスを用意すると、監視と所有権の面で大きな利点が得られますが、モノリスを分割するためのコストと労力が高く、追加の開発費用が発生する可能性があります。モノリスをモジュールに分割すると Gradle でビルド時間が短縮される可能性があることを考慮すると、多くの場合、モノレポを維持するのが最も効率的なソリューションになる可能性があります。
Datadog で各チームのアクティビティの監視を簡素化するために、異なるチームの範囲に人工サービス名を割り当てることができます。このアプローチにより、Datadog の監視ツールで各チーム専用のセクションが確保されます。管理するサービスが多数ある場合、人工サービス名を使用すると混乱を招く可能性がありますが、バックエンド サービスの数を制限すれば管理しやすくなります。これらの人工サービス名にプレフィックスを追加すると、Datadog セットアップの整理と明確さが維持され、異なるチームとその責任を区別しやすくなります。
スクリーンショットの代わりに図を使用しますか?? ワーカー/Webアプリはここでは意味がありません
ログに人工的なサービス名を使用すると、同じログ エントリが異なるサービスに表示される可能性があるため、混乱が生じる可能性があります。
たとえば、同じ認証サービスを使用する 2 つのエンドポイントを考えてみましょう。これらのエンドポイントに異なるドメインが注釈付けされている場合、認証ロジックは異なる人工サービスの下にログを生成します。ログは複数のサービス名で表示されるため、ログを調査するときに混乱が生じる可能性があります。この問題を回避するには、トレースで集約されるスパンにのみ人工サービス名を適用して、混乱を減らすことをお勧めします。
それは意味があるのでしょうか?意味がないと思います
この問題を視覚的に表すと次のようになります。
人工サービスを使用すると、APM トレースを操作できるだけでなく、長期間保存される Datadog Metrics でサービス別にフィルタリングできるため、長期間にわたる変更を追跡できます。
以下は、クエリで人工的なサービス名konsus-assets
を使用する Datadog のモニターのスクリーンショットです。
以下は、フィルターで人工的なサービス名konsus-assets
を使用する Datadog のダッシュボードのスクリーンショットです。
監視戦略で偽のサービスを活用することで、モノリシック アプリケーション内の各チームのアクティビティの可視性と説明責任を強化できます。このアプローチにより、チーム固有のモニターとダッシュボードの作成と維持のプロセスが簡素化され、Datadog での監視がより効果的かつ組織的になります。
ドメイン アノテーションは、Datadog でのモノリシック アプリケーションの監視を簡素化する簡単な方法を提供します。この戦略を実装することで、ログ、スパン、メトリックの管理性が向上し、監視設定が特定のチームに合わせたツールに変わります。これにより、説明責任と組織が改善され、アプリケーション全体のトラブルシューティングとパフォーマンス分析がより効果的かつ効率的に行えます。
DomainTagsService
などのサービスを直接使用することで、ドメイン固有の監視を維持できます。ドメインとチームを定義する
それはlibで変わります!!!
アプリケーション内のさまざまなドメインとチームを表す列挙型を作成します。
@Domain
は、クラスまたは関数に適用して、特定のドメイン値でマークできるアノテーションです。DomainValue
、それぞれがチームに関連付けられたさまざまなドメインを表す列挙型です。Team
、アプリケーションで作業しているさまざまなチームを表す列挙型です。 @Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) annotation class Domain(val value: DomainValue) enum class DomainValue(val team: Team) { USER_MANAGEMENT(Team.TEAM_A), PAYMENT_PROCESSING(Team.TEAM_B), NOTIFICATIONS(Team.TEAM_C) } enum class Team { TEAM_A, TEAM_B, TEAM_C }
クラス(および必要に応じてメソッド)に注釈を付ける
@Domain(DomainValue.USER_MANAGEMENT) class UserService { @Domain(DomainValue.PAYMENT_PROCESSING) fun processPayment() { ... } }
サポートされていないケースの処理
直接注釈を付けることができない場合は、 DomainTagsService
直接使用してロジックをラップします。
fun executeNotSupportedByAnnotationsLogic() { domainTagsService.invoke(domain) { executeLogic() } }
Datadogで監視
モニター、ダッシュボード、APMトレースのフィルタリングに人工的なサービスフィルターを使用する
これらの手順に従うことで、モノリシック アプリケーションにドメイン注釈を効果的に実装し、監視、説明責任、全体的な効率を向上させることができます。