В этом руководстве приведены инструкции по интеграции и настройке инструментирования OpenTelemetry (OTel) в Azure Monitor Application Insights.
Дополнительные сведения о концепциях OpenTelemetry см. в обзоре OpenTelemetry.
Чтобы получить общие сведения обо всех библиотеках инструментирования, включенных в дистрибутив Azure Monitor OpenTelemetry, ознакомьтесь с разделом Automatic data collection and resource detectors for Azure Monitor OpenTelemetry.
Вы можете автоматически собирать дополнительные данные при включении библиотек инструментирования из сообщества OpenTelemetry.
Внимание
Мы не поддерживаем и не гарантируем качество библиотек инструментов от сообщества. Чтобы предложить один для нашего дистрибутива, опубликуйте сообщение или проголосуйте в нашем сообществе обратной связи. Имейте в виду, что некоторые из них основаны на экспериментальных спецификациях OpenTelemetry и могут вызвать критические изменения в будущем.
Чтобы добавить библиотеку сообщества, используйте ConfigureOpenTelemetryMeterProviderConfigureOpenTelemetryTracerProvider методы после добавления пакета NuGet для библиотеки.
В следующем примере показано, как добавить инструментирование среды выполнения для сбора дополнительных метрик:
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.
Вы не можете использовать библиотеки инструментирования от сообщества с нативными Java приложениями GraalVM.
export class RegisterExpressInstrumentationSample {
static async run() {
// Dynamically import Azure Monitor and Express instrumentation
const { useAzureMonitor } = await import("@azure/monitor-opentelemetry");
const { registerInstrumentations } = await import("@opentelemetry/instrumentation");
const { ExpressInstrumentation } = await import("@opentelemetry/instrumentation-express");
// Initialize Azure Monitor (uses env var if set)
const monitor = useAzureMonitor();
// Register the Express instrumentation
registerInstrumentations({
instrumentations: [new ExpressInstrumentation()],
});
console.log("Express instrumentation registered");
}
}
Чтобы добавить библиотеку инструментирования сообщества, инструментируйте её напрямую. Список библиотек инструментирования сообщества можно найти в GitHub.
Примечание.
Не используйте и дистрибутив 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())
Сбор настраиваемой телеметрии
В этом разделе объясняется, как собирать пользовательские данные телеметрии из приложения.
В зависимости от языка и типа сигнала существуют различные способы сбора пользовательских данных телеметрии, в том числе:
- OpenTelemetry API
- Библиотеки логирования и метрик для конкретных языков программирования
- Классический API Application Insights
Примечание.
API трассировки Micrometer для Java не поддерживается.
В следующей таблице представлены поддерживаемые в настоящее время пользовательские типы телеметрии:
| Язык |
Пользовательские события |
Пользовательские метрики |
Зависимости |
Исключения |
Просмотры страницы |
Запросы |
Следы |
|
ASP.NET Core |
|
|
|
|
|
|
|
| OpenTelemetry API |
|
Да |
Да |
Да |
|
Да |
|
API ILogger |
Да |
|
|
|
|
|
Да |
| Классический API ИИ |
Да |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Java |
|
|
|
|
|
|
|
| OpenTelemetry API |
Да |
Да |
Да |
Да |
|
Да |
|
Logback, Log4j, JUL |
|
|
|
Да |
|
|
Да |
| Метрики микрометра |
|
Да |
|
|
|
|
|
| Классический API ИИ |
Да |
Да |
Да |
Да |
Да |
Да |
Да |
|
|
|
|
|
|
|
|
|
Node.js |
|
|
|
|
|
|
|
| OpenTelemetry API |
Да |
Да |
Да |
Да |
|
Да |
|
|
|
|
|
|
|
|
|
|
Python |
|
|
|
|
|
|
|
| OpenTelemetry API |
|
Да |
Да |
Да |
|
Да |
|
| модуль ведения журнала Python |
|
|
|
|
|
|
Да |
| Расширение событий |
Да |
|
|
|
|
|
Да |
Примечание.
Application Insights Java 3.x и Application Insights Node.js 3.x собирают данные телеметрии из API Application Insights Classic API. Это поведение упрощает обновление и временно поддерживает настраиваемую телеметрию, пока API OpenTelemetry не включает все пользовательские типы телеметрии.
Добавление пользовательских метрик
В этом контексте термин пользовательских метрик относится к ручному инструментированию кода для сбора дополнительных метрик за пределами того, что библиотеки инструментирования OpenTelemetry автоматически собирают. Дополнительные сведения об использовании метрик см. в разделе "Метрики" в Application Insights.
API OpenTelemetry предлагает шесть инструментов для покрытия различных сценариев метрик и необходимо выбрать правильный тип агрегирования при визуализации метрик в обозревателе метрик. Это требование верно при использовании API метрик OpenTelemetry для отправки метрик и при использовании библиотеки инструментирования.
В следующей таблице показаны рекомендуемые типы агрегирования для каждого из инструментов метрик OpenTelemetry.
| Инструмент OpenTelemetry |
тип агрегирования Azure Monitor |
| Счетчик |
Сумма |
| Асинхронный счетчик |
Сумма |
| Гистограмма |
Мин, Макс, Среднее, Сумма и Количество |
| Асинхронный датчик |
Среднее |
| UpDownCounter |
Сумма |
| Асинхронный счётчик вверх-вниз |
Сумма |
Внимание
В большинстве случаев другие типы агрегирования не являются значимыми.
Спецификация OpenTelemetry описывает инструменты и предоставляет примеры использования каждого из них.
Совет
Гистограмма является самым универсальным и наиболее близким эквивалентом классическому API Application Insights GetMetric. 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. Майкрософт не предоставляет техническую поддержку этой интеграции.
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. Майкрософт не предоставляет техническую поддержку этой интеграции.
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. Майкрософт не предоставляет техническую поддержку этой интеграции.
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" });
}
Чтобы записать исключение с помощью действия:
// 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);
Пакет SDK Node.js экспортирует вручную зарегистрированные исключения, основанные на интервалах, в 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");
}
}
SDK для Python в OpenTelemetry реализован таким образом, что возникающие исключения автоматически перехватываются и записываются. Пример этого поведения см. в следующем примере кода:
# 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 представляют собой концепции OpenTelemetry Span и Tracer соответственно. Вы создаете ActivitySource непосредственно с помощью конструктора, а не с помощью TracerProvider. Каждый класс ActivitySource должен быть явно подключен к TracerProvider с помощью AddSource(). Это связано с тем, что части API трассировки OpenTelemetry включаются непосредственно в среду выполнения .NET. Дополнительные сведения см. в статье API трассировки OpenTelemetry для .NET.
// 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 представляют собой концепции OpenTelemetry Span и Tracer соответственно. Вы создаете ActivitySource непосредственно с помощью конструктора, а не с помощью TracerProvider. Каждый класс ActivitySource должен быть явно подключен к TracerProvider с помощью AddSource(). Это связано с тем, что части API трассировки OpenTelemetry включаются непосредственно в среду выполнения .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.
Диапазоны заполняют таблицы requests и dependencies в Application Insights.
Добавьте 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() {
}
По умолчанию диапазон оказывается в таблице с типом зависимости dependenciesInProc.
Для методов, представляющих фоновую задачу, не охватываемую автоинструментацией, рекомендуется применять атрибут kind = SpanKind.SERVER к аннотации @WithSpan, чтобы убедиться, что они отображаются в таблице requests Application Insights.
Использование API OpenTelemetry
Если предыдущая заметка OpenTelemetry @WithSpan не соответствует вашим потребностям, можно добавить диапазоны с помощью API OpenTelemetry.
Добавьте 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. Майкрософт не предоставляет техническую поддержку этой интеграции.
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");
}
}
API OpenTelemetry можно использовать для добавления собственных спанов, которые отображаются в таблицах requests и dependencies в Application Insights.
В примере кода показано, как использовать 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.
Если вы хотите автоматизировать коллекцию событий взаимодействия на стороне клиента, можно использовать подключаемый модуль в пакете SDK javaScript.
События настраиваются с помощью 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");
Чтобы отправить customEvent с агентом Java, задайте атрибут "microsoft.custom_event.name" в записи журнала OpenTelemetry.
В зависимости от того, используется ли агент 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();
Чтобы надежно выдавать пользовательские события, используйте API OpenTelemetry напрямую. Некоторые платформы ведения журнала не поддерживают добавление или анализ настраиваемого атрибута событий.
Невозможно отправить customEvent с помощью атрибута "microsoft.custom_event.name" в нативной среде Java.
Чтобы отправить 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");
}
}
Чтобы отправить customEvent в Python, используйте библиотеку ведения журнала с атрибутом "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 в таблице запросов, зависимостей, трассировок или исключений.
Чтобы добавить атрибуты диапазона, используйте один из следующих двух способов:
Совет
Преимущество использования параметров, предоставляемых библиотеками инструментирования, когда они доступны, заключается в том, что доступен весь контекст. В результате пользователи могут добавить или отфильтровать дополнительные атрибуты. Например, опция обогащения в библиотеке инструментирования HttpClient предоставляет пользователям доступ к HttpRequestMessage и HttpResponseMessage. Они могут выбрать что-нибудь из него и сохранить его как атрибут.
Многие библиотеки инструментов предоставляют опцию расширения. Для получения инструкции см. файлы README отдельных библиотек инструментирования.
Использование пользовательского процессора:
Совет
Добавьте процессор, показанный здесь, перед добавлением 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 в project с помощью следующего кода:
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");
}
}
Чтобы добавить атрибуты диапазона, используйте один из следующих двух способов:
- Используйте параметры, предоставляемые библиотеками инструментирования.
- Добавьте пользовательский процессор span.
Совет
Преимущество использования параметров, предоставляемых библиотеками инструментирования, когда они доступны, заключается в том, что доступен весь контекст. В результате пользователи могут добавить или отфильтровать дополнительные атрибуты. Например, параметр обогащения в библиотеке инструментирования HttpClient предоставляет пользователям доступ к самому httpRequestMessage. Они могут выбрать что-нибудь из него и сохранить его как атрибут.
Многие библиотеки инструментов предоставляют опцию расширения. Для получения инструкции см. файлы README отдельных библиотек инструментирования.
Использование пользовательского процессора:
Совет
Добавьте процессор, показанный здесь, перед экспортером 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 в project с помощью следующего кода:
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 в project с помощью следующего кода:
# 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>");
Java автоматически заполняет это поле.
Это поле заполняется автоматически.
Используйте пример пользовательского свойства, но замените следующие строки кода:
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>"
Установка идентификатора пользователя или идентификатора пользователя, прошедшего проверку подлинности
Вы можете заполнить поле user_Id или user_AuthenticatedId для запросов с помощью следующего руководства. Идентификатор пользователя — это анонимный идентификатор пользователя. Идентификатор пользователя, прошедший проверку подлинности, является известным идентификатором пользователя.
Внимание
Перед настройкой идентификатора пользователя с проверкой подлинности обратитесь к применимым законам о конфиденциальности.
Используйте пример пользовательского свойства:
// 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 использует .NETILogger.
Добавление пользовательских атрибутов к логам можно осуществить с помощью шаблона для сообщения.
OpenTelemetry использует .NET ILogger.
Добавление пользовательских атрибутов к логам можно осуществить с помощью шаблона для сообщения.
Logback, Log4j и java.util.log автоматически инструментируются. Присоединение пользовательских измерений к журналам можно сделать следующим образом:
Для собственных приложений 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 logging автоматически инструментирована. Вы можете присоединить пользовательские измерения к журналам, передав словарь в extra аргумент журналов:
...
# Create a warning log message with the properties "key1" and "value1".
logger.warning("WARNING: Warning log with properties", extra={"key1": "value1"})
...
Переопределение статуса ошибки запроса для ответов HTTP 4xx
Вы можете запретить Application Insights считать ответы 4xx как ошибки.
В следующем коде показан настраиваемый обработчик действий, который помечает ответы HTTP 4xx как успешные.
Процессор:
public class Http4xxSuccessProcessor : BaseProcessor<Activity>
{
public override void OnEnd(Activity activity)
{
if (activity.Kind == ActivityKind.Server)
{
var statusCodeTag = activity.GetTagItem("http.response.status_code");
if (statusCodeTag is int statusCode && statusCode >= 400 && statusCode < 500)
{
// Set status to Ok to bypass the Azure Monitor exporter's default logic
// which treats any HTTP 4xx as failure when status is Unset.
// The response code tag (e.g., 400) remains unchanged — only the
// success field in Application Insights is affected.
activity.SetStatus(ActivityStatusCode.Ok);
}
}
base.OnEnd(activity);
}
}
Регистрации:
builder.Services.AddOpenTelemetry()
.UseAzureMonitor(options =>
{
options.ConnectionString = "<your-connection-string>";
})
.WithTracing(tracing =>
{
// Add custom processor to mark 4xx responses as successful
tracing.AddProcessor<Http4xxSuccessProcessor>();
});
Следующий код предназначен для пользовательского обработчика действий, который помечает ответы HTTP 4xx как успешные.
Процессор:
public class Http4xxSuccessProcessor : BaseProcessor<Activity>
{
public override void OnEnd(Activity activity)
{
if (activity.Kind == ActivityKind.Server)
{
var statusCodeTag = activity.GetTagItem("http.response.status_code");
if (statusCodeTag is int statusCode && statusCode >= 400 && statusCode < 500)
{
// Set status to Ok to bypass the Azure Monitor exporter's default logic
// which treats any HTTP 4xx as failure when status is Unset.
// The response code tag (e.g., 400) remains unchanged — only the
// success field in Application Insights is affected.
activity.SetStatus(ActivityStatusCode.Ok);
}
}
base.OnEnd(activity);
}
}
Регистрации:
using System.Diagnostics;
using OpenTelemetry;
using OpenTelemetry.Trace;
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
// Add the processor before the exporter
.AddProcessor(new Http4xxSuccessProcessor())
.AddAzureMonitorTraceExporter(options =>
{
options.ConnectionString = "<your-connection-string>";
})
.Build();
Примечание.
Эта функция доступна начиная с Java агента версии 3.3.0.
По умолчанию агент записывает HTTP-запросы сервера, которые приводят к ошибкам в кодах ответов 4xx. Это поведение можно изменить, чтобы записать их как успешные:
{
"preview": {
"captureHttpServer4xxAsError": false
}
}
Процессор:
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.trace.ReadWriteSpan;
import io.opentelemetry.sdk.trace.ReadableSpan;
import io.opentelemetry.sdk.trace.internal.ExtendedSpanProcessor;
import java.util.Set;
public final class Http4xxAsSuccessProcessor implements ExtendedSpanProcessor {
private static final AttributeKey<Long> HTTP_RESPONSE_STATUS_CODE =
AttributeKey.longKey("http.response.status_code");
// Deprecated semconv attribute that some libraries may still emit
private static final AttributeKey<Long> HTTP_STATUS_CODE =
AttributeKey.longKey("http.status_code");
private static final AttributeKey<Boolean> MODIFIED_FLAG =
AttributeKey.booleanKey("ai.modified.http4xx.success");
private final Set<Long> keepAsFailure = Set.of(429L);
@Override
public void onStart(Context parentContext, ReadWriteSpan span) {
// No-op
}
@Override
public boolean isStartRequired() {
return false;
}
@Override
public void onEnding(ReadWriteSpan span) {
if (span.getKind() != SpanKind.SERVER) {
return;
}
Long statusCode = span.getAttribute(HTTP_RESPONSE_STATUS_CODE);
if (statusCode == null) {
statusCode = span.getAttribute(HTTP_STATUS_CODE);
}
if (statusCode != null
&& statusCode >= 400
&& statusCode < 500
&& !keepAsFailure.contains(statusCode)) {
// Keep the HTTP status code attribute unchanged, but mark the span as OK
// so downstream backends such as Application Insights don't count it as a failure.
span.setStatus(StatusCode.OK);
span.setAttribute(MODIFIED_FLAG, true);
}
}
@Override
public boolean isOnEndingRequired() {
return true;
}
@Override
public void onEnd(ReadableSpan span) {
// No-op
}
@Override
public boolean isEndRequired() {
return false;
}
@Override
public CompletableResultCode shutdown() {
return CompletableResultCode.ofSuccess();
}
@Override
public CompletableResultCode forceFlush() {
return CompletableResultCode.ofSuccess();
}
}
Регистрация (Spring Boot):
import com.azure.monitor.opentelemetry.autoconfigure.AzureMonitorAutoConfigure;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder;
public class TelemetryConfiguration {
public static OpenTelemetry configureOpenTelemetry() {
AutoConfiguredOpenTelemetrySdkBuilder sdkBuilder = AutoConfiguredOpenTelemetrySdk.builder();
AzureMonitorAutoConfigure.customize(sdkBuilder, "<your-connection-string>");
sdkBuilder.addTracerProviderCustomizer(
(tracerProviderBuilder, configProperties) ->
tracerProviderBuilder.addSpanProcessor(new Http4xxAsSuccessProcessor())
);
return sdkBuilder.build().getOpenTelemetrySdk();
}
}
Регистрация (Quarkus):
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class Http4xxAsSuccessProcessor extends Http4xxAsSuccessProcessorBase {
}
import { SpanKind, SpanStatusCode } from "@opentelemetry/api";
import { SpanProcessor, ReadableSpan } from "@opentelemetry/sdk-trace-base";
import { ATTR_HTTP_RESPONSE_STATUS_CODE } from "@opentelemetry/semantic-conventions";
// Deprecated semconv attribute; not exported from the stable entry point.
const ATTR_HTTP_STATUS_CODE = "http.status_code";
export class Http4xxAsSuccessProcessor implements SpanProcessor {
private keepAsFailure = new Set<number>(/* [429] */);
onStart(): void {}
onEnd(span: ReadableSpan): void {
if (span.kind !== SpanKind.SERVER) return;
const attrs = span.attributes;
const sc =
(attrs[ATTR_HTTP_RESPONSE_STATUS_CODE] as number | undefined) ??
(attrs[ATTR_HTTP_STATUS_CODE] as number | undefined);
if (
typeof sc === "number" &&
sc >= 400 &&
sc < 500 &&
!this.keepAsFailure.has(sc)
) {
// By onEnd the span is ended, so setStatus()/setAttribute() are no-ops.
// Directly mutate the backing fields so the exporter sees the change.
(span as any).status = { code: SpanStatusCode.OK };
(span as any).attributes = {
...attrs,
"ai.modified.http4xx.success": true,
};
console.log(`[Processor] Rewrote ${sc} span to OK`);
}
}
shutdown(): Promise<void> {
return Promise.resolve();
}
forceFlush(): Promise<void> {
return Promise.resolve();
}
}
Процессор:
from __future__ import annotations
from typing import Iterable, Optional
from opentelemetry.trace import SpanKind, Status, StatusCode
from opentelemetry.sdk.trace import ReadableSpan, SpanProcessor
# Current HTTP semconv attribute
ATTR_HTTP_RESPONSE_STATUS_CODE = "http.response.status_code"
# Older / deprecated attribute that some instrumentations may still emit
ATTR_HTTP_STATUS_CODE = "http.status_code"
class Http4xxAsSuccessProcessor(SpanProcessor):
def __init__(self, keep_as_failure: Optional[Iterable[int]] = None) -> None:
# Example: keep 429 as a failure if you want throttling to remain visible
# self._keep_as_failure = set(keep_as_failure or {429})
def on_start(self, span, parent_context=None) -> None:
# No-op
return
def on_end(self, span: ReadableSpan) -> None:
if span.kind is not SpanKind.SERVER:
return
attrs = span.attributes
status_code = attrs.get(
ATTR_HTTP_RESPONSE_STATUS_CODE,
attrs.get(ATTR_HTTP_STATUS_CODE),
)
if (
isinstance(status_code, int)
and 400 <= status_code < 500
and status_code not in self._keep_as_failure
):
# ReadableSpan.status is read-only, so in current released SDKs
# we mutate the private backing field that the exporter reads.
span._status = Status(StatusCode.OK) # pylint: disable=protected-access
# Optional diagnostic marker so you can tell the processor rewrote it.
# ReadableSpan.attributes returns a read-only MappingProxyType, so we
# update the private backing store instead.
if getattr(span, "_attributes", None) is None:
span._attributes = {} # pylint: disable=protected-access
try:
span._attributes["ai.modified.http4xx.success"] = True # pylint: disable=protected-access
except TypeError:
# Fallback if the backing store is not directly writable
span._attributes = dict(span.attributes) # pylint: disable=protected-access
span._attributes["ai.modified.http4xx.success"] = True # pylint: disable=protected-access
def shutdown(self) -> None:
return
def force_flush(self, timeout_millis: int = 30000) -> bool:
return True
Регистрации:
from azure.monitor.opentelemetrgit import configure_azure_monitor
configure_azure_monitor(
connection_string="<your-connection-string>",
span_processors=[Http4xxAsSuccessProcessor()],
)
Получение идентификатора трассировки или идентификатора диапазона
Получите Trace ID и Span ID для текущего активного диапазона, выполнив следующие действия.
Примечание.
Классы Activity и ActivitySource из пространства имен System.Diagnostics представляют собой концепции OpenTelemetry Span и Tracer соответственно. Это связано с тем, что части API трассировки OpenTelemetry включаются непосредственно в среду выполнения .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 представляют собой концепции OpenTelemetry Span и Tracer соответственно. Это связано с тем, что части API трассировки OpenTelemetry включаются непосредственно в среду выполнения .NET. Дополнительные сведения см. в статье Введение в OpenTelemetry .NET Tracing 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.
Добавьте 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;
Span span = Span.current();
String traceId = span.getSpanContext().getTraceId();
String spanId = span.getSpanContext().getSpanId();
Получите идентификатор трассировки запроса и идентификатор диапазона в коде:
import io.opentelemetry.api.trace.Span;
Span span = Span.current();
String traceId = span.getSpanContext().getTraceId();
String spanId = span.getSpanContext().getSpanId();
Получите идентификатор трассировки запроса и идентификатор диапазона в коде:
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);
}
}
Получите идентификатор трассировки запроса и идентификатор диапазона в коде:
# 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
Устранение неполадок, обратная связь и поддержка
Совет
Во всех статьях о дистрибутивах OpenTelemetry доступны следующие разделы.
Troubleshooting
Отзывы о OpenTelemetry
Чтобы оставить отзыв, сделайте следующее:
Поддержка
Выберите вкладку для выбранного языка, чтобы узнать параметры поддержки.
- Для проблем с поддержкой Azure откройте запрос поддержка Azure.
- Если у вас возникли проблемы с OpenTelemetry, обратитесь непосредственно к сообществу OpenTelemetry .NET.
- Список открытых задач, связанных с Azure Monitor Exporter, см. на странице GitHub Issues.
- Для проблем с поддержкой Azure откройте запрос поддержка Azure.
- Если у вас возникли проблемы с OpenTelemetry, обратитесь непосредственно к сообществу OpenTelemetry .NET.
- Список открытых задач, связанных с Azure Monitor Exporter, см. на странице GitHub Issues.
- Для проблем с поддержкой Azure откройте запрос поддержка Azure.
- Для проблем с OpenTelemetry обратитесь непосредственно к сообществу OpenTelemetry .
- Список открытых проблем с нативными приложениями Spring Boot см. на странице GitHub Issues.
- Список открытых проблем с собственными приложениями Quarkus см. на странице проблем GitHub.
Примечание.
Сообщество Quarkus поддерживает и сопровождает расширения Quarkus. Для получения справки используйте каналы поддержки сообщества Quarkus. Майкрософт не предоставляет техническую поддержку этой интеграции.
Следующие шаги