サンプリング オーバーライド - Azure Monitor Application Insights for Java
Note
サンプリング オーバーライド機能の一般提供は 3.5.0 以降です。
サンプリング オーバーライドを使用すると、既定のサンプリング率をオーバーライドできます。次に例を示します。
- ノイズの多い正常性チェックでは、サンプリング率を 0 (または何らかの小さい値) に設定します。
- ノイズの多い依存関係呼び出しでは、サンプリング率を 0 (または何らかの小さい値) に設定します。
- 重要な要求の種類 (
/login
など) では、既定のサンプリングが低く構成されている場合でも、サンプリング率を 100 に設定します。
用語
サンプリング オーバーライドについて学習する前に、"スパン" という用語を理解しておく必要があります。 スパンは、次を表す一般的な用語です。
- 着信要求。
- 送信依存関係 (別のサービスへのリモート呼び出しなど)。
- プロセス内の依存関係 (サービスのサブコンポーネントによって実行される操作など)。
サンプリング オーバーライドに関しては、次のスパンのコンポーネントが重要です。
- 属性
スパン属性は、指定された要求または依存関係の標準とカスタムの両方のプロパティを表します。
作業の開始
開始するには、applicationinsights.json という名前の構成ファイルを作成します。 これを、applicationinsights-agent-*.jar と同じディレクトリに保存します。 次に示すテンプレートを使用します。
{
"connectionString": "...",
"sampling": {
"percentage": 10,
"overrides": [
{
"telemetryType": "request",
"attributes": [
...
],
"percentage": 0
},
{
"telemetryType": "request",
"attributes": [
...
],
"percentage": 100
}
]
}
}
しくみ
telemetryType
(Application Insights 3.4.0 では telemetryKind
) は、request
、dependency
、trace
(ログ)、または exception
のいずれかである必要があります。
スパンが開始されると、いずれかのサンプリング オーバーライドが一致するかどうかを確認するために、その時点で存在するスパンと属性が使用されます。
一致は strict
か regexp
です。 正規表現の一致は、属性値全体に対して実行されます。そのため、その中のどこかに abc
が含まれる値に一致することが望まれる場合、.*abc.*
を使用する必要があります。
1 つのサンプリング オーバーライドに複数の属性条件を指定できます。その場合、そのすべてが一致対象のサンプリング オーバーライドに一致している必要があります。
いずれかのサンプリング オーバーライドが一致する場合は、そのサンプリング率を使用してスパンをサンプリングするかどうかを決定します。
一致する最初のサンプリング オーバーライドのみが使用されます。
サンプリング オーバーライドが一致しない場合:
- そのスパンがトレースの最初のスパンである場合は、最上位のサンプリング構成が使用されます。
- そのスパンがトレースの最初のスパンでない場合は、親のサンプリングの決定が使用されます。
サンプリングに使用できるスパン属性
OpenTelemetry スパン属性は自動的に収集され、OpenTelemetry セマンティック規則に基づいています。
プログラムでスパン属性を追加し、サンプリングに使用することもできます。
Note
アプリケーションの Application Insights Java によってキャプチャされた属性の正確なセットを確認するには、自己診断レベルを debug に設定し、テキスト "exporting span" で始まるデバッグ メッセージを探します。
Note
サンプリングに使用できるのはスパンの開始時に設定された属性のみであり、後でキャプチャされる http.response.status_code
や要求期間などの属性は、OpenTelemetry Java 拡張機能を使用してフィルター処理できます。 要求の期間に基づいてスパンをフィルター処理する拡張機能のサンプルを次に示します。
Note
テレメトリ プロセッサで追加された属性は、サンプリングには使用できません。
ユース ケース
正常性チェックのテレメトリ収集を抑制する
この例では、/health-checks
へのすべての要求に対するテレメトリの収集が抑制されています。
この例では、通常は /health-checks
で収集されるダウンストリームのスパン (依存関係) の収集も抑制されています。
{
"connectionString": "...",
"sampling": {
"overrides": [
{
"telemetryType": "request",
"attributes": [
{
"key": "url.path",
"value": "/health-check",
"matchType": "strict"
}
],
"percentage": 0
}
]
}
}
ノイズの多い依存関係呼び出しのテレメトリ収集を抑制する
この例では、すべての GET my-noisy-key
redis 呼び出しに対するテレメトリの収集が抑制されています。
{
"connectionString": "...",
"sampling": {
"overrides": [
{
"telemetryType": "dependency",
"attributes": [
{
"key": "db.system",
"value": "redis",
"matchType": "strict"
},
{
"key": "db.statement",
"value": "GET my-noisy-key",
"matchType": "strict"
}
],
"percentage": 0
}
]
}
}
重要な要求の種類のテレメトリを 100% 収集する
この例では、/login
のテレメトリが 100% 収集されます。
ダウンストリームのスパン (依存関係) は親のサンプリング決定を尊重するため (ダウンストリームのスパンのサンプリング オーバーライドは存在しません)、すべての '/login' 要求についても収集されます。
{
"connectionString": "...",
"sampling": {
"percentage": 10
},
"sampling": {
"overrides": [
{
"telemetryType": "request",
"attributes": [
{
"key": "url.path",
"value": "/login",
"matchType": "strict"
}
],
"percentage": 100
}
]
}
}
SQL 依存関係呼び出しを抑制するためにスパン属性を公開する
この例では、ノイズの多い SQL 呼び出しを抑制する使用可能な属性の検索について段階的に説明します。 次のクエリは、過去 30 日間のさまざまな SQL 呼び出しと、関連するレコード数を示しています。
dependencies
| where timestamp > ago(30d)
| where name == 'SQL: DB Query'
| summarize count() by name, operation_Name, data
| sort by count_ desc
SQL: DB Query POST /Order DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar; 36712549
SQL: DB Query POST /Receipt DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar; 2220248
SQL: DB Query POST /CheckOutForm DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar; 554074
SQL: DB Query GET /ClientInfo DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar; 37064
上記の結果から、すべての操作が data
フィールドで同じ値 (DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar;
) を共有していることがわかります。 これらのすべてのレコードに共通点があるため、サンプリング オーバーライドの候補に適しています。
自己診断をデバッグに設定すると、次のログ エントリが出力に表示されるようになります。
2023-10-26 15:48:25.407-04:00 DEBUG c.m.a.a.i.exporter.AgentSpanExporter - exporting span: SpanData{spanContext=ImmutableSpanContext...
これらのログの関心領域は "attributes" セクションです。
{
"attributes": {
"data": {
"thread.name": "DefaultDatabaseBroadcastTransport: MessageReader thread",
"thread.id": 96,
"db.connection_string": "apache:",
"db.statement": "DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar;",
"db.system": "other_sql",
"applicationinsights.internal.item_count": 1
}
}
}
その出力を使用して、次のようなサンプリング オーバーライドを構成できます。これによりノイズの多い SQL 呼び出しがフィルター処理されます。
{
"connectionString": "...",
"preview": {
"sampling": {
"overrides": [
{
"telemetryType": "dependency",
"attributes": [
{
"key": "db.statement",
"value": "DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar;",
"matchType": "strict"
}
],
"percentage": 0
}
]
}
}
}
変更が適用されると、次のクエリを使用して、これらの依存関係が Application Insights に最後に取り込まれた時刻を確認できます。
dependencies
| where timestamp > ago(30d)
| where data contains 'DECLARE @MyVar'
| summarize max(timestamp) by data
| sort by max_timestamp desc
DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar; 11/13/2023 8:52:41 PM
ログのテレメトリ収集を抑制する
SL4J を使用すると、ログ属性を追加できます。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
public class MdcClass {
private static final Logger logger = LoggerFactory.getLogger(MdcClass.class);
void method {
MDC.put("key", "value");
try {
logger.info(...); // Application log to remove
finally {
MDC.remove("key"); // In a finally block in case an exception happens with logger.info
}
}
}
その後、追加された属性を持つログを削除できます。
{
"sampling": {
"overrides": [
{
"telemetryType": "trace",
"percentage": 0,
"attributes": [
{
"key": "key",
"value": "value",
"matchType": "strict"
}
]
}
]
}
}
Java メソッドのテレメトリ収集を抑制する
Java メソッドにスパンを追加し、サンプリング オーバーライドを使用してこのスパンを削除します。
まず opentelemetry-instrumentation-annotations
依存関係を追加します。
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-instrumentation-annotations</artifactId>
</dependency>
これで、SQL 要求を実行する Java メソッドに WithSpan
注釈を追加できるようになりました。
package org.springframework.samples.petclinic.vet;
@Controller
class VetController {
private final VetRepository vetRepository;
public VetController(VetRepository vetRepository) {
this.vetRepository = vetRepository;
}
@GetMapping("/vets.html")
public String showVetList(@RequestParam(defaultValue = "1") int page, Model model) {
Vets vets = new Vets();
Page<Vet> paginated = findPaginated(page);
vets.getVetList().addAll(paginated.toList());
return addPaginationModel(page, paginated, model);
}
@WithSpan
private Page<Vet> findPaginated(int page) {
int pageSize = 5;
Pageable pageable = PageRequest.of(page - 1, pageSize);
return vetRepository.findAll(pageable); // Execution of SQL requests
}
次のサンプリング オーバーライド構成を使用すると、WithSpan
注釈によって追加されたスパンを削除できます。
"sampling": {
"overrides": [
{
"telemetryType": "dependency",
"attributes": [
{
"key": "code.function",
"value": "findPaginated",
"matchType": "strict"
}
],
"percentage": 0
}
]
}
属性値は Java メソッドの名前です。
この構成により、findPaginated
メソッドから作成されたすべてのテレメトリ データが削除されます。 findPaginated
メソッドからの SQL 実行に対して SQL 依存関係は作成されません。
次の構成では、WithSpan
注釈を持つ VetController
クラスのメソッドから出力されたすべてのテレメトリ データが削除されます。
"sampling": {
"overrides": [
{
"telemetryType": "dependency",
"attributes": [
{
"key": "code.namespace",
"value": "org.springframework.samples.petclinic.vet.VetController",
"matchType": "strict"
}
],
"percentage": 0
}
]
}
トラブルシューティング
regexp
を使用していて、サンプリング オーバーライドが機能しない場合は、.*
正規表現を試してください。 サンプリングが機能するようになった場合は、最初の正規表現に問題があることを意味します。こちらの正規表現のドキュメントを確認してください。
.*
で機能しない場合は、application-insights.json file
に構文の問題が存在している可能性があります。 Application Insights のログを確認し、警告メッセージが表示されているかどうかを確認してください。