为 .NET、Java、Node.js 和 Python 应用程序添加和修改 Azure Monitor OpenTelemetry

本文提供有关如何使用 Azure Monitor Application Insights 为应用程序添加和修改 OpenTelemetry 的指导。

若要详细了解 OpenTelemetry 概念,请参阅 OpenTelemetry 概述OpenTelemetry 常见问题解答

自动数据收集

发行版通过捆绑 OpenTelemetry 检测库来自动收集数据。

包含的检测库

以下 OpenTelemetry 检测库作为 Azure Monitor Application Insights 发行版的一部分包含在内。 有关详细信息,请参阅 Azure SDK for JavaScript

请求

依赖项

日志

可以使用 AzureMonitorOpenTelemetryOptions 配置检测:

// Import Azure Monitor OpenTelemetry
const { useAzureMonitor, AzureMonitorOpenTelemetryOptions } = require("@azure/monitor-opentelemetry");
// Import OpenTelemetry HTTP Instrumentation to get config type
const { HttpInstrumentationConfig } = require("@azure/monitor-opentelemetry");
    // Import HTTP to get type
const { IncomingMessage } = require("http");

// Specific Instrumentation configs could be added
const httpInstrumentationConfig: HttpInstrumentationConfig = {
    ignoreIncomingRequestHook: (request: IncomingMessage) => {
        return false; //Return true if you want to ignore a specific request 
    },
    enabled: true
};
// Instrumentations configuration
const options: AzureMonitorOpenTelemetryOptions = {
instrumentationOptions: {
    http: httpInstrumentationConfig,
    azureSdk: { enabled: true },
    mongoDb: { enabled: true },
    mySql: { enabled: true },
    postgreSql: { enabled: true },
    redis: { enabled: true },
    redis4: { enabled: true },
}
};

// Enable Azure Monitor integration
useAzureMonitor(options);

脚注

  • ¹:支持未经处理的/未捕获的异常的自动报告
  • ²:支持 OpenTelemetry 指标
  • ³:默认情况下,日志记录仅在 INFO 级别或更高级别收集。 若要更改此设置,请参阅配置选项
  • ⁴:默认情况下,仅当在 WARNING 级别或更高级别执行日志记录时,才会收集日志记录。

备注

Azure Monitor OpenTelemetry 发行版包括自定义映射和逻辑,用于自动发出 Application Insights 标准指标

提示

所有 OpenTelemetry 指标,无论是从检测库自动收集的还是从自动编码中收集收集的,现在都被认为是用于计费目的的 Application Insights“自定义指标”。 了解详细信息

添加社区检测库

从 OpenTelemetry 社区包含检测库时,可以自动收集更多数据。

注意

我们不支持也不保证社区检测库的质量。 要为我们的分发版推荐一个检测库,请在反馈社区中发帖或投票。 请注意,某些检测库基于实验性 OpenTelemetry 规范,可能会在将来引入中断性变更。

此处提供了其他 OpenTelemetry 检测,可以使用 ApplicationInsightsClient 中的 TraceHandler 添加它们:

   // Import the Azure Monitor OpenTelemetry plugin and OpenTelemetry API
   const { useAzureMonitor } = require("@azure/monitor-opentelemetry");
   const { metrics, trace, ProxyTracerProvider } = require("@opentelemetry/api");

   // Import the OpenTelemetry instrumentation registration function and Express instrumentation
   const { registerInstrumentations } = require( "@opentelemetry/instrumentation");
   const { ExpressInstrumentation } = require('@opentelemetry/instrumentation-express');

   // Get the OpenTelemetry tracer provider and meter provider
   const tracerProvider = (trace.getTracerProvider() as ProxyTracerProvider).getDelegate();
   const meterProvider = metrics.getMeterProvider();

   // Enable Azure Monitor integration
   useAzureMonitor();
   
   // Register the Express instrumentation
   registerInstrumentations({
     // List of instrumentations to register
     instrumentations: [
       new ExpressInstrumentation(), // Express instrumentation
     ],
   // OpenTelemetry tracer provider
     tracerProvider: tracerProvider,
     // OpenTelemetry meter provider
     meterProvider: meterProvider
   });

