В этом руководстве приведены инструкции по интеграции и настройке инструментирования OpenTelemetry (OTel) в Azure Monitor Application Insights.
Дополнительные сведения о концепциях OpenTelemetry см. в обзоре OpenTelemetry.
Сбор настраиваемой телеметрии
В этом разделе объясняется, как собирать пользовательские данные телеметрии из приложения.
В зависимости от языка и типа сигнала существуют различные способы сбора пользовательских данных телеметрии, в том числе:
- OpenTelemetry API
- Библиотеки логирования и метрик для конкретных языков программирования
- Классический API Application Insights
В следующей таблице представлены поддерживаемые в настоящее время пользовательские типы телеметрии:
| Язык |
Пользовательские события |
Пользовательские метрики |
Зависимости |
Исключения |
Просмотры страницы |
Запросы |
Следы |
|
ASP.NET Core |
|
|
|
|
|
|
|
| OpenTelemetry API |
|
Да |
Да |
Да |
|
Да |
|
API ILogger |
Да |
|
|
|
|
|
Да |
| Классический API ИИ |
Да |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Java |
|
|
|
|
|
|
|
| OpenTelemetry API |
Да |
Да |
Да |
Да |
|
Да |
|
Logback, Log4j, JUL |
|
|
|
Да |
|
|
Да |
| Метрики микрометра |
|
Да |
|
|
|
|
|
| Классический API ИИ |
Да |
Да |
Да |
Да |
Да |
Да |
Да |
|
|
|
|
|
|
|
|
|
Node.js |
|
|
|
|
|
|
|
| OpenTelemetry API |
Да |
Да |
Да |
Да |
|
Да |
|
|
|
|
|
|
|
|
|
|
Питон |
|
|
|
|
|
|
|
| OpenTelemetry API |
|
Да |
Да |
Да |
|
Да |
|
| Модуль ведения журнала Python |
|
|
|
|
|
|
Да |
| Расширение событий |
Да |
|
|
|
|
|
Да |
Примечание.
Application Insights Java 3.x и Application Insights Node.js 3.x собирают данные телеметрии из классического API Application Insights. Это поведение упрощает обновление и временно поддерживает настраиваемую телеметрию, пока API OpenTelemetry не включает все пользовательские типы телеметрии.
Добавление пользовательских метрик
В этом контексте термин пользовательских метрик относится к ручному инструментированию кода для сбора дополнительных метрик за пределами того, что библиотеки инструментирования OpenTelemetry автоматически собирают. Дополнительные сведения об использовании метрик см. в разделе "Метрики" в Application Insights.
API OpenTelemetry предлагает шесть инструментов для покрытия различных сценариев метрик и необходимо выбрать правильный тип агрегирования при визуализации метрик в обозревателе метрик. Это требование верно при использовании API метрик OpenTelemetry для отправки метрик и при использовании библиотеки инструментирования.
В следующей таблице показаны рекомендуемые типы агрегирования для каждого из инструментов метрик OpenTelemetry.
| Инструмент OpenTelemetry |
Тип агрегирования монитора Azure |
| Счетчик |
Сумма |
| Асинхронный счетчик |
Сумма |
| Гистограмма |
Мин, Макс, Среднее, Сумма и Количество |
| Асинхронный датчик |
Среднее |
| UpDownCounter |
Сумма |
| Асинхронный счётчик вверх-вниз |
Сумма |
Внимание
В большинстве случаев другие типы агрегирования не являются значимыми.
Спецификация OpenTelemetry описывает инструменты и предоставляет примеры использования каждого из них.
Совет
Гистограмма является самым универсальным и наиболее близким эквивалентом классическому API Application Insights GetMetric. Azure Монитор в настоящее время упрощает инструмент гистограммы в наши пять поддерживаемых типов агрегирования, и поддержка процентилей пока осуществляется. Хотя и менее универсальный, другие инструменты 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 OpenTelemetry для Python реализован таким образом, чтобы исключения автоматически фиксировались и записывались. Пример этого поведения см. в следующем примере кода:
# 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. Дополнительные сведения см. в статье Introduction to 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 представляют собой концепции OpenTelemetry Span и Tracer соответственно. Вы создаете ActivitySource непосредственно с помощью конструктора, а не с помощью TracerProvider. Каждый класс ActivitySource должен быть явно подключен к TracerProvider с помощью AddSource(). Это связано с тем, что части API трассировки OpenTelemetry включаются непосредственно в среду выполнения .NET. Дополнительные сведения см. в статье Introduction to 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.
В зависимости от того, используется ли агент Java Application Insights или пакет SDK для автоматической настройки, способ получения средства ведения журнала OpenTelemetry немного отличается. Это подробно описано в следующих примерах.
Для агента Java Application Insights:
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.
// 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.
// 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 использует .NET ILogger.
Добавление пользовательских атрибутов к логам можно осуществить с помощью шаблона для сообщения.
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");
}
}
Библиотека logging в Python является автоинструментированной. Вы можете присоединить пользовательские измерения к журналам, передав словарь в extra аргумент журналов:
...
# Create a warning log message with the properties "key1" and "value1".
logger.warning("WARNING: Warning log with properties", extra={"key1": "value1"})
...
Получение идентификатора трассировки или идентификатора диапазона
Вы можете получить Trace ID и Span ID для текущего активного промежутка, выполнив следующие действия.
Примечание.
Классы Activity и ActivitySource из пространства имен System.Diagnostics представляют собой концепции OpenTelemetry Span и Tracer соответственно. Это связано с тем, что части API трассировки OpenTelemetry включаются непосредственно в среду выполнения .NET. Дополнительные сведения см. в статье Introduction to 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. Дополнительные сведения см. в статье Introduction to 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.
Добавьте 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
Чтобы оставить отзыв, сделайте следующее:
Поддержка
Выберите вкладку для выбранного языка, чтобы узнать параметры поддержки.
Примечание.
Сообщество Quarkus поддерживает и сопровождает расширения Quarkus. Для получения справки используйте каналы поддержки сообщества Quarkus. Корпорация Майкрософт не предоставляет техническую поддержку этой интеграции.
Следующие шаги