共用方式為


取樣覆寫 - 適用於 Java 的 Azure 監視器 Application Insights

注意

從 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) 必須是 requestdependencytrace (log)或 exception 之一。

範圍開始後,範圍的類型與當時範圍上出現的屬性會用來檢查是否有任何取樣覆寫相符。

strictregexp 可能符合。 規則運算式比對會針對整個屬性值執行,因此如果您想要比對包含其中任何位置 abc 的值,則需要使用 .*abc.*。 取樣覆寫可以指定多個屬性準則,在此情況下,所有屬性準則都必須符合要比對的取樣覆寫。

如果其中一個取樣覆寫相符,則會使用其取樣百分比決定是否取樣此範圍。

只會使用符合的第一個取樣覆寫。

如果沒有取樣覆寫相符:

  • 如果這是追蹤中的第一個範圍,則會使用最上層取樣設定
  • 如果這不是追蹤中的第一個範圍,則會使用父代取樣決策。

可用於取樣的 Span 屬性

OpenTelemetry 範圍屬性會根據 OpenTelemetry 語意慣例自動收集。

您也可以以程式設計方式新增span屬性,並將其用於取樣。

注意

若要查看 Application Insights Java 為您的應用程式所擷取的確切屬性集,請將自我診斷層級設定為偵錯,然後尋找以文字 "exporting span" 開頭的偵錯訊息。

注意

只有在範圍開頭設定的屬性可用於取樣,因此如 http.response.status_code 或要求期間之類稍後擷取的屬性可以透過 OpenTelemetry Java 延伸模組篩選。 以下的樣本延伸模組會根據要求期間篩選範圍

注意

使用 遙測處理器 新增的屬性無法用於取樣。

使用案例

隱藏收集健康情況檢查的遙測

此範例會抑制針對 /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": {
    "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>

我們現在可以將批注新增 WithSpan 至執行 SQL 要求的 Java 方法:

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 記錄,並確認是否發現任何警告訊息。