本指南提供有关在 Azure Monitor Application Insights 中集成和自定义 OpenTelemetry (OTel) 仪表的说明。
若要了解有关 OpenTelemetry 概念的详细信息,请参阅 OpenTelemetry 概述 或 OpenTelemetry 常见问题解答。
自动数据收集
发行版通过捆绑 OpenTelemetry 检测库来自动收集数据。
包含的检测库
请求
依赖
日志记录
若要减少或增加发送到 Azure Monitor 的日志数,请配置日志记录以设置相应的日志级别或应用筛选器。 例如,您可以选择仅将 Warning
和 Error
日志发送到 OpenTelemetry/Azure Monitor。 OpenTelemetry 不负责控制日志路由或筛选——这些决策由您的 ILogger
配置来决定。 有关配置 ILogger
的详细信息,请参阅 “配置日志记录”。
有关ILogger
的详细信息,请参阅C# 和 .NET 中的日志记录以及代码示例。
Azure Monitor 导出程序不包含任何检测库。
可以使用以下代码示例从 Azure 软件开发工具包(SDK) 收集依赖项,以手动订阅源。
// Create an OpenTelemetry tracer provider builder.
// It is important to keep the TracerProvider instance active throughout the process lifetime.
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
// The following line subscribes to dependencies emitted from Azure SDKs
.AddSource("Azure.*")
.AddAzureMonitorTraceExporter()
.AddHttpClientInstrumentation(o => o.FilterHttpRequestMessage = (_) =>
{
// Azure SDKs create their own client span before calling the service using HttpClient
// In this case, we would see two spans corresponding to the same operation
// 1) created by Azure SDK 2) created by HttpClient
// To prevent this duplication we are filtering the span from HttpClient
// as span from Azure SDK contains all relevant information needed.
var parentActivity = Activity.Current?.Parent;
if (parentActivity != null && parentActivity.Source.Name.Equals("Azure.Core.Http"))
{
return false;
}
return true;
})
.Build();
若要减少或增加发送到 Azure Monitor 的日志数,请配置日志记录以设置相应的日志级别或应用筛选器。 例如,您可以选择仅将 Warning
和 Error
日志发送到 OpenTelemetry/Azure Monitor。 OpenTelemetry 不负责控制日志路由或筛选——这些决策由您的 ILogger
配置来决定。 有关配置 ILogger
的详细信息,请参阅 “配置日志记录”。
请求
- Java 消息服务 (JMS) 使用者
- Kafka 使用者
- Netty
- 石英
- RabbitMQ
- Servlet
- 春季日程安排
备注
Servlet 和 Netty 自动检测涵盖大多数 Java HTTP 服务,包括 Java EE、Jakarta EE、Spring Boot、Quarkus 和 Micronaut
。
依赖项(加上下游分布式跟踪传播)
- Apache HttpClient
- Apache HttpAsyncClient
- AsyncHttpClient
- Google HttpClient
- gRPC
- java.net.HttpURLConnection
- Java 11 HttpClient
- JAX-RS client
- Jetty HttpClient (Jetty HTTP客户端)
- Java 消息服务 (JMS)
- 卡 夫 卡
- Netty 客户端
- OkHttp
- RabbitMQ
依赖项(没有下游分布式跟踪传播)
- 支持 Cassandra
- 支持 Java 数据库连接 (JDBC)
- 支持 MongoDB (异步和同步)
- 支持 Redis (Lettuce 和 Jedis)
指标
- Micrometer 指标,包括 Spring Boot Actuator 指标
- Java 管理扩展 (JMX) 指标
日志
- Logback(包含 MDC 属性) ¹
- Log4j(包括 MDC/线程上下文属性) ¹
- JBoss 日志记录功能(包括 MDC 属性) ¹
- java.util.logging ¹
若要减少或增加 Azure Monitor 收集的日志数,请先在应用程序的日志记录库中设置所需的日志记录级别(例如 WARNING
或 ERROR
)。
默认集合
默认情况下,自动收集以下 Azure SDK 发出的遥测数据:
[//]: # "Azure Cosmos DB 4.22.0+ due to https://github.com/Azure/azure-sdk-for-java/pull/25571"
[//]: # "the remaining above names and links scraped from https://azure.github.io/azure-sdk/releases/latest/java.html"
[//]: # "and version synched manually against the oldest version in maven central built on azure-core 1.14.0"
[//]: # ""
[//]: # "var table = document.querySelector('#tg-sb-content > div > table')"
[//]: # "var str = ''"
[//]: # "for (var i = 1, row; row = table.rows[i]; i++) {"
[//]: # " var name = row.cells[0].getElementsByTagName('div')[0].textContent.trim()"
[//]: # " var stableRow = row.cells[1]"
[//]: # " var versionBadge = stableRow.querySelector('.badge')"
[//]: # " if (!versionBadge) {"
[//]: # " continue"
[//]: # " }"
[//]: # " var version = versionBadge.textContent.trim()"
[//]: # " var link = stableRow.querySelectorAll('a')[2].href"
[//]: # " str += '* [' + name + '](' + link + ') ' + version + '\n'"
[//]: # "}"
[//]: # "console.log(str)"
Spring Boot 原生应用程序的请求
- Spring Web
- Spring Web MVC(模型-View-Controller)
- Spring WebFlux
Spring Boot 本机应用程序的依赖项
指标
Spring Boot 本机应用程序的日志
若要减少或增加 Azure Monitor 收集的日志数,请先在应用程序的日志记录库中设置所需的日志记录级别(例如 WARNING
或 ERROR
)。
有关Quartz原生应用程序,请查看 Quarkus 文档。
以下 OpenTelemetry 检测库作为 Azure Monitor Application Insights 发行版的一部分包含在内。 有关详细信息,请参阅 适用于 JavaScript 的 Azure SDK。
请求
依赖
日志
若要减少或增加 Azure Monitor 收集的日志数,请先在应用程序的日志记录库中设置所需的日志记录级别(例如 WARNING
或 ERROR
)。
可以使用 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);
请求
依赖
日志
若要减少或增加 Azure Monitor 收集的日志数,请先在应用程序的日志记录库中设置所需的日志记录级别(例如 WARNING
或 ERROR
)。
可以在 GitHub 上找到使用 Python 日志记录库的示例。
默认情况下,会自动 收集 Azure 软件开发工具包(SDK)发出的遥测数据。
脚注
- ¹:支持未经处理的/未捕获的异常的自动报告
- ²:支持 OpenTelemetry 指标
提示
所有 OpenTelemetry 指标,无论是从仪器化库自动收集的还是从手动编码中收集的,现在都被认为是用于计费目的的 Application Insights“自定义指标”。 了解详细信息。
包含来自 OpenTelemetry 社区的工具库时,可以自动收集更多数据。
注意
我们不支持也不保证社区检测库的质量。 若要为发行版建议一个,请在 反馈社区中发布或投票。 请注意,某些检测基于实验性的 OpenTelemetry 规范,未能可能会引入中断性变更。
若要添加社区库,请在为库添加 NuGet 包后使用 ConfigureOpenTelemetryMeterProvider
或 ConfigureOpenTelemetryTracerProvider
方法。
以下示例演示如何添加 运行时检测 以收集额外的指标:
dotnet add package OpenTelemetry.Instrumentation.Runtime
// Create a new ASP.NET Core web application builder.
var builder = WebApplication.CreateBuilder(args);
// Configure the OpenTelemetry meter provider to add runtime instrumentation.
builder.Services.ConfigureOpenTelemetryMeterProvider((sp, builder) => builder.AddRuntimeInstrumentation());
// Add the Azure Monitor telemetry service to the application.
// This service will collect and send telemetry data to Azure Monitor.
builder.Services.AddOpenTelemetry().UseAzureMonitor();
// Build the ASP.NET Core web application.
var app = builder.Build();
// Start the ASP.NET Core web application.
app.Run();
以下示例演示如何添加 运行时检测 以收集额外的指标:
// Create a new OpenTelemetry meter provider and add runtime instrumentation and the Azure Monitor metric exporter.
// It is important to keep the MetricsProvider instance active throughout the process lifetime.
var metricsProvider = Sdk.CreateMeterProviderBuilder()
.AddRuntimeInstrumentation()
.AddAzureMonitorMetricExporter();
不能使用社区检测库来扩展 Java 发行版。 若要请求我们加入另一个检测库,请在 GitHub 页面上开启问题。 可以在 后续步骤中找到指向 GitHub 页面的链接。
不能将社区检测库与 GraalVM Java 原生应用程序一起使用。
此处提供了其他 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
});
若要添加社区检测库(Azure Monitor 发行版未正式支持/包括),可以直接使用检测功能进行检测。 可在 此处找到社区检测库的列表。
备注
建议不要使用 和发行库 instrument()
手动检测configure_azure_monitor()
。 这不是受支持的场景,可能会导致遥测出现非预期行为。
# Import the `configure_azure_monitor()`, `SQLAlchemyInstrumentor`, `create_engine`, and `text` functions from the appropriate packages.
from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
from sqlalchemy import create_engine, text
# Configure OpenTelemetry to use Azure Monitor.
configure_azure_monitor()
# Create a SQLAlchemy engine.
engine = create_engine("sqlite:///:memory:")
# SQLAlchemy instrumentation is not officially supported by this package, however, you can use the OpenTelemetry `instrument()` method manually in conjunction with `configure_azure_monitor()`.
SQLAlchemyInstrumentor().instrument(
engine=engine,
)
# Database calls using the SQLAlchemy library will be automatically captured.
with engine.connect() as conn:
result = conn.execute(text("select 'hello world'"))
print(result.all())
收集自定义遥测数据
本部分介绍如何从应用程序收集自定义遥测数据。
根据语言和信号类型,可以通过不同的方式收集自定义遥测数据,包括:
- 开放遥测 API
- 特定于语言的日志记录/指标库
- Application Insights 经典 API
下表显示了目前支持的自定义遥测类型:
语言 |
自定义事件 |
自定义指标 |
依赖项 |
异常 |
页面视图 |
请求 |
跟踪 |
ASP.NET Core |
|
|
|
|
|
|
|
开放遥测 API |
|
是 |
是 |
是 |
|
是 |
|
ILogger API |
|
|
|
|
|
|
是 |
AI 经典 API |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
爪哇岛 |
|
|
|
|
|
|
|
开放遥测 API |
|
是 |
是 |
是 |
|
是 |
|
Logback,Log4j ,JUL |
|
|
|
是 |
|
|
是 |
Micrometer 指标 |
|
是 |
|
|
|
|
|
AI 经典 API |
是 |
是 |
是 |
是 |
是 |
是 |
是 |
|
|
|
|
|
|
|
|
Node.js |
|
|
|
|
|
|
|
开放遥测 API |
|
是 |
是 |
是 |
|
是 |
|
|
|
|
|
|
|
|
|
Python |
|
|
|
|
|
|
|
开放遥测 API |
|
是 |
是 |
是 |
|
是 |
|
Python 日志记录模块 |
|
|
|
|
|
|
是 |
事件扩展 |
是 |
|
|
|
|
|
是 |
备注
Application Insights Java 3.x 和 Application Insights Node.js 3.x 从 Application Insights 经典 API 收集遥测数据。 此行为简化了升级,并暂时支持自定义遥测,直到 OpenTelemetry API 包含所有自定义遥测类型。
添加自定义指标
在此上下文中,自定义指标术语是指手动检测代码以收集超出 OpenTelemetry Instrumentation 库自动收集的额外指标。
OpenTelemetry API 提供六种指标“仪表”来涵盖各种指标场景,在 Metrics Explorer 中可视化指标时,需要选择正确的“聚合类型”。 使用 OpenTelemetry 指标 API 发送指标和使用检测库时,此要求是正确的。
下表显示了每个 OpenTelemetry 指标工具的建议 聚合类型 。
OpenTelemetry 工具 |
Azure Monitor 聚合类型 |
计数器 |
总和 |
异步计数器 |
总和 |
直方图 |
最小值、最大值、平均值、总和和计数 |
异步仪表 |
平均值 |
UpDownCounter |
总和 |
异步增减计数器 |
总和 |
OpenTelemetry 规范介绍了这些仪器,并提供了何时可以使用每个仪器的示例。
提示
直方图最通用,最等效于 Application Insights GetMetric 经典 API。 Azure Monitor 目前将直方图检测合并到五种受支持的聚合类型中,并且正在研发对百分位数的支持。 虽然通用性较低,但其他 OpenTelemetry 仪器对应用程序性能的影响较小。
直方图示例
应用程序在启动时必须按名称订阅计量:
// Create a new ASP.NET Core web application builder.
var builder = WebApplication.CreateBuilder(args);
// Configure the OpenTelemetry meter provider to add a meter named "OTel.AzureMonitor.Demo".
builder.Services.ConfigureOpenTelemetryMeterProvider((sp, builder) => builder.AddMeter("OTel.AzureMonitor.Demo"));
// Add the Azure Monitor telemetry service to the application.
// This service will collect and send telemetry data to Azure Monitor.
builder.Services.AddOpenTelemetry().UseAzureMonitor();
// Build the ASP.NET Core web application.
var app = builder.Build();
// Start the ASP.NET Core web application.
app.Run();
Meter
必须使用同一名称初始化:
// Create a new meter named "OTel.AzureMonitor.Demo".
var meter = new Meter("OTel.AzureMonitor.Demo");
// Create a new histogram metric named "FruitSalePrice".
Histogram<long> myFruitSalePrice = meter.CreateHistogram<long>("FruitSalePrice");
// Create a new Random object.
var rand = new Random();
// Record a few random sale prices for apples and lemons, with different colors.
myFruitSalePrice.Record(rand.Next(1, 1000), new("name", "apple"), new("color", "red"));
myFruitSalePrice.Record(rand.Next(1, 1000), new("name", "lemon"), new("color", "yellow"));
myFruitSalePrice.Record(rand.Next(1, 1000), new("name", "lemon"), new("color", "yellow"));
myFruitSalePrice.Record(rand.Next(1, 1000), new("name", "apple"), new("color", "green"));
myFruitSalePrice.Record(rand.Next(1, 1000), new("name", "apple"), new("color", "red"));
myFruitSalePrice.Record(rand.Next(1, 1000), new("name", "lemon"), new("color", "yellow"));
public class Program
{
// Create a static readonly Meter object named "OTel.AzureMonitor.Demo".
// This meter will be used to track metrics about the application.
private static readonly Meter meter = new("OTel.AzureMonitor.Demo");
public static void Main()
{
// Create a new MeterProvider object using the OpenTelemetry SDK.
// The MeterProvider object is responsible for managing meters and sending
// metric data to exporters.
// It is important to keep the MetricsProvider instance active
// throughout the process lifetime.
//
// The MeterProviderBuilder is configured to add a meter named
// "OTel.AzureMonitor.Demo" and an Azure Monitor metric exporter.
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("OTel.AzureMonitor.Demo")
.AddAzureMonitorMetricExporter()
.Build();
// Create a new Histogram metric named "FruitSalePrice".
// This metric will track the distribution of fruit sale prices.
Histogram<long> myFruitSalePrice = meter.CreateHistogram<long>("FruitSalePrice");
// Create a new Random object. This object will be used to generate random sale prices.
var rand = new Random();
// Record a few random sale prices for apples and lemons, with different colors.
// Each record includes a timestamp, a value, and a set of attributes.
// The attributes can be used to filter and analyze the metric data.
myFruitSalePrice.Record(rand.Next(1, 1000), new("name", "apple"), new("color", "red"));
myFruitSalePrice.Record(rand.Next(1, 1000), new("name", "lemon"), new("color", "yellow"));
myFruitSalePrice.Record(rand.Next(1, 1000), new("name", "lemon"), new("color", "yellow"));
myFruitSalePrice.Record(rand.Next(1, 1000), new("name", "apple"), new("color", "green"));
myFruitSalePrice.Record(rand.Next(1, 1000), new("name", "apple"), new("color", "red"));
myFruitSalePrice.Record(rand.Next(1, 1000), new("name", "lemon"), new("color", "yellow"));
// Display a message to the user and wait for them to press Enter.
// This allows the user to see the message and the console before the
// application exits.
System.Console.WriteLine("Press Enter key to exit.");
System.Console.ReadLine();
}
}
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.DoubleHistogram;
import io.opentelemetry.api.metrics.Meter;
public class Program {
public static void main(String[] args) {
Meter meter = GlobalOpenTelemetry.getMeter("OTEL.AzureMonitor.Demo");
DoubleHistogram histogram = meter.histogramBuilder("histogram").build();
histogram.record(1.0);
histogram.record(100.0);
histogram.record(30.0);
}
}
注入 OpenTelemetry
:
创建直方图:
import io.opentelemetry.api.metrics.DoubleHistogram;
import io.opentelemetry.api.metrics.Meter;
Meter meter = openTelemetry.getMeter("OTEL.AzureMonitor.Demo");
DoubleHistogram histogram = meter.histogramBuilder("histogram").build();
histogram.record(1.0);
histogram.record(100.0);
histogram.record(30.0);
// 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 `configure_azure_monitor()` and `metrics` functions from the appropriate packages.
from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry import metrics
import os
# Configure OpenTelemetry to use Azure Monitor with the specified connection string.
# Replace `<your-connection-string>` with the connection string to your Azure Monitor Application Insights resource.
configure_azure_monitor(
connection_string="<your-connection-string>",
)
# Opt in to allow grouping of your metrics via a custom metrics namespace in app insights metrics explorer.
# Specify the namespace name using get_meter("namespace-name")
os.environ["APPLICATIONINSIGHTS_METRIC_NAMESPACE_OPT_IN"] = "true"
# Get a meter provider and a meter with the name "otel_azure_monitor_histogram_demo".
meter = metrics.get_meter_provider().get_meter("otel_azure_monitor_histogram_demo")
# Record three values to the histogram.
histogram = meter.create_histogram("histogram")
histogram.record(1.0, {"test_key": "test_value"})
histogram.record(100.0, {"test_key2": "test_value"})
histogram.record(30.0, {"test_key": "test_value2"})
# Wait for background execution.
input()
反例
应用程序在启动时必须按名称订阅计量:
// Create a new ASP.NET Core web application builder.
var builder = WebApplication.CreateBuilder(args);
// Configure the OpenTelemetry meter provider to add a meter named "OTel.AzureMonitor.Demo".
builder.Services.ConfigureOpenTelemetryMeterProvider((sp, builder) => builder.AddMeter("OTel.AzureMonitor.Demo"));
// Add the Azure Monitor telemetry service to the application.
// This service will collect and send telemetry data to Azure Monitor.
builder.Services.AddOpenTelemetry().UseAzureMonitor();
// Build the ASP.NET Core web application.
var app = builder.Build();
// Start the ASP.NET Core web application.
app.Run();
Meter
必须使用同一名称初始化:
// Create a new meter named "OTel.AzureMonitor.Demo".
var meter = new Meter("OTel.AzureMonitor.Demo");
// Create a new counter metric named "MyFruitCounter".
Counter<long> myFruitCounter = meter.CreateCounter<long>("MyFruitCounter");
// Record the number of fruits sold, grouped by name and color.
myFruitCounter.Add(1, new("name", "apple"), new("color", "red"));
myFruitCounter.Add(2, new("name", "lemon"), new("color", "yellow"));
myFruitCounter.Add(1, new("name", "lemon"), new("color", "yellow"));
myFruitCounter.Add(2, new("name", "apple"), new("color", "green"));
myFruitCounter.Add(5, new("name", "apple"), new("color", "red"));
myFruitCounter.Add(4, new("name", "lemon"), new("color", "yellow"));
public class Program
{
// Create a static readonly Meter object named "OTel.AzureMonitor.Demo".
// This meter will be used to track metrics about the application.
private static readonly Meter meter = new("OTel.AzureMonitor.Demo");
public static void Main()
{
// Create a new MeterProvider object using the OpenTelemetry SDK.
// The MeterProvider object is responsible for managing meters and sending
// metric data to exporters.
// It is important to keep the MetricsProvider instance active
// throughout the process lifetime.
//
// The MeterProviderBuilder is configured to add a meter named
// "OTel.AzureMonitor.Demo" and an Azure Monitor metric exporter.
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("OTel.AzureMonitor.Demo")
.AddAzureMonitorMetricExporter()
.Build();
// Create a new counter metric named "MyFruitCounter".
// This metric will track the number of fruits sold.
Counter<long> myFruitCounter = meter.CreateCounter<long>("MyFruitCounter");
// Record the number of fruits sold, grouped by name and color.
myFruitCounter.Add(1, new("name", "apple"), new("color", "red"));
myFruitCounter.Add(2, new("name", "lemon"), new("color", "yellow"));
myFruitCounter.Add(1, new("name", "lemon"), new("color", "yellow"));
myFruitCounter.Add(2, new("name", "apple"), new("color", "green"));
myFruitCounter.Add(5, new("name", "apple"), new("color", "red"));
myFruitCounter.Add(4, new("name", "lemon"), new("color", "yellow"));
// Display a message to the user and wait for them to press Enter.
// This allows the user to see the message and the console before the
// application exits.
System.Console.WriteLine("Press Enter key to exit.");
System.Console.ReadLine();
}
}
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.metrics.Meter;
public class Program {
public static void main(String[] args) {
Meter meter = GlobalOpenTelemetry.getMeter("OTEL.AzureMonitor.Demo");
LongCounter myFruitCounter = meter
.counterBuilder("MyFruitCounter")
.build();
myFruitCounter.add(1, Attributes.of(AttributeKey.stringKey("name"), "apple", AttributeKey.stringKey("color"), "red"));
myFruitCounter.add(2, Attributes.of(AttributeKey.stringKey("name"), "lemon", AttributeKey.stringKey("color"), "yellow"));
myFruitCounter.add(1, Attributes.of(AttributeKey.stringKey("name"), "lemon", AttributeKey.stringKey("color"), "yellow"));
myFruitCounter.add(2, Attributes.of(AttributeKey.stringKey("name"), "apple", AttributeKey.stringKey("color"), "green"));
myFruitCounter.add(5, Attributes.of(AttributeKey.stringKey("name"), "apple", AttributeKey.stringKey("color"), "red"));
myFruitCounter.add(4, Attributes.of(AttributeKey.stringKey("name"), "lemon", AttributeKey.stringKey("color"), "yellow"));
}
}
注入 OpenTelemetry
:
创建计数器:
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.metrics.Meter;
Meter meter = openTelemetry.getMeter("OTEL.AzureMonitor.Demo");
LongCounter myFruitCounter = meter.counterBuilder("MyFruitCounter")
.build();
myFruitCounter.add(1, Attributes.of(AttributeKey.stringKey("name"), "apple", AttributeKey.stringKey("color"), "red"));
myFruitCounter.add(2, Attributes.of(AttributeKey.stringKey("name"), "lemon", AttributeKey.stringKey("color"), "yellow"));
myFruitCounter.add(1, Attributes.of(AttributeKey.stringKey("name"), "lemon", AttributeKey.stringKey("color"), "yellow"));
myFruitCounter.add(2, Attributes.of(AttributeKey.stringKey("name"), "apple", AttributeKey.stringKey("color"), "green"));
myFruitCounter.add(5, Attributes.of(AttributeKey.stringKey("name"), "apple", AttributeKey.stringKey("color"), "red"));
myFruitCounter.add(4, Attributes.of(AttributeKey.stringKey("name"), "lemon", AttributeKey.stringKey("color"), "yellow"));
// 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 `configure_azure_monitor()` and `metrics` functions from the appropriate packages.
from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry import metrics
import os
# Configure OpenTelemetry to use Azure Monitor with the specified connection string.
# Replace `<your-connection-string>` with the connection string to your Azure Monitor Application Insights resource.
configure_azure_monitor(
connection_string="<your-connection-string>",
)
# Opt in to allow grouping of your metrics via a custom metrics namespace in app insights metrics explorer.
# Specify the namespace name using get_meter("namespace-name")
os.environ["APPLICATIONINSIGHTS_METRIC_NAMESPACE_OPT_IN"] = "true"
# Get a meter provider and a meter with the name "otel_azure_monitor_counter_demo".
meter = metrics.get_meter_provider().get_meter("otel_azure_monitor_counter_demo")
# Create a counter metric with the name "counter".
counter = meter.create_counter("counter")
# Add three values to the counter.
# The first argument to the `add()` method is the value to add.
# The second argument is a dictionary of dimensions.
# Dimensions are used to group related metrics together.
counter.add(1.0, {"test_key": "test_value"})
counter.add(5.0, {"test_key2": "test_value"})
counter.add(3.0, {"test_key": "test_value2"})
# Wait for background execution.
input()
仪表示例
应用程序在启动时必须按名称订阅计量:
// Create a new ASP.NET Core web application builder.
var builder = WebApplication.CreateBuilder(args);
// Configure the OpenTelemetry meter provider to add a meter named "OTel.AzureMonitor.Demo".
builder.Services.ConfigureOpenTelemetryMeterProvider((sp, builder) => builder.AddMeter("OTel.AzureMonitor.Demo"));
// Add the Azure Monitor telemetry service to the application.
// This service will collect and send telemetry data to Azure Monitor.
builder.Services.AddOpenTelemetry().UseAzureMonitor();
// Build the ASP.NET Core web application.
var app = builder.Build();
// Start the ASP.NET Core web application.
app.Run();
Meter
必须使用同一名称初始化:
// Get the current process.
var process = Process.GetCurrentProcess();
// Create a new meter named "OTel.AzureMonitor.Demo".
var meter = new Meter("OTel.AzureMonitor.Demo");
// Create a new observable gauge metric named "Thread.State".
// This metric will track the state of each thread in the current process.
ObservableGauge<int> myObservableGauge = meter.CreateObservableGauge("Thread.State", () => GetThreadState(process));
private static IEnumerable<Measurement<int>> GetThreadState(Process process)
{
// Iterate over all threads in the current process.
foreach (ProcessThread thread in process.Threads)
{
// Create a measurement for each thread, including the thread state, process ID, and thread ID.
yield return new((int)thread.ThreadState, new("ProcessId", process.Id), new("ThreadId", thread.Id));
}
}
public class Program
{
// Create a static readonly Meter object named "OTel.AzureMonitor.Demo".
// This meter will be used to track metrics about the application.
private static readonly Meter meter = new("OTel.AzureMonitor.Demo");
public static void Main()
{
// Create a new MeterProvider object using the OpenTelemetry SDK.
// The MeterProvider object is responsible for managing meters and sending
// metric data to exporters.
// It is important to keep the MetricsProvider instance active
// throughout the process lifetime.
//
// The MeterProviderBuilder is configured to add a meter named
// "OTel.AzureMonitor.Demo" and an Azure Monitor metric exporter.
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("OTel.AzureMonitor.Demo")
.AddAzureMonitorMetricExporter()
.Build();
// Get the current process.
var process = Process.GetCurrentProcess();
// Create a new observable gauge metric named "Thread.State".
// This metric will track the state of each thread in the current process.
ObservableGauge<int> myObservableGauge = meter.CreateObservableGauge("Thread.State", () => GetThreadState(process));
// Display a message to the user and wait for them to press Enter.
// This allows the user to see the message and the console before the
// application exits.
System.Console.WriteLine("Press Enter key to exit.");
System.Console.ReadLine();
}
private static IEnumerable<Measurement<int>> GetThreadState(Process process)
{
// Iterate over all threads in the current process.
foreach (ProcessThread thread in process.Threads)
{
// Create a measurement for each thread, including the thread state, process ID, and thread ID.
yield return new((int)thread.ThreadState, new("ProcessId", process.Id), new("ThreadId", thread.Id));
}
}
}
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.Meter;
public class Program {
public static void main(String[] args) {
Meter meter = GlobalOpenTelemetry.getMeter("OTEL.AzureMonitor.Demo");
meter.gaugeBuilder("gauge")
.buildWithCallback(
observableMeasurement -> {
double randomNumber = Math.floor(Math.random() * 100);
observableMeasurement.record(randomNumber, Attributes.of(AttributeKey.stringKey("testKey"), "testValue"));
});
}
}
注入 OpenTelemetry
:
创建仪表:
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.Meter;
Meter meter = openTelemetry.getMeter("OTEL.AzureMonitor.Demo");
meter.gaugeBuilder("gauge")
.buildWithCallback(
observableMeasurement -> {
double randomNumber = Math.floor(Math.random() * 100);
observableMeasurement.record(randomNumber, Attributes.of(AttributeKey.stringKey("testKey"), "testValue"));
});
// 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"});
});
# Import the necessary packages.
from typing import Iterable
import os
from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry import metrics
from opentelemetry.metrics import CallbackOptions, Observation
# Configure OpenTelemetry to use Azure Monitor with the specified connection string.
# Replace `<your-connection-string>` with the connection string to your Azure Monitor Application Insights resource.
configure_azure_monitor(
connection_string="<your-connection-string>",
)
# Opt in to allow grouping of your metrics via a custom metrics namespace in app insights metrics explorer.
# Specify the namespace name using get_meter("namespace-name")
os.environ["APPLICATIONINSIGHTS_METRIC_NAMESPACE_OPT_IN"] = "true"
# Get a meter provider and a meter with the name "otel_azure_monitor_gauge_demo".
meter = metrics.get_meter_provider().get_meter("otel_azure_monitor_gauge_demo")
# Define two observable gauge generators.
# The first generator yields a single observation with the value 9.
# The second generator yields a sequence of 10 observations with the value 9 and a different dimension value for each observation.
def observable_gauge_generator(options: CallbackOptions) -> Iterable[Observation]:
yield Observation(9, {"test_key": "test_value"})
def observable_gauge_sequence(options: CallbackOptions) -> Iterable[Observation]:
observations = []
for i in range(10):
observations.append(
Observation(9, {"test_key": i})
)
return observations
# Create two observable gauges using the defined generators.
gauge = meter.create_observable_gauge("gauge", [observable_gauge_generator])
gauge2 = meter.create_observable_gauge("gauge2", [observable_gauge_sequence])
# Wait for background execution.
input()
添加自定义异常
某些检测库会自动向 Application Insights 报告异常。
但是,你可能想要手动报告检测库报告的异常之外的异常。
例如,通常不会报告代码捕获的异常。 你可能希望报告这些异常,以便在相关体验中引起注意,包括故障部分和端到端交易视图。
若要使用活动记录异常:
// Start a new activity named "ExceptionExample".
using (var activity = activitySource.StartActivity("ExceptionExample"))
{
// Try to execute some code.
try
{
throw new Exception("Test exception");
}
// If an exception is thrown, catch it and set the activity status to "Error".
catch (Exception ex)
{
activity?.SetStatus(ActivityStatusCode.Error);
activity?.RecordException(ex);
}
}
要使用 ILogger
记录异常:
// Create a logger using the logger factory. The logger category name is used to filter and route log messages.
var logger = loggerFactory.CreateLogger(logCategoryName);
// Try to execute some code.
try
{
throw new Exception("Test Exception");
}
catch (Exception ex)
{
// Log an error message with the exception. The log level is set to "Error" and the event ID is set to 0.
// The log message includes a template and a parameter. The template will be replaced with the value of the parameter when the log message is written.
logger.Log(
logLevel: LogLevel.Error,
eventId: 0,
exception: ex,
message: "Hello {name}.",
args: new object[] { "World" });
}
若要使用活动记录异常:
// Start a new activity named "ExceptionExample".
using (var activity = activitySource.StartActivity("ExceptionExample"))
{
// Try to execute some code.
try
{
throw new Exception("Test exception");
}
// If an exception is thrown, catch it and set the activity status to "Error".
catch (Exception ex)
{
activity?.SetStatus(ActivityStatusCode.Error);
activity?.RecordException(ex);
}
}
要使用 ILogger
记录异常:
// Create a logger using the logger factory. The logger category name is used to filter and route log messages.
var logger = loggerFactory.CreateLogger("ExceptionExample");
try
{
// Try to execute some code.
throw new Exception("Test Exception");
}
catch (Exception ex)
{
// Log an error message with the exception. The log level is set to "Error" and the event ID is set to 0.
// The log message includes a template and a parameter. The template will be replaced with the value of the parameter when the log message is written.
logger.Log(
logLevel: LogLevel.Error,
eventId: 0,
exception: ex,
message: "Hello {name}.",
args: new object[] { "World" });
}
可以使用 opentelemetry-api
来更新跨度的状态并记录异常。
将 opentelemetry-api-1.0.0.jar
(或更高版本)添加到应用程序:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>1.0.0</version>
</dependency>
将状态设置为 error
,并记录代码中的异常:
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
Span span = Span.current();
span.setStatus(StatusCode.ERROR, "errorMessage");
span.recordException(e);
将状态设置为 error
,并记录代码中的异常:
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
Span span = Span.current();
span.setStatus(StatusCode.ERROR, "errorMessage");
span.recordException(e);
仅当记录在顶级跨度或远程或内部跨度的子级时,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);
}
OpenTelemetry Python SDK 的实现方式使得引发的异常会被自动捕获和记录。 有关此行为的示例,请参阅以下代码示例:
# Import the necessary packages.
from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry import trace
# Configure OpenTelemetry to use Azure Monitor with the specified connection string.
# Replace `<your-connection-string>` with the connection string to your Azure Monitor Application Insights resource.
configure_azure_monitor(
connection_string="<your-connection-string>",
)
# Get a tracer for the current module.
tracer = trace.get_tracer("otel_azure_monitor_exception_demo")
# Exception events
try:
# Start a new span with the name "hello".
with tracer.start_as_current_span("hello") as span:
# This exception will be automatically recorded
raise Exception("Custom exception message.")
except Exception:
print("Exception raised")
如果要手动记录异常,可以在上下文管理器中禁用该选项,并直接使用 record_exception()
,如下例所示:
...
# Start a new span with the name "hello" and disable exception recording.
with tracer.start_as_current_span("hello", record_exception=False) as span:
try:
# Raise an exception.
raise Exception("Custom exception message.")
except Exception as ex:
# Manually record exception
span.record_exception(ex)
...
添加自定义范围
你可能想要在两种情况下添加自定义跨度。 首先,当存在检测库尚未收集的依赖项请求时。 其次,当你希望在端到端事务视图上将应用程序进程建模为跨度时。
备注
Activity
命名空间中的 ActivitySource
和 System.Diagnostics
类分别代表 Span
和 Tracer
的 OpenTelemetry 概念。 可以通过使用其构造函数而不是使用 ActivitySource
来直接创建 TracerProvider
。 每个 ActivitySource
类都必须使用 TracerProvider
显式连接到 AddSource()
。 这是因为 OpenTelemetry 跟踪 API 的某些部分直接合并到 .NET 运行时中。 若要了解详细信息,请参阅 OpenTelemetry .NET 跟踪 API 简介。
// Define an activity source named "ActivitySourceName". This activity source will be used to create activities for all requests to the application.
internal static readonly ActivitySource activitySource = new("ActivitySourceName");
// Create an ASP.NET Core application builder.
var builder = WebApplication.CreateBuilder(args);
// Configure the OpenTelemetry tracer provider to add a source named "ActivitySourceName". This will ensure that all activities created by the activity source are traced.
builder.Services.ConfigureOpenTelemetryTracerProvider((sp, builder) => builder.AddSource("ActivitySourceName"));
// Add the Azure Monitor telemetry service to the application. This service will collect and send telemetry data to Azure Monitor.
builder.Services.AddOpenTelemetry().UseAzureMonitor();
// Build the ASP.NET Core application.
var app = builder.Build();
// Map a GET request to the root path ("/") to the specified action.
app.MapGet("/", () =>
{
// Start a new activity named "CustomActivity". This activity will be traced and the trace data will be sent to Azure Monitor.
using (var activity = activitySource.StartActivity("CustomActivity"))
{
// your code here
}
// Return a response message.
return $"Hello World!";
});
// Start the ASP.NET Core application.
app.Run();
StartActivity
默认为 ActivityKind.Internal
,但你可以提供任何其他 ActivityKind
。
ActivityKind.Client
、ActivityKind.Producer
、ActivityKind.Internal
映射到 Application Insights dependencies
。
ActivityKind.Server
、ActivityKind.Consumer
映射到 Application Insights requests
。
备注
Activity
命名空间中的 ActivitySource
和 System.Diagnostics
类分别代表 Span
和 Tracer
的 OpenTelemetry 概念。 可以通过使用其构造函数而不是使用 ActivitySource
来直接创建 TracerProvider
。 每个 ActivitySource
类都必须使用 TracerProvider
显式连接到 AddSource()
。 这是因为 OpenTelemetry 跟踪 API 的某些部分直接合并到 .NET 运行时中。 若要了解详细信息,请参阅 OpenTelemetry .NET 跟踪 API 简介。
// Create an OpenTelemetry tracer provider builder.
// It is important to keep the TracerProvider instance active throughout the process lifetime.
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("ActivitySourceName")
.AddAzureMonitorTraceExporter()
.Build();
// Create an activity source named "ActivitySourceName".
var activitySource = new ActivitySource("ActivitySourceName");
// Start a new activity named "CustomActivity". This activity will be traced and the trace data will be sent to Azure Monitor.
using (var activity = activitySource.StartActivity("CustomActivity"))
{
// your code here
}
StartActivity
默认为 ActivityKind.Internal
,但你可以提供任何其他 ActivityKind
。
ActivityKind.Client
、ActivityKind.Producer
、ActivityKind.Internal
映射到 Application Insights dependencies
。
ActivityKind.Server
、ActivityKind.Consumer
映射到 Application Insights requests
。
使用 OpenTelemetry 注解
添加自己的范围的最简单方法是使用 OpenTelemetry 的 @WithSpan
注释。
在 Application Insights 中,跨度会填充 requests
和 dependencies
表。
将 opentelemetry-instrumentation-annotations-1.32.0.jar
(或更高版本)添加到应用程序:
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-instrumentation-annotations</artifactId>
<version>1.32.0</version>
</dependency>
每次执行方法时,请使用 @WithSpan
注解生成一个跨度:
import io.opentelemetry.instrumentation.annotations.WithSpan;
@WithSpan(value = "your span name")
public void yourMethod() {
}
默认情况下,跨度会显示在 dependencies
表中,依赖项类型为 InProc
。
对于表示未被自动检测所捕获的后台作业的方法,我们建议将 kind = SpanKind.SERVER
属性应用于 @WithSpan
注解,以确保它们会出现在 Application Insights requests
表中。
使用 OpenTelemetry API
如果上述 OpenTelemetry @WithSpan
注释不能满足你的需求,可使用 OpenTelemetry API 添加范围。
将 opentelemetry-api-1.0.0.jar
(或更高版本)添加到应用程序:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>1.0.0</version>
</dependency>
使用 GlobalOpenTelemetry
类创建 Tracer
:
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Tracer;
static final Tracer tracer = GlobalOpenTelemetry.getTracer("com.example");
创建一个范围,使其成为当前范围,然后结束该范围:
Span span = tracer.spanBuilder("my first span").startSpan();
try (Scope ignored = span.makeCurrent()) {
// do stuff within the context of this
} catch (Throwable t) {
span.recordException(t);
} finally {
span.end();
}
注入 OpenTelemetry
:
创建 Tracer
:
import io.opentelemetry.api.trace.Tracer;
static final Tracer tracer = openTelemetry.getTracer("com.example");
创建一个范围,使其成为当前范围,然后结束该范围:
Span span = tracer.spanBuilder("my first span").startSpan();
try (Scope ignored = span.makeCurrent()) {
// do stuff within the context of this
} catch (Throwable t) {
span.recordException(t);
} finally {
span.end();
}
// 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();
OpenTelemetry API 可用于添加你自己的跨度,它们会显示在 Application Insights 的 requests
和 dependencies
表中。
代码示例展示如何使用 tracer.start_as_current_span()
方法来启动跨度、使其成为当前跨度,并在其上下文中结束跨度。
...
# Import the necessary packages.
from opentelemetry import trace
# Get a tracer for the current module.
tracer = trace.get_tracer(__name__)
# Start a new span with the name "my first span" and make it the current span.
# The "with" context manager starts, makes the span current, and ends the span within it's context
with tracer.start_as_current_span("my first span") as span:
try:
# Do stuff within the context of this span.
# All telemetry generated within this scope will be attributed to this span.
except Exception as ex:
# Record the exception on the span.
span.record_exception(ex)
...
默认情况下,跨度位于 dependencies
表中,依赖项类型为 InProc
。
如果方法代表尚未通过自动检测捕获的后台作业,我们建议设置属性 kind = SpanKind.SERVER
,以确保它出现在 Application Insights requests
表中。
...
# Import the necessary packages.
from opentelemetry import trace
from opentelemetry.trace import SpanKind
# Get a tracer for the current module.
tracer = trace.get_tracer(__name__)
# Start a new span with the name "my request span" and the kind set to SpanKind.SERVER.
with tracer.start_as_current_span("my request span", kind=SpanKind.SERVER) as span:
# Do stuff within the context of this span.
...
发送自定义事件
Application Insights 将自定义事件 customEvents
存储在表中。 分析、筛选和可视化它们的一种方法是使用 Application Insights 使用情况体验。
如果要自动收集客户端交互事件,可以在 JavaScript SDK 中使用插件。
自定义事件处于公开预览阶段,并使用 Azure.Monitor.OpenTelemetry.AspNetCore
1.3.0-beta.3。
若要使用 CustomEvent
发送 ILogger
,请设置消息模板中的 "microsoft.custom_event.name"
属性。
// Create a logger factory and configure OpenTelemetry with Azure Monitor
var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddOpenTelemetry(options =>
{
options.AddAzureMonitorLogExporter();
});
});
// Create a logger for the specified category
var logger = loggerFactory.CreateLogger(logCategoryName);
// Log a custom event with a custom name and additional attribute
// The 'microsoft.custom_event.name' value will be used as the name of the customEvent
logger.LogInformation("{microsoft.custom_event.name} {additional_attrs}", "test-event-name", "val1");
自定义事件当前处于公共预览阶段,并使用 Azure.Monitor.OpenTelemetry.Exporter
1.4.0-beta.3。
若要使用 CustomEvent
发送 ILogger
,请设置消息模板中的 "microsoft.custom_event.name"
属性。
// Create a logger factory and configure OpenTelemetry with Azure Monitor
var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddOpenTelemetry(options =>
{
options.AddAzureMonitorLogExporter();
});
});
// Create a logger for the specified category
var logger = loggerFactory.CreateLogger(logCategoryName);
// Log a custom event with a custom name and additional attribute
// The 'microsoft.custom_event.name' value will be used as the name of the customEvent
logger.LogInformation("{microsoft.custom_event.name} {additional_attrs}", "test-event-name", "val1");
若要使用 Java 代理发送 customEvent
,请在 OpenTelemetry 日志记录上设置 "microsoft.custom_event.name"
属性。
根据是否使用 Application Insights Java 代理或自动配置 SDK,获取 OpenTelemetry 记录器的方式会略有不同。 以下示例进一步介绍了此详细信息。
对于 Application Insights Java 代理:
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.logs.Logger;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.logs.Severity;
Logger logger = GlobalOpenTelemetry.get().getLogsBridge().get("opentelemetry-logger");
logger.logRecordBuilder()
.setAttribute(AttributeKey.stringKey("microsoft.custom_event.name"),"test-event-name")
.setSeverity(Severity.INFO)
.emit();
对于自动配置 SDK:
import com.azure.monitor.opentelemetry.autoconfigure.AzureMonitorAutoConfigure;
import com.azure.monitor.opentelemetry.autoconfigure.AzureMonitorAutoConfigureOptions;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.logs.Logger;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder;
AutoConfiguredOpenTelemetrySdkBuilder sdkBuilder = AutoConfiguredOpenTelemetrySdk.builder();
AzureMonitorAutoConfigureOptions options = new AzureMonitorAutoConfigureOptions();
options.connectionString("<your connection string>");
AzureMonitorAutoConfigure.customize(sdkBuilder, options);
OpenTelemetry openTelemetry = sdkBuilder.build().getOpenTelemetrySdk();
Logger logger = openTelemetry.getLogsBridge().get("opentelemetry-logger");
logger.logRecordBuilder()
.setAttribute(AttributeKey.stringKey("microsoft.custom_event.name"),"test-event-name")
.setSeverity(Severity.INFO)
.emit();
若要可靠地发出自定义事件,请直接使用 OpenTelemetry API。 某些日志记录框架不支持追加或分析自定义事件属性。
无法在 Java 原生环境中使用 customEvent
属性发送 "microsoft.custom_event.name"
。
若要使用customEvent
发送logger.emit
,请在日志"microsoft.custom_event.name"
对象中设置attributes
属性。 还可以根据需要包含其他属性。
// Send a customEvent by including the microsoft attribute key in the log.
// The customEvent name uses the value of that attribute.
logger.emit({
body: 'Hello World!',
attributes: {
"microsoft.custom_event.name": "test-event-name",
"additional_attrs": "val1"
},
});
// You can also populate fields like client_IP with attribute `client.address`
logger.emit({
body: 'This entry will have a custom client_IP',
attributes: {
"microsoft.custom_event.name": "test_event",
"client.address": "192.168.1.1"
},
});
若要在 Python 中发送customEvent
,请使用日志库,并在"microsoft.custom_event.name"
参数中使用extra
属性。
import logging
from azure.monitor.opentelemetry import configure_azure_monitor
# Set up your application logger
logger = logging.getLogger("my-app-logger")
# Configure Azure Monitor to collect logs from the specified logger name
configure_azure_monitor(
logger_name="my-app-logger", # Collect logs from your namespaced logger
)
# Log a custom event with a custom name and additional attribute
# The 'microsoft.custom_event.name' value will be used as the name of the customEvent
logger.warning(
"Hello World!",
extra={
"microsoft.custom_event.name": "test-event-name",
"additional_attrs": "val1"
}
)
# You can also populate fields like client_IP with attribute `client.address`
logger.info(
"This entry will have a custom client_IP",
extra={
"microsoft.custom_event.name": "test_event",
"client.address": "192.168.1.1"
}
)
修改遥测
本部分介绍如何修改遥测。
添加范围属性
这些属性可能包括向遥测添加自定义属性。 还可以使用属性来设置 Application Insights 架构中的可选字段,如客户端 IP。
将自定义属性添加到Span对象
添加到范围的任何 属性 都导出为自定义属性。 它们将填充请求、依赖项、跟踪或异常表中的 customDimensions 字段。
若要添加范围属性,请使用以下两种方法之一:
许多检测库都提供扩充选项。 有关指南,请参阅各个检测库的自述文件:
使用自定义处理器:
提示
在添加 Azure Monitor 之前,添加此处显示的处理器。
// Create an ASP.NET Core application builder.
var builder = WebApplication.CreateBuilder(args);
// Configure the OpenTelemetry tracer provider to add a new processor named ActivityEnrichingProcessor.
builder.Services.ConfigureOpenTelemetryTracerProvider((sp, builder) => builder.AddProcessor(new ActivityEnrichingProcessor()));
// Add the Azure Monitor telemetry service to the application. This service will collect and send telemetry data to Azure Monitor.
builder.Services.AddOpenTelemetry().UseAzureMonitor();
// Build the ASP.NET Core application.
var app = builder.Build();
// Start the ASP.NET Core application.
app.Run();
使用以下代码将 ActivityEnrichingProcessor.cs
添加到你的项目:
public class ActivityEnrichingProcessor : BaseProcessor<Activity>
{
public override void OnEnd(Activity activity)
{
// The updated activity will be available to all processors which are called after this processor.
activity.DisplayName = "Updated-" + activity.DisplayName;
activity.SetTag("CustomDimension1", "Value1");
activity.SetTag("CustomDimension2", "Value2");
}
}
若要添加范围属性,请使用以下两种方法之一:
提示
使用检测库提供的选项(当它们可用时)的优点是整个上下文都可用。 因此,用户可以选择添加或筛选更多属性。 例如,HttpClient 检测库中的扩充选项允许用户访问 httpRequestMessage 本身。 他们可以从中选择任何内容并将其存储为属性。
许多检测库都提供扩充选项。 有关指南,请参阅各个检测库的自述文件:
使用自定义处理器:
提示
在使用 Azure Monitor 导出器之前,添加如下所示的处理器。
// Create an OpenTelemetry tracer provider builder.
// It is important to keep the TracerProvider instance active throughout the process lifetime.
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
// Add a source named "OTel.AzureMonitor.Demo".
.AddSource("OTel.AzureMonitor.Demo") // Add a new processor named ActivityEnrichingProcessor.
.AddProcessor(new ActivityEnrichingProcessor()) // Add the Azure Monitor trace exporter.
.AddAzureMonitorTraceExporter() // Add the Azure Monitor trace exporter.
.Build();
使用以下代码将 ActivityEnrichingProcessor.cs
添加到你的项目:
public class ActivityEnrichingProcessor : BaseProcessor<Activity>
{
// The OnEnd method is called when an activity is finished. This is the ideal place to enrich the activity with additional data.
public override void OnEnd(Activity activity)
{
// Update the activity's display name.
// The updated activity will be available to all processors which are called after this processor.
activity.DisplayName = "Updated-" + activity.DisplayName;
// Set custom tags on the activity.
activity.SetTag("CustomDimension1", "Value1");
activity.SetTag("CustomDimension2", "Value2");
}
}
可以使用 opentelemetry-api
向范围中添加属性。
添加一个或多个范围属性会填充 customDimensions
、requests
、dependencies
或 traces
表中的 exceptions
字段。
将 opentelemetry-api-1.0.0.jar
(或更高版本)添加到应用程序:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>1.0.0</version>
</dependency>
在代码中添加自定义维度:
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.common.AttributeKey;
AttributeKey attributeKey = AttributeKey.stringKey("mycustomdimension");
Span.current().setAttribute(attributeKey, "myvalue1");
在代码中添加自定义维度:
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.common.AttributeKey;
AttributeKey attributeKey = AttributeKey.stringKey("mycustomdimension");
Span.current().setAttribute(attributeKey, "myvalue1");
// 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);
使用自定义处理器:
...
# Import the necessary packages.
from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry import trace
# Create a SpanEnrichingProcessor instance.
span_enrich_processor = SpanEnrichingProcessor()
# Configure OpenTelemetry to use Azure Monitor with the specified connection string.
# Replace `<your-connection-string>` with the connection string to your Azure Monitor Application Insights resource.
configure_azure_monitor(
connection_string="<your-connection-string>",
# Configure the custom span processors to include span enrich processor.
span_processors=[span_enrich_processor],
)
...
使用以下代码将 SpanEnrichingProcessor
添加到你的项目:
# Import the SpanProcessor class from the opentelemetry.sdk.trace module.
from opentelemetry.sdk.trace import SpanProcessor
class SpanEnrichingProcessor(SpanProcessor):
def on_end(self, span):
# Prefix the span name with the string "Updated-".
span._name = "Updated-" + span.name
# Add the custom dimension "CustomDimension1" with the value "Value1".
span._attributes["CustomDimension1"] = "Value1"
# Add the custom dimension "CustomDimension2" with the value "Value2".
span._attributes["CustomDimension2"] = "Value2"
设置用户 IP
可以通过在跨度上设置属性来填充 client_IP 请求字段。 Application Insights 使用 IP 地址生成用户位置属性,然后 默认将其丢弃。
使用自定义属性示例,但替换以下代码行:ActivityEnrichingProcessor.cs
// Add the client IP address to the activity as a tag.
// only applicable in case of activity.Kind == Server
activity.SetTag("client.address", "<IP Address>");
使用自定义属性示例,但替换以下代码行:ActivityEnrichingProcessor.cs
// Add the client IP address to the activity as a tag.
// only applicable in case of activity.Kind == Server
activity.SetTag("client.address", "<IP Address>");
使用 自定义属性示例,但替换以下代码行:
...
// 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>";
}
}
使用自定义属性示例,但替换以下代码行:SpanEnrichingProcessor.py
# Set the `http.client_ip` attribute of the span to the specified IP address.
span._attributes["http.client_ip"] = "<IP Address>"
设置用户 ID 或经过身份验证的用户 ID
您可以根据以下指南为请求填充user_Id或user_AuthenticatedId字段。 用户 ID 是匿名用户标识符。 经过身份验证的用户 ID 是已知的用户标识符。
重要
在设置经过身份验证的用户 ID 之前,请参考适用的隐私法律。
使用 自定义属性示例:
// Add the user ID to the activity as a tag, but only if the activity is not null.
activity?.SetTag("enduser.id", "<User Id>");
使用 自定义属性示例:
// Add the user ID to the activity as a tag, but only if the activity is not null.
activity?.SetTag("enduser.id", "<User Id>");
填充 user ID
、requests
或 dependencies
表中的 exceptions
字段。
将 opentelemetry-api-1.0.0.jar
(或更高版本)添加到应用程序:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>1.0.0</version>
</dependency>
在代码中设置 user_Id
:
import io.opentelemetry.api.trace.Span;
Span.current().setAttribute("enduser.id", "myuser");
填充 user ID
、requests
或 dependencies
表中的 exceptions
字段。
在代码中设置 user_Id
:
import io.opentelemetry.api.trace.Span;
Span.current().setAttribute("enduser.id", "myuser");
使用 自定义属性示例,但替换以下代码行:
...
// 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>";
}
}
使用 自定义属性示例,但替换以下代码行:
# Set the `enduser.id` attribute of the span to the specified user ID.
span._attributes["enduser.id"] = "<User ID>"
添加日志属性
OpenTelemetry 使用 .NET 的 ILogger
。
可以使用 消息模板将自定义维度附加到日志。
OpenTelemetry 使用 .NET 的 ILogger
。
可以使用 消息模板将自定义维度附加到日志。
会自动检测 Logback、Log4j 和 java.util.logging。 可通过以下方式将自定义维度附加到日志:
对于 Spring Boot 原生应用程序,Logback 可直接使用且无需额外配置。
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');
Python 日志记录库是自动仪表化的。 可以通过将一个字典传递到日志的 extra
参数,将自定义维度附加到日志中:
...
# Create a warning log message with the properties "key1" and "value1".
logger.warning("WARNING: Warning log with properties", extra={"key1": "value1"})
...
获取跟踪 ID 或范围 ID
可以使用以下步骤获取当前处于活动状态的范围的 Trace ID
和 Span ID
。
备注
Activity
命名空间中的 ActivitySource
和 System.Diagnostics
类分别代表 Span
和 Tracer
的 OpenTelemetry 概念。 这是因为 OpenTelemetry 跟踪 API 的某些部分直接合并到 .NET 运行时中。 若要了解详细信息,请参阅 OpenTelemetry .NET 跟踪 API 简介。
// Get the current activity.
Activity activity = Activity.Current;
// Get the trace ID of the activity.
string traceId = activity?.TraceId.ToHexString();
// Get the span ID of the activity.
string spanId = activity?.SpanId.ToHexString();
备注
Activity
命名空间中的 ActivitySource
和 System.Diagnostics
类分别代表 Span
和 Tracer
的 OpenTelemetry 概念。 这是因为 OpenTelemetry 跟踪 API 的某些部分直接合并到 .NET 运行时中。 若要了解详细信息,请参阅 OpenTelemetry .NET 跟踪 API 简介。
// Get the current activity.
Activity activity = Activity.Current;
// Get the trace ID of the activity.
string traceId = activity?.TraceId.ToHexString();
// Get the span ID of the activity.
string spanId = activity?.SpanId.ToHexString();
可以使用 opentelemetry-api
获取跟踪 ID 或范围 ID。
将 opentelemetry-api-1.0.0.jar
(或更高版本)添加到应用程序:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>1.0.0</version>
</dependency>
在代码中获取请求跟踪 ID 和范围 ID:
import io.opentelemetry.api.trace.Span;
Span span = Span.current();
String traceId = span.getSpanContext().getTraceId();
String spanId = span.getSpanContext().getSpanId();
在代码中获取请求跟踪 ID 和范围 ID:
import io.opentelemetry.api.trace.Span;
Span span = Span.current();
String traceId = span.getSpanContext().getTraceId();
String spanId = span.getSpanContext().getSpanId();
在代码中获取请求跟踪 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;
在代码中获取请求跟踪 ID 和范围 ID:
# Import the necessary libraries.
from opentelemetry import trace
# Get the trace ID and span ID of the current span.
trace_id = trace.get_current_span().get_span_context().trace_id
span_id = trace.get_current_span().get_span_context().span_id
后续步骤