本指南提供有关在 Azure Monitor Application Insights 中集成和自定义 OpenTelemetry (OTel) 仪表的说明。
若要详细了解 OpenTelemetry 概念,请参阅 OpenTelemetry 概述或 OpenTelemetry 常见问题解答。
收集自定义遥测数据
本部分介绍如何从应用程序收集自定义遥测数据。
根据语言和信号类型,可以通过不同的方式收集自定义遥测数据,包括:
- 开放遥测 API
- 特定于语言的日志记录/指标库
- Application Insights 经典 API
下表显示了目前支持的自定义遥测类型:
| 语言 |
自定义事件 |
自定义指标 |
依赖项 |
异常 |
页面视图 |
请求 |
痕迹 |
|
ASP.NET Core |
|
|
|
|
|
|
|
| 开放遥测 API |
|
是 |
是 |
是 |
|
是 |
|
ILogger 应用程序接口 |
是 |
|
|
|
|
|
是 |
| 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 库自动收集的额外指标。 要详细了解如何使用指标,请参阅 Application Insights 中的指标。
OpenTelemetry API 提供六种度量工具,以涵盖各种度量方案。当在指标资源管理器中可视化指标时,需要选取正确的聚合类型。 使用 OpenTelemetry 指标 API 发送指标和使用检测库时,此要求是正确的。
下表显示了每个 OpenTelemetry 度量工具的建议聚合类型。
| OpenTelemetry 工具 |
Azure Monitor 聚合类型 |
| 计数器 |
总和 |
| 异步计数器 |
总和 |
| 直方图 |
最小值、最大值、平均值、总和和计数 |
| 异步仪表 |
平均值 |
| UpDownCounter |
总和 |
| 异步增减计数器 |
总和 |
OpenTelemetry 规范介绍了这些工具,并提供了每种工具使用的示例。
提示
直方图是最通用的,也与 Application Insights GetMetric Classic 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);
注意
Quarkus 社区支持和维护 Quarkus 扩展。 寻求帮助,请使用 Quarkus 社区支持渠道。 Azure 不提供对此集成的技术支持。
export class HistogramSample {
static async run() {
// Dynamically import Azure Monitor and metrics API
const { useAzureMonitor } = await import("@azure/monitor-opentelemetry");
const { metrics } = await import("@opentelemetry/api");
// Initialize Azure Monitor
const monitor = useAzureMonitor({
azureMonitorExporterOptions: {
connectionString:
process.env.APPLICATIONINSIGHTS_CONNECTION_STRING || "<YOUR-CONNECTION-STRING>",
},
});
// Create a histogram and record values
const meter = metrics.getMeter("testMeter");
const histogram = meter.createHistogram("histogram");
histogram.record(1, { testKey: "testValue" });
histogram.record(30, { testKey: "testValue2" });
histogram.record(100, { testKey2: "testValue" });
console.log("Histogram metrics recorded");
}
}
# 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"));
注意
Quarkus 社区支持和维护 Quarkus 扩展。 寻求帮助,请使用 Quarkus 社区支持渠道。 Azure 不提供对此集成的技术支持。
export class CounterSample {
static async run() {
// Dynamically import Azure Monitor and metrics API
const { useAzureMonitor } = await import("@azure/monitor-opentelemetry");
const { metrics } = await import("@opentelemetry/api");
// Initialize Azure Monitor
const monitor = useAzureMonitor({
azureMonitorExporterOptions: {
connectionString:
process.env.APPLICATIONINSIGHTS_CONNECTION_STRING || "<YOUR-CONNECTION-STRING>",
},
});
// Create a counter and add some sample values
const meter = metrics.getMeter("otel_azure_monitor_counter_demo");
const counter = meter.createCounter("MyFruitCounter");
counter.add(1, { name: "apple", color: "red" });
counter.add(2, { name: "lemon", color: "yellow" });
counter.add(1, { name: "lemon", color: "yellow" });
counter.add(2, { name: "apple", color: "green" });
counter.add(5, { name: "apple", color: "red" });
counter.add(4, { name: "lemon", color: "yellow" });
console.log("Counter metrics recorded");
}
}
# 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"));
});
注意
Quarkus 社区支持和维护 Quarkus 扩展。 寻求帮助,请使用 Quarkus 社区支持渠道。 Azure 不提供对此集成的技术支持。
export class GaugeSample {
static async run() {
// Dynamically import Azure Monitor and metrics API
const { useAzureMonitor } = await import("@azure/monitor-opentelemetry");
const { metrics } = await import("@opentelemetry/api");
// Initialize Azure Monitor
const monitor = useAzureMonitor({
azureMonitorExporterOptions: {
connectionString:
process.env.APPLICATIONINSIGHTS_CONNECTION_STRING || "<YOUR-CONNECTION-STRING>",
},
});
// Create an observable gauge and register a callback
const meter = metrics.getMeter("testMeter");
const gauge = meter.createObservableGauge("gauge");
gauge.addCallback((observableResult) => {
const randomNumber = Math.floor(Math.random() * 100);
observableResult.observe(randomNumber, { testKey: "testValue" });
});
console.log("Observable gauge registered");
}
}
# 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" });
}
要使用 "Activity" 来记录异常:
// 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。
export class CustomExceptionSample {
static async run() {
// Dynamically import Azure Monitor and tracing API
const { useAzureMonitor } = await import("@azure/monitor-opentelemetry");
const { trace } = await import("@opentelemetry/api");
// Initialize Azure Monitor
const monitor = useAzureMonitor({
azureMonitorExporterOptions: {
connectionString:
process.env.APPLICATIONINSIGHTS_CONNECTION_STRING || "<YOUR-CONNECTION-STRING>",
},
});
// Create a span and record an exception
const tracer = trace.getTracer("testTracer");
const span = tracer.startSpan("hello");
try {
throw new Error("Test Error");
} catch (error) {
span.recordException(error as Error);
} finally {
span.end();
}
console.log("Exception recorded on span");
}
}
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 类都必须显式地通过 AddSource() 来连接到 TracerProvider。 这是因为 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 类都必须使用 AddSource() 显式地与 TracerProvider 连接。 这是因为 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();
}
注意
Quarkus 社区支持和维护 Quarkus 扩展。 寻求帮助,请使用 Quarkus 社区支持渠道。 Azure 不提供对此集成的技术支持。
export class CustomTraceSample {
static async run() {
// Dynamically import Azure Monitor and tracing API
const { useAzureMonitor } = await import("@azure/monitor-opentelemetry");
const { trace } = await import("@opentelemetry/api");
// Initialize Azure Monitor
const monitor = useAzureMonitor({
azureMonitorExporterOptions: {
connectionString:
process.env.APPLICATIONINSIGHTS_CONNECTION_STRING || "<YOUR-CONNECTION-STRING>",
},
});
// Create a custom span, add attributes/events, then end
const tracer = trace.getTracer("otel_azure_monitor_custom_trace_demo");
const span = tracer.startSpan("doWork");
try {
span.setAttribute("component", "worker");
span.setAttribute("operation.id", "42");
span.addEvent("invoking doWork");
for (let i = 0; i < 1_000_000; i++) { /* simulate work */ }
} catch (err) {
span.recordException(err as Error);
} finally {
span.end();
}
console.log("Custom span recorded");
}
}
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。
若要使用 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。
若要使用 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属性。 还可以根据需要包含其他属性。
export class CustomEventSample {
static async run() {
// Dynamically import Azure Monitor and the OpenTelemetry logs API
const { useAzureMonitor } = await import("@azure/monitor-opentelemetry");
const { logs, SeverityNumber } = await import("@opentelemetry/api-logs");
// Initialize Azure Monitor (enables logs bridge)
const monitor = useAzureMonitor();
// Get a logger and emit a customEvent by setting the microsoft attribute key
const logger = logs.getLogger("my-app-logger");
logger.emit({
body: "Hello World!",
severityNumber: SeverityNumber.INFO,
attributes: {
"microsoft.custom_event.name": "test-event-name",
"additional_attrs": "val1",
},
});
// Example: populate client_IP via attribute 'client.address'
logger.emit({
body: "This entry will have a custom client_IP",
severityNumber: SeverityNumber.INFO,
attributes: {
"microsoft.custom_event.name": "test_event",
"client.address": "192.168.1.1",
},
});
console.log("Custom events emitted");
}
}
若要在 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");
export class SpanAttributeEnrichmentSample {
static async run() {
// Dynamically import the Azure Monitor integration
const { useAzureMonitor } = await import("@azure/monitor-opentelemetry");
// Create a SpanEnrichingProcessor to add custom dimensions
class SpanEnrichingProcessor {
forceFlush() { return Promise.resolve(); }
shutdown() { return Promise.resolve(); }
onStart() {}
onEnd(span: any) {
(span as any).attributes = (span as any).attributes || {};
(span as any).attributes["CustomDimension1"] = "value1";
(span as any).attributes["CustomDimension2"] = "value2";
}
}
// Initialize Azure Monitor with the custom processor
const monitor = useAzureMonitor({
spanProcessors: [new SpanEnrichingProcessor()],
});
console.log("Span enrichment processor registered");
}
}
使用自定义处理器:
...
# 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
可以通过在 span 上设置属性来填充请求的 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>");
使用自定义属性示例,但替换以下代码行:
export class SetUserIpSample {
static async run() {
// Dynamically import Azure Monitor and tracing API
const { useAzureMonitor } = await import("@azure/monitor-opentelemetry");
const { trace } = await import("@opentelemetry/api");
// Initialize Azure Monitor
const monitor = useAzureMonitor();
// Framework-agnostic helper to set client IP on the active server span
const setIpForRequest = (clientIp: string) => {
const span = trace.getActiveSpan();
if (span) {
// Preferred attribute for client IP
span.setAttribute("client.address", clientIp);
// Optional: legacy/alternate attribute
span.setAttribute("http.client_ip", clientIp);
}
};
// Call setIpForRequest("<IP Address>") from within your web framework's request pipeline
console.log("Use setIpForRequest('<IP Address>') inside your request handler to stamp the active span.");
}
}
使用自定义属性示例,但替换 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_AuthenticatedId)
Span.current().setAttribute("enduser.pseudo.id", "myuser"); // (user_Id)
填充 user ID、requests 或 dependencies 表中的 exceptions 字段。
在代码中设置 user_Id:
import io.opentelemetry.api.trace.Span;
Span.current().setAttribute("enduser.id", "myuser"); // (user_AuthenticatedId)
Span.current().setAttribute("enduser.pseudo.id", "myuser"); // (user_Id)
使用自定义属性示例,但替换以下代码行:
export class SetUserIdSample {
static async run() {
// Dynamically import Azure Monitor and tracing API
const { useAzureMonitor } = await import("@azure/monitor-opentelemetry");
const { trace } = await import("@opentelemetry/api");
// Initialize Azure Monitor
const monitor = useAzureMonitor();
// Framework-agnostic helper to set user identifiers on the active server span
const setUserForRequest = (authenticatedId?: string, anonymousId?: string) => {
const span = trace.getActiveSpan();
if (span) {
if (authenticatedId) span.setAttribute("enduser.id", authenticatedId); // user_AuthenticatedId
if (anonymousId) span.setAttribute("enduser.pseudo.id", anonymousId); // user_Id
}
};
// Call setUserForRequest("<authenticated-id>", "<anonymous-id>") inside your request handler
console.log("Use setUserForRequest('<auth-id>', '<anon-id>') inside your request handler to stamp the active span.");
}
}
使用自定义属性示例,但替换以下代码行:
# 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 是开箱即用的。
export class BunyanLogAttributesSample {
static async run() {
// Dynamically import Azure Monitor and Bunyan
const { useAzureMonitor } = await import("@azure/monitor-opentelemetry");
const bunyanMod = await import("bunyan");
const bunyan = (bunyanMod as any).default ?? bunyanMod;
// Enable Azure Monitor integration and bunyan instrumentation
const monitor = useAzureMonitor({
instrumentationOptions: { bunyan: { enabled: true } },
});
// Emit a log with custom attributes
const log = (bunyan as any).createLogger({ name: "testApp" });
log.info({ key1: "value1", feature: "demo" }, "Warning log with properties");
console.log("Bunyan log with attributes emitted");
}
}
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:
export class GetTraceAndSpanIdSample {
static async run() {
// Dynamically import tracing API
const { trace } = await import("@opentelemetry/api");
// Read the span/trace id from the active span (if any)
const activeSpan = trace.getActiveSpan();
const spanId = activeSpan?.spanContext().spanId;
const traceId = activeSpan?.spanContext().traceId;
console.log("SpanId:", spanId, "TraceId:", 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
后续步骤
注意
Quarkus 社区支持和维护 Quarkus 扩展。 寻求帮助,请使用 Quarkus 社区支持渠道。 Azure 不提供对此集成的技术支持。