Instrumentación
Instrumentation is the act of adding observability code to an app yourself.
If you’re instrumenting an app, you need to use the OpenTelemetry SDK for your language. You’ll then use the SDK to initialize OpenTelemetry and the API to instrument your code. This will emit telemetry from your app, and any library you installed that also comes with instrumentation.
If you’re instrumenting a library, only install the OpenTelemetry API package for your language. Your library will not emit telemetry on its own. It will only emit telemetry when it is part of an app that uses the OpenTelemetry SDK. For more on instrumenting libraries, see Libraries.
For more information about the OpenTelemetry API and SDK, see the specification.
Configuración
Primero, asegúrate de tener los paquetes API y SDK:
pip install opentelemetry-api
pip install opentelemetry-sdk
Trazas
Adquirir el trazador
Para comenzar a realizar trazas, necesitarás inicializar un
TracerProvider
y
opcionalmente configurarlo como el proveedor global predeterminado.
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
BatchSpanProcessor,
ConsoleSpanExporter,
)
provider = TracerProvider()
processor = BatchSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(processor)
# Establece el proveedor de tracer global predeterminado
trace.set_tracer_provider(provider)
# Crea un tracer a partir del proveedor de tracer global
tracer = trace.get_tracer("my.tracer.name")
Crear spans
Para crear un span, normalmente querrás iniciarlo como el span actual.
def do_work():
with tracer.start_as_current_span("span-name") as span:
# realiza algún trabajo que 'span' rastreará
print("haciendo algún trabajo...")
# Cuando el bloque 'with' sale del contexto, 'span' se cierra automáticamente
También puedes usar start_span
para crear un span sin hacerlo el span actual.
Esto se suele hacer para rastrear operaciones concurrentes o asíncronas.
Crear spans anidados
Si tienes una sub-operación distinta que deseas rastrear como parte de otra, puedes crear spans para representar la relación:
def do_work():
with tracer.start_as_current_span("parent") as parent:
# realiza algún trabajo que 'parent' rastreará
print("haciendo algún trabajo...")
# Crea un span anidado para rastrear el trabajo anidado
with tracer.start_as_current_span("child") as child:
# realiza algún trabajo que 'child' rastreará
print("haciendo trabajo anidado...")
# el span anidado se cierra cuando sale del contexto
# Este span también se cierra cuando sale del contexto
Cuando veas spans en una herramienta de visualización de trazas, child
se
rastreará como un span anidado bajo parent
.
Crear spans con decoradores
Es común que un único span rastree la ejecución de una función completa. En ese caso, hay un decorador que puedes usar para reducir el código:
@tracer.start_as_current_span("do_work")
def do_work():
print("haciendo algún trabajo...")
El uso del decorador es equivalente a crear el span dentro de do_work()
y
finalizarlo cuando do_work()
termine.
Para usar el decorador, debes tener una instancia de tracer
disponible
globalmente para la declaración de tu función.
Obtener el span actual
A veces es útil acceder al span actual en un momento dado para poder enriquecerlo con más información.
from opentelemetry import trace
current_span = trace.get_current_span()
# enriquecer 'current_span' con más información
Agregar atributos a un span
Los atributos te permiten adjuntar pares clave/valor a un span para que contenga más información sobre la operación actual que está rastreando.
from opentelemetry import trace
current_span = trace.get_current_span()
current_span.set_attribute("operation.value", 1)
current_span.set_attribute("operation.name", "¡Diciendo hola!")
current_span.set_attribute("operation.other-stuff", [1, 2, 3])
Agregar atributos semánticos
Los atributos semánticos son atributos predefinidos que son convenciones de nombres bien conocidas para tipos comunes de datos. Usar atributos semánticos te permite normalizar este tipo de información en tus sistemas.
Para usar los atributos semánticos en Python, asegúrate de tener instalado el paquete de convenciones semánticas:
pip install opentelemetry-semantic-conventions
Luego puedes usarlos en el código:
from opentelemetry import trace
from opentelemetry.semconv.trace import SpanAttributes
// ...
current_span = trace.get_current_span()
current_span.set_attribute(SpanAttributes.HTTP_METHOD, "GET")
current_span.set_attribute(SpanAttributes.HTTP_URL, "https://opentelemetry.io/")
Agregar eventos
Un evento es un mensaje legible en un span que representa “algo que sucede” durante su vida útil. Puedes pensarlo como un registro o log primitivo.
from opentelemetry import trace
current_span = trace.get_current_span()
current_span.add_event("¡Voy a intentarlo!")
# Haz la cosa
current_span.add_event("¡Lo hice!")
Agregar enlaces
Un span se puede crear con uno o más enlaces que lo vinculen causalmente con otro span. Un enlace necesita un contexto de span para ser creado.
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("span-1"):
# Hacer algo que 'span-1' rastrea.
ctx = trace.get_current_span().get_span_context()
link_from_span_1 = trace.Link(ctx)
with tracer.start_as_current_span("span-2", links=[link_from_span_1]):
# Hacer algo que 'span-2' rastrea.
# El enlace en 'span-2' está causalmente asociado con 'span-1',
# pero no es un span hijo.
pass
Establecer el estado del span
A Status can be set on a
Span, typically used to specify that a
Span has not completed successfully - Error
. By default, all spans are
Unset
, which means a span completed without error. The Ok
status is reserved
for when you need to explicitly mark a span as successful rather than stick with
the default of Unset
(i.e., “without error”).
The status can be set at any time before the span is finished.
from opentelemetry import trace
from opentelemetry.trace import Status, StatusCode
current_span = trace.get_current_span()
try:
# algo que podría fallar
except:
current_span.set_status(Status(StatusCode.ERROR))
Registrar excepciones en spans
Puede ser una buena idea registrar excepciones cuando ocurren. Se recomienda hacerlo a la vez que se establece el estado del span.
from opentelemetry import trace
from opentelemetry.trace import Status, StatusCode
current_span = trace.get_current_span()
try:
# algo que podría fallar
# Considera capturar una excepción más específica en tu código
except Exception as ex:
current_span.set_status(Status(StatusCode.ERROR))
current_span.record_exception(ex)
Cambiar el formato de propagación predeterminado
Por defecto, OpenTelemetry Python usa los siguientes formatos de propagación:
- W3C Trace Context
- W3C Baggage
Si necesitas cambiar los valores predeterminados, puedes hacerlo a través de variables de entorno o en el código.
Usando variables de entorno
Puedes establecer la variable de entorno OTEL_PROPAGATORS
con una lista
separada por comas. Los valores aceptados son:
"tracecontext"
: W3C Trace Context"baggage"
: W3C Baggage"b3"
: B3 Single"b3multi"
: B3 Multi"jaeger"
: Jaeger"xray"
: AWS X-Ray (tercero)"ottrace"
: OT Trace (tercero)"none"
: Sin propagador configurado automáticamente.
La configuración predeterminada es equivalente a
OTEL_PROPAGATORS="tracecontext,baggage"
.
Usando APIs del SDK
Alternativamente, puedes cambiar el formato en el código.
Por ejemplo, si necesitas usar el formato de propagación B3 de Zipkin, puedes instalar el paquete B3:
pip install opentelemetry-propagator-b3
Luego configura el propagador B3 en tu código de inicialización de trazado:
from opentelemetry.propagate import set_global_textmap
from opentelemetry.propagators.b3 import B3Format
set_global_textmap(B3Format())
Nota que las variables de entorno anularán lo que esté configurado en el código.
Lectura adicional
- Conceptos de Trazas
- Especificación de Trazas
- Documentación de la API de Trazas de Python
- Documentación del SDK de Trazas de Python
Métricas
Para comenzar a recopilar métricas, necesitarás inicializar un
MeterProvider
y opcionalmente
configurarlo como el proveedor global predeterminado.
from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import (
ConsoleMetricExporter,
PeriodicExportingMetricReader,
)
metric_reader = PeriodicExportingMetricReader(ConsoleMetricExporter())
provider = MeterProvider(metric_readers=[metric_reader])
# Establece el proveedor de medidores global predeterminado
metrics.set_meter_provider(provider)
# Crea un medidor a partir del proveedor de medidores global
meter = metrics.get_meter("my.meter.name")
Crear y usar instrumentos síncronos
Los instrumentos se utilizan para realizar mediciones de tu aplicación. Los instrumentos síncronos se usan en línea con la lógica de procesamiento de aplicaciones/negocios, como cuando se maneja una solicitud o se llama a otro servicio.
Primero, crea tu instrumento. Los instrumentos generalmente se crean una vez al nivel del módulo o clase y luego se utilizan en línea con la lógica del negocio. Este ejemplo utiliza un contador para contar la cantidad de tareas de trabajo completadas:
work_counter = meter.create_counter(
"work.counter", unit="1", description="Cuenta la cantidad de trabajo realizado"
)
Usando la operación de agregado del contador, el código a continuación incrementa el conteo en uno, utilizando el tipo de elemento de trabajo como un atributo.
def do_work(work_item):
# contar el trabajo que se está realizando
work_counter.add(1, {"work.type": work_item.work_type})
print("haciendo algún trabajo...")
Crear y usar instrumentos asíncronos
Los instrumentos asíncronos permiten al usuario registrar funciones de devolución de llamada (callbacks), que se invocan cuando sea necesario para realizar mediciones. Esto es útil para medir periódicamente un valor que no se puede instrumentar directamente. Los instrumentos asíncronos se crean con una o más callbacks que serán invocadas durante la recopilación de métricas. Cada callback acepta opciones del SDK y devuelve sus observaciones.
Este ejemplo usa un medidor asíncrono (gauge) para reportar la versión actual de la configuración proporcionada por un servidor de configuración al hacer scraping de un endpoint HTTP. Primero, escribe una callback para hacer observaciones:
from typing import Iterable
from opentelemetry.metrics import CallbackOptions, Observation
def scrape_config_versions(options: CallbackOptions) -> Iterable[Observation]:
r = requests.get(
"http://configserver/version_metadata", timeout=options.timeout_millis / 10**3
)
for metadata in r.json():
yield Observation(
metadata["version_num"], {"config.name": metadata["version_num"]}
)
Nota que OpenTelemetry pasará opciones a tu callback que contienen un tiempo de espera. Las callbacks deben respetar este tiempo de espera para evitar bloquearse indefinidamente. Finalmente, crea el instrumento con la callback para registrarlo:
meter.create_observable_gauge(
"config.version",
callbacks=[scrape_config_versions],
description="La versión activa de la configuración para cada configuración",
)
Lectura adicional
- Conceptos de métricas
- Especificación de métricas
- Documentación de la API de métricas en Python
- Documentación del SDK de métricas en Python
Logs
La API y SDK de logs están actualmente en desarrollo.
Próximos pasos
Tal vez quieras configurar un exportador adecuado para exportar tus datos de telemetría a uno o más backends de telemetría.
Comentarios
¿Fue útil esta página?
Thank you. Your feedback is appreciated!
Please let us know how we can improve this page. Your feedback is appreciated!