Eventos amplios canónicos
Un evento canónico amplio describe una unidad de trabajo completa con el contexto necesario para explicar su resultado. En lugar de reconstruir una solicitud a partir de mensajes desconectados “iniciados”, “base de datos llamada” y “finalizado”, la aplicación emite un resultado de solicitud que contiene su ruta, cuenta, versión, duración, estado y contexto de falla categorizado.
Este patrón también se denomina línea de registro canónico, evento estructurado o evento amplio. Stripe describió las líneas de registro canónicas como una forma de recopilar el contexto importante para una solicitud en un solo lugar. Honeycomb utiliza eventos estructurados ricos en contexto como base para la observabilidad. El Modelo de datos de registros OpenTelemetry proporciona una representación estándar que puede correlacionar registros con seguimientos. Los nombres y el transporte difieren, pero la pregunta sobre el diseño útil es la misma: ¿puede un registro explicar un resultado significativo sin buscar en una narrativa?
"Amplio" significa que el evento puede incluir muchos campos útiles. No significa copiar todos los objetos en la memoria.
Comience con el grano del evento
El grano del evento es lo representado por una fila. Anótelo antes de elegir campos. Los cereales útiles incluyen:
- una solicitud API alcanzó un resultado terminal
- un trabajo en segundo plano completó o agotó sus reintentos
- una entrega de webhook fue procesada, rechazada o deduplicada
- una ejecución de agente se completó, falló o alcanzó un límite de seguridad
- una cuenta alcanzó un hito de activación, facturación o retención
- una operación de base de datos completada con una huella digital limitada
Evite mezclar granos en una tabla. Si una fila a veces significa un intento de solicitud y otras veces significa una solicitud lógica en todos los reintentos, los recuentos y las tasas se vuelven ambiguos. Utilice un attempt_number independiente o un evento de intento independiente cuando se requieran ambas vistas.
Cree el evento canónico durante el ciclo de vida de la operación y emítalo cuando se conozca el resultado final:
const outcome = {
request_id: requestId,
route_template: "/api/projects/:id/sync",
method: "POST",
team_id: teamId,
release: process.env.APP_RELEASE,
environment: "production",
started_at: new Date().toISOString(),
};
try {
await syncProject();
await telemetry.log("api_request_completed", {
...outcome,
status: "success",
status_code: 200,
latency_ms: Math.round(performance.now() - startedAt),
});
} catch (error) {
await telemetry.log("api_request_completed", {
...outcome,
status: "failed",
status_code: statusFor(error),
error_type: classifyError(error),
latency_ms: Math.round(performance.now() - startedAt),
});
throw error;
}
La entrega de instrumentación no debería convertir una solicitud exitosa en una solicitud fallida. Utilice tiempos de espera acotados, observe los errores de entrega por separado y decida explícitamente qué eventos críticos requieren una cola duradera.
Utilice una taxonomía de campo
Un evento canónico útil generalmente se compone de seis grupos de campos:
| grupo | Ejemplos | Por que existe |
|---|---|---|
| Identidad | event_id, request_id, run_id |
Deduplicar y encontrar un resultado |
| Grano y resultado | event_name, status, error_type, attempt_number |
Definir lo que se cuenta |
| Sincronización | timestamp_utc, duration_ms, queue_wait_ms |
Tasas de compilación y distribuciones de latencia |
| Contexto del producto | feature, plan, workflow, route_template |
Conecte la confiabilidad con el comportamiento de cara al usuario |
| Contexto de implementación | service, environment, region, release |
Comparar cambios y aislar regresiones |
| Correlación | trace_id, job_id, team_id |
Vaya a pruebas más profundas o únase a eventos relacionados |
Utilice categorías controladas para los campos que se agruparán. error_type: "dependency_timeout" es más confiable que un mensaje de excepción sin formato. Utilice unidades explícitas en los nombres: _ms, _bytes, _usd y _count. Utilice plantillas de ruta normalizadas en lugar de URL sin formato.
Los identificadores como los ID de solicitud, los ID de cuenta y los ID de seguimiento tienen una cardinalidad alta. Esto suele ser correcto: son valiosos para el filtrado y la correlación incluso cuando son dimensiones de gráficos deficientes. Consérvelos sólo cuando el beneficio de la investigación justifique el costo de privacidad, almacenamiento y consulta. Ver Campos de alta cardinalidad.
Tres formas prácticas de eventos
Un evento de solicitud API debe mantener juntos el denominador y el resultado:
{
"event_name": "api_request_completed",
"request_id": "req_7d91",
"route_template": "/api/projects/:id/sync",
"method": "POST",
"status_code": 503,
"status": "failed",
"error_type": "dependency_timeout",
"latency_ms": 8420,
"release": "2026.07.4",
"schema_version": 2
}
Un evento de trabajo en segundo plano debería hacer que el reintento sea explícito:
{
"event_name": "job_completed",
"job_id": "job_82f1",
"job_name": "sync_billing_account",
"queue_name": "billing",
"status": "failed",
"terminal": true,
"attempt_number": 4,
"queue_wait_ms": 1820,
"duration_ms": 9612,
"error_type": "provider_timeout"
}
Un evento ejecutado por un agente debe separar los resultados operativos del contenido confidencial:
{
"event_name": "agent_run_completed",
"run_id": "run_28bd",
"workflow": "support_resolution",
"agent_name": "support_agent",
"model": "approved_model_alias",
"status": "success",
"tool_call_count": 3,
"retry_count": 1,
"duration_ms": 4820,
"accepted": true,
"prompt_version": "support-v4"
}
No registre solicitudes sin procesar, finalizaciones, argumentos de herramientas ni documentos recuperados de forma predeterminada. El evento resultante puede responder preguntas sobre volumen, confiabilidad, costo y aceptación sin retener el contenido del cliente.
Mantenga estrecho el límite de privacidad
Trate cada campo como datos que pueden aparecer en el resultado de una consulta, panel, exportación o flujo de trabajo de soporte. Utilice una lista de permitidos en el momento de la construcción del evento. No incluya encabezados de autorización, cookies, credenciales, cadenas de conexión, cuerpos de solicitud o respuesta, cargas útiles de webhooks, detalles de pago ni contenido de cliente sin restricciones.
Prefiera un identificador de cuenta interno a una dirección de correo electrónico, una plantilla de ruta a una URL completa y una categoría de error controlada al texto de excepción. El hash de datos personales no los hace seguros automáticamente; Los hashes estables aún pueden ser identificadores vinculables. Expectativas de propiedad, propósito, retención y eliminación de documentos en un plan de seguimiento de eventos.
Correlacionar en lugar de duplicar
Un evento canónico amplio complementa las métricas, los seguimientos y los registros de diagnóstico detallados. No es necesario reproducirlos.
- Las métricas siguen siendo eficientes para las alertas de infraestructura y estado del servicio agregado.
- Los rastros muestran el momento y la causalidad en todos los tramos.
- Los registros de diagnóstico conservan detalles locales, como un seguimiento de la pila.
- Los eventos canónicos preservan la solicitud completa o el resultado comercial.
Adjunte un trace_id aprobado o una identificación de correlación cuando haya evidencia más profunda en otro lugar. Los respondedores pueden pasar de una fila de resultados fallidos a su seguimiento sin copiar una cascada de tramos o un seguimiento de pila en el evento. El guía de registros, métricas y seguimientos cubre los límites con más detalle.
Planificar la evolución del esquema antes del lanzamiento.
Dale al evento un propietario y un schema_version. Agregue campos opcionales antes de hacerlos obligatorios. Nunca cambie silenciosamente un campo numérico en una cadena ni reutilice el nombre de un campo para darle un significado diferente. Durante una migración, admita ambas versiones de esquema en SQL hasta que los productores y las ventanas históricas hayan convergido.
Mantenga las categorías controladas delimitadas. Si aparece una nueva categoría de error, revise si cambia un panel, una alerta o un runbook. Si una actualización de una aplicación cambia el nombre de una ruta o flujo de trabajo, conserve un nombre analítico estable por separado del nombre de la implementación.
guía de evolución del esquema y tipos de datos y nulidad explican estas opciones de implementación.
Muestra basada en decisiones, no en conveniencia
No elimine fallas raras, resultados de trabajos terminales, cambios de facturación, acciones de seguridad o eventos utilizados para una conciliación exacta. Las solicitudes exitosas de gran volumen pueden ser candidatas para un muestreo determinista o basado en tasas, pero conservan la decisión y el peso del muestreo si el análisis posterior necesita totales estimados.
Compare el almacenamiento guardado con las preguntas perdidas. El muestreo puede preservar las distribuciones de latencia y al mismo tiempo imposibilitar los recuentos exactos del impacto en la cuenta. El guía de muestreo de eventos describe casos seguros e inseguros.
Validar el evento con SQL
Un evento está completo cuando responde a las preguntas previstas con un SQL defendible, no cuando contiene la mayor cantidad de campos. Ejercite rutas de éxito, error, reintento, tiempo de espera, entrega duplicada, campo nulo y llegada tardía en un entorno que no sea de producción. Inspeccione el esquema almacenado antes de crear un panel.
Para un evento de resultado API, comience con un recuento y un denominador:
SELECT
route_template,
COUNT(*) AS requests,
SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) AS failures,
100.0 * SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END)
/ NULLIF(COUNT(*), 0) AS failure_rate_pct,
approx_percentile_cont(latency_ms, 0.95) AS p95_latency_ms
FROM api_request_completed
WHERE timestamp_utc >= now() - INTERVAL '24 hours'
AND environment = 'production'
GROUP BY route_template
HAVING COUNT(*) >= 20
ORDER BY failure_rate_pct DESC;
Mantenga el volumen al lado de las tasas, excluya períodos de tiempo incompletos al comparar períodos e indique si los reintentos son intentos o resultados lógicos. Almacene un elemento determinista y el resultado esperado para consultas que se vuelven operativamente importantes. El Pruebas de instrumentación en la guía de CI. muestra cómo evitar que el contrato se desvíe.
Migrar un flujo de trabajo a la vez
No reemplace una secuencia de registro completa. Elija una decisión recurrente, emita su evento canónico junto a la telemetría existente y ejecute dos veces las respuestas antiguas y nuevas en la misma ventana UTC cerrada. Investigue las diferencias en el manejo de reintentos, la normalización de rutas, las marcas de tiempo, los nulos y las exclusiones. Promocione la nueva consulta a un panel o alerta solo después de que su propietario acepte la semántica.
El camino práctico es:
- Defina el grano del evento y la decisión.
- Escriba el contrato de campo permitido.
- Resultados del terminal de instrumentos.
- Verificar entrega y esquema.
- Pruebe la consulta con accesorios.
- Informes o alertas de doble ejecución.
- Jubilar únicamente al consumidor redundante.
Continúe con el guía de gestión de registros estructurados, eventos estructurados versus registros de texto o el guía de migración completo.