收集自定义遥测数据

本部分介绍如何从应用程序收集自定义遥测数据。

根据语言和信号类型,可以通过不同的方式收集自定义遥测数据,包括:

  • OpenTelemetry API
  • 特定于语言的日志记录/指标库
  • Application Insights Classic API

下表显示了目前支持的自定义遥测类型:

语言 自定义事件 自定义指标 依赖项 异常 页面视图 请求 跟踪
ASP.NET Core
   OpenTelemetry API
   ILogger API
   AI Classic API
Java
   OpenTelemetry API
   Logback,Log4j,JUL
   Micrometer 指标
   AI Classic API
Node.js
   OpenTelemetry API
Python
   OpenTelemetry API
   Python 日志记录模块
   事件扩展

备注

Application Insights Java 3.x 会侦听发送到 Application Insights Classic API 的遥测数据。 类似地,Application Insights Node.js 3.x 会收集使用 Application Insights Classic API 创建的事件。 在所有自定义遥测类型都通过 OpenTelemetry API 得到支持之前,这可以简化升级,并填补自定义遥测支持中的空白。

添加自定义指标

在这种情况下,自定义指标这个术语是指收集检测代码,以收集 OpenTelemetry 检测库没有自动收集的额外指标。

OpenTelemetry API 提供六种指标“检测”来涵盖各种指标方案,在指标资源管理器中可视化指标时,需要选取正确的“聚合类型”。 使用 OpenTelemetry 指标 API 发送指标和使用检测库时,此要求是正确的。

下表显示了每个 OpenTelemetry 指标检测的建议聚合类型

OpenTelemetry 检测 Azure Monitor 聚合类型
计数器 Sum
异步计数器 Sum
直方图 Min、Max、Average、Sum 和 Count
异步仪表 平均值
UpDownCounter Sum
异步 UpDownCounter Sum

注意

表中显示类型以外的聚合类型通常没有意义。

OpenTelemetry 规范介绍了这些检测,并提供了何时可以使用每种检测的示例。

提示

直方图是最通用的,也与 Application Insights GetMetric Classic API 最接近。 Azure Monitor 目前将直方图检测合并到五种受支持的聚合类型中,并且正在研发对百分位数的支持。 其他 OpenTelemetry 检测虽然通用性较差,但是对应用程序性能的影响较小。

直方图示例

// Import the Azure Monitor OpenTelemetry plugin and OpenTelemetry API
const { useAzureMonitor } = require("@azure/monitor-opentelemetry");
const { metrics } = require("@opentelemetry/api");

// Enable Azure Monitor integration
useAzureMonitor();

// Get the meter for the "testMeter" namespace
const meter =  metrics.getMeter("testMeter");

// Create a histogram metric
let histogram = meter.createHistogram("histogram");

// Record values to the histogram metric with different tags
histogram.record(1, { "testKey": "testValue" });
histogram.record(30, { "testKey": "testValue2" });
histogram.record(100, { "testKey2": "testValue" });

计数器示例

// Import the Azure Monitor OpenTelemetry plugin and OpenTelemetry API
const { useAzureMonitor } = require("@azure/monitor-opentelemetry");
const { metrics } = require("@opentelemetry/api");

// Enable Azure Monitor integration
useAzureMonitor();

// Get the meter for the "testMeter" namespace
const meter =  metrics.getMeter("testMeter");

// Create a counter metric
let counter = meter.createCounter("counter");

// Add values to the counter metric with different tags
counter.add(1, { "testKey": "testValue" });
counter.add(5, { "testKey2": "testValue" });
counter.add(3, { "testKey": "testValue2" });

仪表示例

// Import the useAzureMonitor function and the metrics module from the @azure/monitor-opentelemetry and @opentelemetry/api packages, respectively.
const { useAzureMonitor } = require("@azure/monitor-opentelemetry");
const { metrics } = require("@opentelemetry/api");

// Enable Azure Monitor integration.
useAzureMonitor();

