Habilitación de OpenTelemetry en Azure Monitor para aplicaciones de .NET, Node.js y Python (versión preliminar)
Artículo
Tiempo de lectura: 38 minutos
El Exportador de OpenTelemetry en Azure Monitor es un componente que envía seguimientos y métricas (y, a la larga, toda la telemetría de la aplicación) a Application Insights de Azure Monitor. Para obtener más información sobre conceptos de OpenTelemetry, consulte Introducción a OpenTelemetry o las preguntas más frecuentes sobre el estándar.
En este artículo se explica cómo habilitar y configurar la oferta en versión preliminar de OpenTelemetry en Azure Monitor. Cuando termine de leer las instrucciones de este artículo, podrá enviar seguimientos y métricas de OpenTelemetry a Application Insights de Azure Monitor.
Importante
La oferta de OpenTelemetry en Azure Monitor para aplicaciones de .NET, Node.js y Python se encuentra actualmente en versión preliminar.
Consulte Términos de uso complementarios para las versiones preliminares de Microsoft Azure para conocer los términos legales que se aplican a las características de Azure que se encuentran en la versión beta, en versión preliminar o que todavía no se han publicado para que estén disponibles con carácter general.
Reflexione sobre si esta versión preliminar satisface sus necesidades. Esta versión habilita el seguimiento distribuido, las métricas y excluye lo siguiente:
Status admite statuscode(unset,ok,error) y status-description. Los Exportadores de Azure Monitor omiten la "Descripción del estado".
Si necesita una experiencia con todas las características, use el SDK existente de ASP.NET o ASP.NET Core de Application Insights hasta que la oferta de OpenTelemetry esté más madura.
Reflexione sobre si esta versión preliminar satisface sus necesidades. Esta versión habilita el seguimiento distribuido, las métricas y excluye lo siguiente:
Reflexione sobre si esta versión preliminar satisface sus necesidades. Esta versión habilita el seguimiento distribuido, las métricas y excluye lo siguiente:
Reflexione sobre si esta versión preliminar satisface sus necesidades. Esta versión habilita el seguimiento distribuido, las métricas y excluye lo siguiente:
Si recibe un error como "No hay ninguna versión disponible del paquete "Azure.Monitor.OpenTelemetry.Exporter", probablemente se deba a que falta el valor de los orígenes del paquete NuGet. Pruebe a especificar el origen con la opción -s:
# Install the latest package with the NuGet package source specified.
dotnet add package --prerelease Azure.Monitor.OpenTelemetry.Exporter -s https://api.nuget.org/v3/index.json
En el siguiente código se muestra cómo habilitar OpenTelemetry en una aplicación de consola de C# configurando OpenTelemetry TracerProvider. Este código debe estar en el inicio de la aplicación. En el caso de ASP.NET Core, suele realizarse en el método ConfigureServices de la clase Startup de la aplicación. En el caso de las aplicaciones ASP.NET, suele realizarse en Global.asax.cs.
using System.Diagnostics;
using Azure.Monitor.OpenTelemetry.Exporter;
using OpenTelemetry;
using OpenTelemetry.Trace;
public class Program
{
private static readonly ActivitySource MyActivitySource = new ActivitySource(
"OTel.AzureMonitor.Demo");
public static void Main()
{
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("OTel.AzureMonitor.Demo")
.AddAzureMonitorTraceExporter(o =>
{
o.ConnectionString = "<Your Connection String>";
})
.Build();
using (var activity = MyActivitySource.StartActivity("TestActivity"))
{
activity?.SetTag("CustomTag1", "Value1");
activity?.SetTag("CustomTag2", "Value2");
}
System.Console.WriteLine("Press Enter key to exit.");
System.Console.ReadLine();
}
}
Nota
Las clases Activity y ActivitySource del espacio de nombres System.Diagnostics representan respectivamente los conceptos de Span y Tracer de OpenTelemetry. Para crear ActivitySource directamente, use su constructor en lugar de TracerProvider. Cada clase ActivitySource debe estar conectada explícitamente a TracerProvider mediante AddSource(). El motivo es que algunas partes de la API de seguimiento de OpenTelemetry se incorporan directamente al runtime de .NET. Para más información, vea Introducción a la API de seguimiento de .NET OpenTelemetry.
En el siguiente código se muestra cómo habilitar OpenTelemetry en una aplicación de JavaScript sencilla:
const { AzureMonitorTraceExporter } = require("@azure/monitor-opentelemetry-exporter");
const { BatchSpanProcessor } = require("@opentelemetry/sdk-trace-base");
const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node");
const { context, trace } = require("@opentelemetry/api")
const provider = new NodeTracerProvider();
provider.register();
// Create an exporter instance.
const exporter = new AzureMonitorTraceExporter({
connectionString: "<Your Connection String>"
});
// Add the exporter to the provider.
provider.addSpanProcessor(
new BatchSpanProcessor(exporter)
);
// Create a tracer.
const tracer = trace.getTracer("example-basic-tracer-node");
// Create a span. A span must be closed.
const parentSpan = tracer.startSpan("main");
for (let i = 0; i < 10; i += 1) {
doWork(parentSpan);
}
// Be sure to end the span.
parentSpan.end();
function doWork(parent) {
// Start another span. In this example, the main method already started a
// span, so that will be the parent span, and this will be a child span.
const ctx = trace.setSpan(context.active(), parent);
// Set attributes to the span.
// Check the SpanOptions interface for more options that can be set into the span creation
const spanOptions = {
attributes: {
"key": "value"
}
};
const span = tracer.startSpan("doWork", spanOptions, ctx);
// Simulate some random work.
for (let i = 0; i <= Math.floor(Math.random() * 40000000); i += 1) {
// empty
}
// Annotate our span to capture metadata about our operation.
span.addEvent("invoking doWork");
// Mark the end of span execution.
span.end();
}
En el siguiente código se muestra cómo habilitar OpenTelemetry en una aplicación de TypeScript sencilla:
import { AzureMonitorTraceExporter } from "@azure/monitor-opentelemetry-exporter";
import { BatchSpanProcessor} from "@opentelemetry/sdk-trace-base";
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
import { Context, context, Span, SpanOptions, trace, Tracer } from "@opentelemetry/api";
const provider = new NodeTracerProvider();
provider.register();
// Create an exporter instance.
const exporter = new AzureMonitorTraceExporter({
connectionString: "<Your Connection String>"
});
// Add the exporter to the provider.
provider.addSpanProcessor(
new BatchSpanProcessor(exporter)
);
// Create a tracer.
const tracer: Tracer = trace.getTracer("example-basic-tracer-node");
// Create a span. A span must be closed.
const parentSpan: Span = tracer.startSpan("main");
for (let i = 0; i < 10; i += 1) {
doWork(parentSpan);
}
// Be sure to end the span.
parentSpan.end();
function doWork(parent: Span) {
// Start another span. In this example, the main method already started a
// span, so that will be the parent span, and this will be a child span.
const ctx: Context = trace.setSpan(context.active(), parent);
// Set attributes to the span.
// Check the SpanOptions interface for more options that can be set into the span creation
const options: SpanOptions = {
attributes: {
"key": "value"
}
};
// Create a span and attach the span options and parent span context.
const span: Span = tracer.startSpan("doWork", options, ctx);
// Simulate some random work.
for (let i = 0; i <= Math.floor(Math.random() * 40000000); i += 1) {
// empty
}
// Annotate our span to capture metadata about our operation.
span.addEvent("invoking doWork");
// Mark the end of span execution.
span.end();
}
En el siguiente código se muestra cómo habilitar OpenTelemetry en una aplicación de Python sencilla:
import os
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from azure.monitor.opentelemetry.exporter import AzureMonitorTraceExporter
exporter = AzureMonitorTraceExporter(connection_string="<Your Connection String>")
trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)
span_processor = BatchSpanProcessor(exporter)
trace.get_tracer_provider().add_span_processor(span_processor)
with tracer.start_as_current_span("hello"):
print("Hello, World!")
Sugerencia
Agregue bibliotecas de instrumentación para recopilar automáticamente datos de telemetría en marcos y bibliotecas populares.
Establecimiento de la cadena de conexión de Application Insights
Reemplace el marcador de posición <Your Connection String> del código anterior por la cadena de conexión de su recurso de Application Insights.
Confirmación de que los datos fluyen
Ejecute la aplicación y abra la pestaña Recurso de Application Insights en Azure Portal. Los datos pueden tardar unos minutos en aparecer en el portal.
Nota
Si no puede ejecutar la aplicación o no obtiene datos según lo esperado, consulte Solución de problemas.
Importante
Si tiene dos o más servicios que emiten datos de telemetría al mismo recurso de Application Insights, es obligatorio establecer nombres de rol en la nube para representarlos correctamente en el mapa de aplicación.
Como parte del uso de la instrumentación de Application Insights, se recopilan y envían datos de diagnóstico a Microsoft. Estos datos ayudan a ejecutar y mejorar Application Insights. Puede deshabilitar la recopilación de datos no esenciales. Para obtener más información, consulte Statsbeat en Azure Application Insights.
Establecimiento del nombre y la instancia de rol en la nube
Puede establecer el nombre y la instancia de rol en la nube mediante los atributos de Recurso. Este paso actualiza los valores predeterminados del nombre y la instancia de rol en la nube a algo que tenga sentido para su equipo. Estos valores aparecerán en el mapa de aplicación como el nombre debajo de un nodo. El nombre de rol en la nube usa los atributos service.namespace y service.name, aunque recurre a service.name si no se establece service.namespace. Instancia de rol en la nube usa el valor del atributo service.instance.id.
// Setting role name and role instance
var resourceAttributes = new Dictionary<string, object> {
{ "service.name", "my-service" },
{ "service.namespace", "my-namespace" },
{ "service.instance.id", "my-instance" }};
var resourceBuilder = ResourceBuilder.CreateDefault().AddAttributes(resourceAttributes);
// Done setting role name and role instance
// Set ResourceBuilder on the provider.
var tracerProvider = Sdk.CreateTracerProviderBuilder()
.SetResourceBuilder(resourceBuilder)
.AddSource("OTel.AzureMonitor.Demo")
.AddAzureMonitorTraceExporter(o =>
{
o.ConnectionString = "<Your Connection String>";
})
.Build();
...
const { Resource } = require("@opentelemetry/resources");
const { SemanticResourceAttributes } = require("@opentelemetry/semantic-conventions");
const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node");
const { MeterProvider } = require("@opentelemetry/sdk-metrics")
// ----------------------------------------
// Setting role name and role instance
// ----------------------------------------
const testResource = new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: "my-helloworld-service",
[SemanticResourceAttributes.SERVICE_NAMESPACE]: "my-namespace",
[SemanticResourceAttributes.SERVICE_INSTANCE_ID]: "my-instance",
});
// ----------------------------------------
// Done setting role name and role instance
// ----------------------------------------
const tracerProvider = new NodeTracerProvider({
resource: testResource
});
const meterProvider = new MeterProvider({
resource: testResource
});
import { Resource } from "@opentelemetry/resources";
import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";
import { NodeTracerConfig, NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
import { MeterProvider, MeterProviderOptions } from "@opentelemetry/sdk-metrics";
// ----------------------------------------
// Setting role name and role instance
// ----------------------------------------
const testResource = new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: "my-helloworld-service",
[SemanticResourceAttributes.SERVICE_NAMESPACE]: "my-namespace",
[SemanticResourceAttributes.SERVICE_INSTANCE_ID]: "my-instance",
});
const tracerProviderConfig: NodeTracerConfig = {
resource: testResource
};
const meterProviderConfig: MeterProviderOptions = {
resource: testResource
};
// ----------------------------------------
// Done setting role name and role instance
// ----------------------------------------
const tracerProvider = new NodeTracerProvider(tracerProviderConfig);
const meterProvider = new MeterProvider(meterProviderConfig);
...
...
from opentelemetry.sdk.resources import SERVICE_NAME, SERVICE_NAMESPACE, SERVICE_INSTANCE_ID, Resource
trace.set_tracer_provider(
TracerProvider(
resource=Resource.create(
{
SERVICE_NAME: "my-helloworld-service",
# ----------------------------------------
# Setting role name and role instance
# ----------------------------------------
SERVICE_NAMESPACE: "my-namespace",
SERVICE_INSTANCE_ID: "my-instance",
# ----------------------------------------------
# Done setting role name and role instance
# ----------------------------------------------
}
)
)
)
...
Es posible que quiera habilitar el muestreo para reducir el volumen de ingesta de datos, lo que reduce el coste. Azure Monitor proporciona un muestreo personalizado de frecuencia fija que rellena los eventos con una "relación de muestreo", que Application Insights convierte en "ItemCount". El muestreo de frecuencia fija garantiza experiencias y recuentos de eventos precisos. El muestreo está diseñado para conservar los seguimientos entre servicios y es interoperable con SDK más antiguos de Application Insights. El muestreo espera una frecuencia de muestreo de entre 0 y 1 inclusive. Una tasa de 0,1 significa que se enviará aproximadamente el 10 % de los seguimientos. Para más información, consulte Más información sobre el muestreo.
const { BasicTracerProvider, SimpleSpanProcessor } = require("@opentelemetry/sdk-trace-base");
const { ApplicationInsightsSampler, AzureMonitorTraceExporter } = require("@azure/monitor-opentelemetry-exporter");
// Sampler expects a sample rate of between 0 and 1 inclusive
// A rate of 0.1 means approximately 10% of your traces are sent
const aiSampler = new ApplicationInsightsSampler(0.75);
const provider = new BasicTracerProvider({
sampler: aiSampler
});
const exporter = new AzureMonitorTraceExporter({
connectionString: "<Your Connection String>"
});
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
provider.register();
import { BasicTracerProvider, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base";
import { ApplicationInsightsSampler, AzureMonitorTraceExporter } from "@azure/monitor-opentelemetry-exporter";
// Sampler expects a sample rate of between 0 and 1 inclusive
// A rate of 0.1 means approximately 10% of your traces are sent
const aiSampler = new ApplicationInsightsSampler(0.75);
const provider = new BasicTracerProvider({
sampler: aiSampler
});
const exporter = new AzureMonitorTraceExporter({
connectionString: "<Your Connection String>"
});
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
provider.register();
En este ejemplo se usa ApplicationInsightsSampler, que ofrece compatibilidad con los SDK de Application Insights.
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from azure.monitor.opentelemetry.exporter import (
ApplicationInsightsSampler,
AzureMonitorTraceExporter,
)
# Sampler expects a sample rate of between 0 and 1 inclusive
# 0.1 means approximately 10% of your traces are sent
sampler = ApplicationInsightsSampler(0.1)
trace.set_tracer_provider(TracerProvider(sampler=sampler))
tracer = trace.get_tracer(__name__)
exporter = AzureMonitorTraceExporter(connection_string="<your-connection-string>")
span_processor = BatchSpanProcessor(exporter)
trace.get_tracer_provider().add_span_processor(span_processor)
for i in range(100):
# Approximately 90% of these spans should be sampled out
with tracer.start_as_current_span("hello"):
print("Hello, World!")
Sugerencia
Si sabe dónde establecer la frecuencia de muestreo, comience en un 5 % (es decir, una relación de muestreo del 0,05) y ajústela en función de la precisión de las operaciones mostradas en las hojas de rendimiento y errores. Una tasa más alta suele dar como resultado una mayor precisión. Sin embargo, CUALQUIER muestreo afectará a la precisión, por lo que se recomienda alertar sobre las métricas de OpenTelemetry, que no se ven afectadas por el muestreo.
Bibliotecas de instrumentación
Las siguientes bibliotecas están validadas para funcionar con la versión preliminar.
Advertencia
Las bibliotecas de instrumentación se basan en especificaciones experimentales de OpenTelemetry. El compromiso de soporte técnico de la versión preliminar de Microsoft es garantizar que las siguientes bibliotecas emitan datos a Azure Monitor Application Insights, aunque es posible que los cambios importantes o la asignación experimental bloqueen algunos elementos de datos.
Las ofertas de OpenTelemetry emiten actualmente todas las métricas como Métricas personalizadas en el Explorador de métricas. Lo que establezca como nombre de medidor se convierte en el espacio de nombres de las métricas.
Modificación de la telemetría
En esta sección se explica cómo modificar la telemetría.
Incorporación de atributos de intervalo
Puede agregar atributos de intervalo mediante cualquiera de los dos métodos siguientes:
Agregue un procesador de intervalos personalizado.
Estos atributos pueden incluir agregar una propiedad personalizada a sus datos de telemetría. También puede usar atributos para establecer campos opcionales en el esquema de Application Insights, como la IP de cliente.
Sugerencia
La ventaja de usar las opciones proporcionadas por las bibliotecas de instrumentación, cuando están disponibles, es que se dispone de todo el contexto. En consecuencia, los usuarios pueden optar por agregar o filtrar más atributos. Por ejemplo, la opción de enriquecimiento de la biblioteca de instrumentación HttpClient proporciona a los usuarios acceso al propio httpRequestMessage. Pueden seleccionar lo que deseen de él y almacenarlo como atributo.
Agregar una propiedad personalizada al seguimiento
Los atributos que se agregan a intervalos se exportan como propiedades personalizadas. Rellenan el campo customDimensions de las solicitudes o las tablas de dependencias de Application Insights.
Muchas bibliotecas de instrumentación proporcionan una opción de enriquecimiento. Para obtener instrucciones, consulte el archivo Léame de cada biblioteca de instrumentación:
Agregue el procesador que se muestra a continuación antes de Azure Monitor Exporter.
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("OTel.AzureMonitor.Demo")
.AddProcessor(new ActivityEnrichingProcessor())
.AddAzureMonitorTraceExporter(o =>
{
o.ConnectionString = "<Your Connection String>"
})
.Build();
Agregue ActivityEnrichingProcessor.cs al proyecto con el siguiente código:
using System.Diagnostics;
using OpenTelemetry;
using OpenTelemetry.Trace;
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");
}
}
Use un procesador personalizado:
Sugerencia
Agregue el procesador que se muestra a continuación antes de Azure Monitor Exporter.
Agregue el procesador que se muestra a continuación antes de Azure Monitor Exporter.
...
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
trace.set_tracer_provider(TracerProvider())
span_processor = BatchSpanProcessor(exporter)
span_enrich_processor = SpanEnrichingProcessor()
trace.get_tracer_provider().add_span_processor(span_enrich_processor)
trace.get_tracer_provider().add_span_processor(span_processor)
...
Agregue SpanEnrichingProcessor.py al proyecto con el siguiente código:
from opentelemetry.sdk.trace import SpanProcessor
class SpanEnrichingProcessor(SpanProcessor):
def on_end(self, span):
span._name = "Updated-" + span.name
span._attributes["CustomDimension1"] = "Value1"
span._attributes["CustomDimension2"] = "Value2"
Establecimiento de la IP de usuario
Para rellenar el campo client_IP de solicitudes, establezca el atributo http.client_ip en el intervalo. Application Insights usa la dirección IP para generar atributos de ubicación del usuario y luego la descarta de manera predeterminada.
Muchas bibliotecas de instrumentación proporcionan una opción de filtrado. Para obtener instrucciones, consulte el archivo Léame de cada biblioteca de instrumentación:
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("OTel.AzureMonitor.Demo")
.AddProcessor(new ActivityFilteringProcessor())
.AddAzureMonitorTraceExporter(o =>
{
o.ConnectionString = "<Your Connection String>"
})
.Build();
Agregue ActivityFilteringProcessor.cs al proyecto con el siguiente código:
using System.Diagnostics;
using OpenTelemetry;
using OpenTelemetry.Trace;
public class ActivityFilteringProcessor : BaseProcessor<Activity>
{
public override void OnStart(Activity activity)
{
// prevents all exporters from exporting internal activities
if (activity.Kind == ActivityKind.Internal)
{
activity.IsAllDataRequested = false;
}
}
}
Si un determinado origen no se agrega de manera explícita mediante AddSource("ActivitySourceName"), no se exportará ninguna de las actividades creadas con ese origen.
Excluya la opción de dirección URL que proporcionan muchas bibliotecas de instrumentación HTTP.
Use un procesador personalizado. Puede usar un procesador de intervalos personalizado para excluir determinados intervalos de la exportación. Para marcar los intervalos que no se van a exportar, establezca TraceFlag en DEFAULT.
Use el ejemplo de incorporación de propiedad personalizada, pero reemplace las siguientes líneas de código:
import { IncomingMessage } from "http";
import { RequestOptions } from "https";
import { registerInstrumentations } from "@opentelemetry/instrumentation";
import { HttpInstrumentation, HttpInstrumentationConfig } from "@opentelemetry/instrumentation-http";
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
const httpInstrumentationConfig: HttpInstrumentationConfig = {
ignoreIncomingRequestHook: (request: IncomingMessage) => {
// Ignore OPTIONS incoming requests
if (request.method === 'OPTIONS') {
return true;
}
return false;
},
ignoreOutgoingRequestHook: (options: RequestOptions) => {
// Ignore outgoing requests with /test path
if (options.path === '/test') {
return true;
}
return false;
}
};
const httpInstrumentation = new HttpInstrumentation(httpInstrumentationConfig);
const provider = new NodeTracerProvider();
provider.register();
registerInstrumentations({
instrumentations: [
httpInstrumentation,
]
});
Use un procesador personalizado. Puede usar un procesador de intervalos personalizado para excluir determinados intervalos de la exportación. Para marcar los intervalos que no se van a exportar, establezca TraceFlag en DEFAULT.
Use el ejemplo de incorporación de propiedad personalizada, pero reemplace las siguientes líneas de código:
Excluya la opción de dirección URL que proporcionan muchas bibliotecas de instrumentación HTTP.
A continuación se muestra un ejemplo de cómo excluir una dirección URL determinada del seguimiento mediante la instrumentación de Flask:
...
import flask
from opentelemetry.instrumentation.flask import FlaskInstrumentor
# You might also populate OTEL_PYTHON_FLASK_EXCLUDED_URLS env variable
# List will consist of comma delimited regexes representing which URLs to exclude
excluded_urls = "client/.*/info,healthcheck"
FlaskInstrumentor().instrument(excluded_urls=excluded_urls) # Do this before flask.Flask
app = flask.Flask(__name__)
...
Use un procesador personalizado. Puede usar un procesador de intervalos personalizado para excluir determinados intervalos de la exportación. Para marcar los intervalos que no se van a exportar, establezca TraceFlag en DEFAULT.
...
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
trace.set_tracer_provider(TracerProvider())
span_processor = BatchSpanProcessor(exporter)
span_filter_processor = SpanFilteringProcessor()
trace.get_tracer_provider().add_span_processor(span_filter_processor)
trace.get_tracer_provider().add_span_processor(span_processor)
...
Agregue SpanFilteringProcessor.py al proyecto con el siguiente código:
from opentelemetry.trace import SpanContext, SpanKind, TraceFlags
from opentelemetry.sdk.trace import SpanProcessor
class SpanFilteringProcessor(SpanProcessor):
# prevents exporting spans from internal activities
def on_start(self, span):
if span._kind is SpanKind.INTERNAL:
span._context = SpanContext(
span.context.trace_id,
span.context.span_id,
span.context.is_remote,
TraceFlags.DEFAULT,
span.context.trace_state,
)
Telemetría personalizada
En esta sección se explica cómo recopilar datos de telemetría personalizados de la aplicación.
Agregar Métricas personalizadas
Nota
Las Métricas personalizadas están en versión preliminar en Application Insights de Azure Monitor. Las métricas personalizadas sin dimensiones están disponibles de manera predeterminada. Para ver y alertar sobre las dimensiones, debe participar.
La API de OpenTelemetry ofrece seis "instrumentos" de métricas para cubrir varios escenarios de métricas, y tendrá que elegir el "Tipo de agregación" correcto al visualizar las métricas en el Explorador de métricas. Este requisito es cierto cuando se usa la API de métricas de OpenTelemetry para enviar métricas y cuando se usa una biblioteca de instrumentación.
En la tabla siguiente se muestran los tipos de agregación recomendados para cada uno de los instrumentos de métricas de OpenTelemetry.
Instrumento de OpenTelemetry
Tipo de agregación en Azure Monitor
Contador
Sum
Contador asincrónico
Sum
Histograma
Min, Max, Average, Sum y Count
Medidor asincrónico
Average
UpDownCounter
Sum
UpDownCounter asincrónico
Sum
Precaución
Los tipos de agregación, más allá de lo que se muestra en la tabla, no suelen ser significativos.
El histograma es el equivalente más versátil y más cercano a la API anterior de métricas de seguimiento de Application Insights. Actualmente, Azure Monitor aplana el instrumento de histograma en nuestros cinco tipos de agregación admitidos; estamos trabajando en añadir la compatibilidad con los percentiles. Aunque es menos versátil, otros instrumentos de OpenTelemetry tienen un menor impacto en el rendimiento de la aplicación.
using System.Diagnostics.Metrics;
using Azure.Monitor.OpenTelemetry.Exporter;
using OpenTelemetry;
using OpenTelemetry.Metrics;
public class Program
{
private static readonly Meter meter = new("OTel.AzureMonitor.Demo");
public static void Main()
{
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("OTel.AzureMonitor.Demo")
.AddAzureMonitorMetricExporter(o =>
{
o.ConnectionString = "<Your Connection String>";
})
.Build();
var process = Process.GetCurrentProcess();
ObservableGauge<int> myObservableGauge = meter.CreateObservableGauge("Thread.State", () => GetThreadState(process));
System.Console.WriteLine("Press Enter key to exit.");
System.Console.ReadLine();
}
private static IEnumerable<Measurement<int>> GetThreadState(Process process)
{
foreach (ProcessThread thread in process.Threads)
{
yield return new((int)thread.ThreadState, new("ProcessId", process.Id), new("ThreadId", thread.Id));
}
}
}
const {
MeterProvider,
PeriodicExportingMetricReader
} = require("@opentelemetry/sdk-metrics");
const { AzureMonitorMetricExporter } = require("@azure/monitor-opentelemetry-exporter");
const provider = new MeterProvider();
const exporter = new AzureMonitorMetricExporter({
connectionString:
connectionString: "<Your Connection String>",
});
const metricReader = new PeriodicExportingMetricReader({
exporter: exporter
});
provider.addMetricReader(metricReader);
const meter = provider.getMeter("OTel.AzureMonitor.Demo");
let gauge = meter.createObservableGauge("gauge");
gauge.addCallback((observableResult) => {
let randomNumber = Math.floor(Math.random() * 100);
observableResult.observe(randomNumber, {"testKey": "testValue"});
});
import {
MeterProvider,
PeriodicExportingMetricReader,
PeriodicExportingMetricReaderOptions
} from "@opentelemetry/sdk-metrics";
import { AzureMonitorMetricExporter } from "@azure/monitor-opentelemetry-exporter";
const provider = new MeterProvider();
const exporter = new AzureMonitorMetricExporter({
connectionString: "<Your Connection String>",
});
const metricReaderOptions: PeriodicExportingMetricReaderOptions = {
exporter: exporter,
};
const metricReader = new PeriodicExportingMetricReader(metricReaderOptions);
provider.addMetricReader(metricReader);
const meter = provider.getMeter("OTel.AzureMonitor.Demo");
let gauge = meter.createObservableGauge("gauge");
gauge.addCallback((observableResult: ObservableResult) => {
let randomNumber = Math.floor(Math.random() * 100);
observableResult.observe(randomNumber, {"testKey": "testValue"});
});
from typing import Iterable
from opentelemetry import metrics
from opentelemetry.metrics import CallbackOptions, Observation
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from azure.monitor.opentelemetry.exporter import AzureMonitorMetricExporter
exporter = AzureMonitorMetricExporter(connection_string="<your-connection-string")
reader = PeriodicExportingMetricReader(exporter)
metrics.set_meter_provider(MeterProvider(metric_readers=[reader]))
meter = metrics.get_meter_provider().get_meter("otel_azure_monitor_gauge_demo")
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
gauge = meter.create_observable_gauge("gauge", [observable_gauge_generator])
gauge2 = meter.create_observable_gauge("gauge2", [observable_gauge_sequence])
input()
Agregar excepciones personalizadas
Seleccione bibliotecas de instrumentación que admitan automáticamente excepciones en Application Insights.
Sin embargo, es posible que desee notificar algunas excepciones manualmente, más allá de lo que aparece en el informe de bibliotecas de instrumentación.
Por ejemplo, las excepciones detectadas por el código normalmente no se notifican. Es posible que desee que se notifiquen para tenerlas en cuenta en experiencias pertinentes, incluida la sección de errores y las vistas de transacciones de un extremo a otro.
import * as opentelemetry from "@opentelemetry/api";
import { BasicTracerProvider, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base";
import { AzureMonitorTraceExporter } from "@azure/monitor-opentelemetry-exporter";
const provider = new BasicTracerProvider();
const exporter = new AzureMonitorTraceExporter({
connectionString: "<Your Connection String>",
});
provider.addSpanProcessor(new SimpleSpanProcessor(exporter as any));
provider.register();
const tracer = opentelemetry.trace.getTracer("example-basic-tracer-node");
let span = tracer.startSpan("hello");
try{
throw new Error("Test Error");
}
catch(error){
span.recordException(error);
}
El SDK de Python de OpenTelemetry se implementa de forma que las excepciones producidas se capturarán y registrarán automáticamente. A continuación puede consultar un ejemplo de esto.
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from azure.monitor.opentelemetry.exporter import AzureMonitorTraceExporter
exporter = AzureMonitorTraceExporter(connection_string="<your-connection-string>")
trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer("otel_azure_monitor_exception_demo")
span_processor = BatchSpanProcessor(exporter)
trace.get_tracer_provider().add_span_processor(span_processor)
# Exception events
try:
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")
Si desea registrar las excepciones manualmente, puede deshabilitar esa opción al crear el intervalo, como se muestra a continuación.
...
with tracer.start_as_current_span("hello", record_exception=False) as span:
try:
raise Exception("Custom exception message.")
except Exception as ex:
# Manually record exception
span.record_exception(ex)
...
Habilitación del exportador de OTLP
Es posible que quiera habilitar el exportador de OpenTelemetry Protocol (OTLP) junto con Azure Monitor Exporter para enviar los datos de telemetría a dos ubicaciones.
Nota
El exportador de OTLP solo se muestra por comodidad. Oficialmente, no proporcionamos soporte técnico con relación al exportador de OTLP ni componentes o experiencias de terceros de nivel inferior. Se recomienda abrir una incidencia con OpenTelemetry-Collector en caso de problemas de OpenTelemetry que no sean del ámbito del Soporte técnico de Azure.
Agregue el siguiente fragmento de código. En este ejemplo se da por hecho que tiene un recopilador de OpenTelemetry con un receptor de OTLP en ejecución. Para obtener más información, consulte el ejemplo en GitHub.
// Sends data to Application Insights as well as OTLP
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("OTel.AzureMonitor.Demo")
.AddAzureMonitorTraceExporter(o =>
{
o.ConnectionString = "<Your Connection String>"
})
.AddOtlpExporter()
.Build();
Agregue el siguiente fragmento de código. En este ejemplo se da por hecho que tiene un recopilador de OpenTelemetry con un receptor de OTLP en ejecución. Para obtener más información, consulte el ejemplo en GitHub.
Agregue el siguiente fragmento de código. En este ejemplo se da por hecho que tiene un recopilador de OpenTelemetry con un receptor de OTLP en ejecución. Para obtener más información, consulte el ejemplo en GitHub.
import { BasicTracerProvider, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { OTLPTraceExporter } from '@opentelemetry/exporter-otlp-http';
import { AzureMonitorTraceExporter } from '@azure/monitor-opentelemetry-exporter';
const provider = new BasicTracerProvider();
const azureMonitorExporter = new AzureMonitorTraceExporter({
connectionString: "<Your Connection String>",
});
const otlpExporter = new OTLPTraceExporter();
provider.addSpanProcessor(new SimpleSpanProcessor(azureMonitorExporter));
provider.addSpanProcessor(new SimpleSpanProcessor(otlpExporter));
provider.register();
Agregue el siguiente fragmento de código. En este ejemplo se da por hecho que tiene un recopilador de OpenTelemetry con un receptor de OTLP en ejecución. Para obtener más información, consulte este archivo LÉAME.
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from azure.monitor.opentelemetry.exporter import AzureMonitorTraceExporter
trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)
exporter = AzureMonitorTraceExporter(connection_string="<your-connection-string>")
otlp_exporter = OTLPSpanExporter(endpoint="http://localhost:4317")
span_processor = BatchSpanProcessor(otlp_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)
with tracer.start_as_current_span("test"):
print("Hello world!")
Configuración
Almacenamiento sin conexión y reintentos automáticos
Para mejorar la confiabilidad y la resistencia, las ofertas basadas en OpenTelemetry de Azure Monitor escriben en un almacenamiento sin conexión o local de manera predeterminada cuando una aplicación pierde su conexión con Application Insights. Guarda la telemetría de la aplicación durante 48 horas y, periódicamente, intenta enviarla de nuevo. Además de superar el tiempo permitido, la telemetría se quitará ocasionalmente en aplicaciones de alta carga cuando se supere el tamaño máximo del archivo o el SDK no tenga la oportunidad de borrar el archivo. Si es necesario elegir, el producto guardará los eventos más recientes sobre los antiguos. En algunos casos, puede deshabilitar esta característica para optimizar el rendimiento de la aplicación. Más información
De manera predeterminada, AzureMonitorExporter usa una de las siguientes ubicaciones para el almacenamiento sin conexión (se muestra en orden de prioridad):
Windows
%LOCALAPPDATA%\Microsoft\AzureMonitor
%TEMP%\Microsoft\AzureMonitor
Distinta de Windows
%TMPDIR%/Microsoft/AzureMonitor
/var/tmp/Microsoft/AzureMonitor
/tmp/Microsoft/AzureMonitor
Para invalidar el directorio predeterminado, debe establecer AzureMonitorExporterOptions.StorageDirectory.
Azure Monitor Exporter usa EventSource para sus propios registros internos. Los registros del exportador están disponibles para cualquier elemento EventListener si se opta por el origen de nombre "OpenTelemetry-AzureMonitor-Exporter". En Solución de problemas de OpenTelemetry puede consultar los pasos para solucionar distintos problemas.
Azure Monitor Exportador usa OpenTelemetry API Logger para registros internos. Para habilitarlo, use el siguiente código:
Azure Monitor Exportador usa OpenTelemetry API Logger para registros internos. Para habilitarlo, use el siguiente código:
import { diag, DiagConsoleLogger, DiagLogLevel } from "@opentelemetry/api";
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
const provider = new NodeTracerProvider();
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ALL);
provider.register();
Azure Monitor Exporter usa la biblioteca de registro estándar de Python para sus propios registros internos. Los registros de la API de OpenTelemetry y del Exportador de Azure Monitor se registran con el nivel de gravedad ADVERTENCIA o ERROR si se da una actividad irregular. El nivel de gravedad INFORMACIÓN se usa con relación a actividad normal o correcta. La biblioteca de registro de Python establece de manera predeterminada el nivel de gravedad en ADVERTENCIA, por lo que debe cambiar dicho nivel para ver los registros de menor gravedad. A continuación se muestra un ejemplo de cómo generar registros de todos los niveles de gravedad en la consola y un archivo:
Los problemas conocidos de Azure Monitor OpenTelemetry Exporter incluyen:
Falta el nombre de la operación en los datos de telemetría de dependencias, lo que afecta negativamente a la experiencia de la pestaña "Errores y rendimiento".
Falta el modelo de dispositivo en los datos de telemetría de solicitudes y dependencias, lo que afecta negativamente al análisis de cohortes de dispositivos.
El nombre del servidor de base de datos queda fuera del nombre de dependencia, lo que provoca que se agreguen incorrectamente tablas con el mismo nombre en diferentes servidores.
Prueba de la conectividad entre el host de la aplicación y el servicio de ingesta
Los SDK y agentes de Application Insights envían telemetría para ingerirse como llamadas REST a nuestros puntos de conexión de ingesta. Puede probar la conectividad desde el servidor web o la máquina host de la aplicación a los puntos de conexión del servicio de ingesta mediante clientes REST sin procesar con comandos de PowerShell o curl. Consulte Solución de problemas de telemetría de aplicaciones que faltan en Azure Monitor Application Insights.
Soporte técnico
Para obtener soporte técnico:
Revise los pasos de solución de problemas de este artículo.