// Get the meter for the "testMeter" meter name.
const meter = metrics.getMeter("testMeter");

// Create an observable gauge metric with the name "gauge".
let gauge = meter.createObservableGauge("gauge");

// Add a callback to the gauge metric. The callback will be invoked periodically to generate a new value for the gauge metric.
gauge.addCallback((observableResult: ObservableResult) => {
    // Generate a random number between 0 and 99.
    let randomNumber = Math.floor(Math.random() * 100);

    // Set the value of the gauge metric to the random number.
    observableResult.observe(randomNumber, {"testKey": "testValue"});
});

添加自定义异常

选择检测库会自动报告 Application Insights 的异常。 但是,你可能想要手动报告检测库报告的异常之外的异常。 例如,通常不会报告代码捕获的异常。 你可能希望报告这些异常,以便在相关体验中引起注意,包括故障部分和端到端事务视图。

这些手动记录的基于跨度的异常只有在远程、内部跨度的子跨度上记录时或者在顶级跨度上记录时,Node.js SDK 才会将其导出到 Application Insights 作为异常。

// Import the Azure Monitor OpenTelemetry plugin and OpenTelemetry API
const { useAzureMonitor } = require("@azure/monitor-opentelemetry");
const { trace } = require("@opentelemetry/api");

// Enable Azure Monitor integration
useAzureMonitor();

// Get the tracer for the "testTracer" namespace
const tracer = trace.getTracer("testTracer");

// Start a span with the name "hello"
let span = tracer.startSpan("hello");

// Try to throw an error
try{
    throw new Error("Test Error");
}

// Catch the error and record it to the span
catch(error){
    span.recordException(error);
}

添加自定义范围

你可能想要在两种情况下添加自定义跨度。 首先,当存在检测库尚未收集的依赖项请求时。 其次,当你希望在端到端事务视图上将应用程序进程建模为跨度时。

// Import the Azure Monitor OpenTelemetry plugin and OpenTelemetry API
const { useAzureMonitor } = require("@azure/monitor-opentelemetry");
const { trace } = require("@opentelemetry/api");

// Enable Azure Monitor integration
useAzureMonitor();

// Get the tracer for the "testTracer" namespace
const tracer = trace.getTracer("testTracer");

// Start a span with the name "hello"
let span = tracer.startSpan("hello");

// End the span
span.end();

使用 Application Insights Classic API 发送自定义遥测数据

建议尽可能使用 OpenTelemetry API,但在某些情况下,可能必须使用 Application Insights Classic API

如果要添加自定义事件或访问 Application Insights API,请将 @azure/monitor-opentelemetry 包替换为 applicationinsights v3 Beta 包。 它提供相同的方法和接口,并且@azure/monitor-opentelemetry的所有示例代码都适用于 v3 Beta 包。

需要使用 Application Insights Classic API 发送自定义遥测数据,请使用applicationinsightsv3 Beta 版包。 (https://www.npmjs.com/package/applicationinsights/v/beta)

// Import the TelemetryClient class from the Application Insights SDK for JavaScript.
const { TelemetryClient } = require("applicationinsights");

// Create a new TelemetryClient instance.
const telemetryClient = new TelemetryClient();

然后使用 TelemetryClient 发送自定义遥测数据:

事件

// Create an event telemetry object.
let eventTelemetry = {
    name: "testEvent"
};

// Send the event telemetry object to Azure Monitor Application Insights.
telemetryClient.trackEvent(eventTelemetry);

日志

// Create a trace telemetry object.
let traceTelemetry = {
    message: "testMessage",
    severity: "Information"
};

// Send the trace telemetry object to Azure Monitor Application Insights.
telemetryClient.trackTrace(traceTelemetry);

异常

// Try to execute a block of code.
try {
    ...
}

// If an error occurs, catch it and send it to Azure Monitor Application Insights as an exception telemetry item.
catch (error) {
    let exceptionTelemetry = {
    exception: error,
    severity: "Critical"
    };
    telemetryClient.trackException(exceptionTelemetry);
}

修改遥测

本部分介绍如何修改遥测。

添加范围属性

这些属性可能包括向遥测添加自定义属性。 还可以使用属性来设置 Application Insights 架构中的可选字段,如客户端 IP。

将自定义属性添加到范围

你添加到范围的任何属性都将导出为自定义属性。 它们将填充请求、依赖项、跟踪或异常表中的 customDimensions 字段。

// Import the necessary packages.
const { useAzureMonitor } = require("@azure/monitor-opentelemetry");
const { ReadableSpan, Span, SpanProcessor } = require("@opentelemetry/sdk-trace-base");
const { SemanticAttributes } = require("@opentelemetry/semantic-conventions");

// Create a new SpanEnrichingProcessor class.
class SpanEnrichingProcessor implements SpanProcessor {
  forceFlush(): Promise<void> {
    return Promise.resolve();
  }

  shutdown(): Promise<void> {
    return Promise.resolve();
  }

  onStart(_span: Span): void {}

  onEnd(span: ReadableSpan) {
    // Add custom dimensions to the span.
    span.attributes["CustomDimension1"] = "value1";
    span.attributes["CustomDimension2"] = "value2";
  }
}

// Enable Azure Monitor integration.
const options: AzureMonitorOpenTelemetryOptions = {
    // Add the SpanEnrichingProcessor
    spanProcessors: [new SpanEnrichingProcessor()] 
}
useAzureMonitor(options);

设置用户 IP

可以通过设置范围的属性来填充请求的 client_IP 字段。 Application Insights 使用 IP 地址生成用户位置属性,然后默认放弃它

使用自定义属性示例,但替换以下代码行:

...
// Import the SemanticAttributes class from the @opentelemetry/semantic-conventions package.
const { SemanticAttributes } = require("@opentelemetry/semantic-conventions");

// Create a new SpanEnrichingProcessor class.
class SpanEnrichingProcessor implements SpanProcessor {

    onEnd(span) {
    // Set the HTTP_CLIENT_IP attribute on the span to the IP address of the client.
    span.attributes[SemanticAttributes.HTTP_CLIENT_IP] = "<IP Address>";
    }
}

设置用户 ID 或经过身份验证的用户 ID

可以使用以下指导填充请求的 user_Iduser_AuthenticatedId 字段。 用户 ID 是匿名用户标识符。 经过身份验证的用户 ID 是已知的用户标识符。

重要

在设置经过身份验证的用户 ID 之前,请参考适用的隐私法律。

使用自定义属性示例,但替换以下代码行:

...
// Import the SemanticAttributes class from the @opentelemetry/semantic-conventions package.
import { SemanticAttributes } from "@opentelemetry/semantic-conventions";

// Create a new SpanEnrichingProcessor class.
class SpanEnrichingProcessor implements SpanProcessor {

    onEnd(span: ReadableSpan) {
    // Set the ENDUSER_ID attribute on the span to the ID of the user.
    span.attributes[SemanticAttributes.ENDUSER_ID] = "<User ID>";
    }
}

添加日志属性

const { useAzureMonitor } = require("@azure/monitor-opentelemetry");
const bunyan = require('bunyan');

// Instrumentations configuration
const options: AzureMonitorOpenTelemetryOptions = {
    instrumentationOptions: {
        // Instrumentations generating logs
        bunyan: { enabled: true },
    }
};

// Enable Azure Monitor integration
useAzureMonitor(options);

var log = bunyan.createLogger({ name: 'testApp' });
log.info({
    "testAttribute1": "testValue1",
    "testAttribute2": "testValue2",
    "testAttribute3": "testValue3"
}, 'testEvent');

获取跟踪 ID 或范围 ID

可以使用以下步骤获取当前处于活动状态的范围的 Trace IDSpan ID

在代码中获取请求跟踪 ID 和范围 ID:

// Import the trace module from the OpenTelemetry API.
const { trace } = require("@opentelemetry/api");

// Get the span ID and trace ID of the active span.
let spanId = trace.getActiveSpan().spanContext().spanId;
let traceId = trace.getActiveSpan().spanContext().traceId;

后续步骤