autotel 4.3.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -103
- package/dist/analysis.cjs +87 -0
- package/dist/analysis.cjs.map +1 -0
- package/dist/analysis.d.cts +87 -0
- package/dist/analysis.d.cts.map +1 -0
- package/dist/analysis.d.ts +87 -0
- package/dist/analysis.d.ts.map +1 -0
- package/dist/analysis.js +85 -0
- package/dist/analysis.js.map +1 -0
- package/dist/{attribute-redacting-processor-DtTS9xxh.d.ts → attribute-redacting-processor-Pk7lAzWd.d.cts} +13 -8
- package/dist/attribute-redacting-processor-Pk7lAzWd.d.cts.map +1 -0
- package/dist/{attribute-redacting-processor-DtTS9xxh.d.cts → attribute-redacting-processor-Pk7lAzWd.d.ts} +13 -8
- package/dist/attribute-redacting-processor-Pk7lAzWd.d.ts.map +1 -0
- package/dist/attribute-redacting-processor.cjs +4 -4
- package/dist/attribute-redacting-processor.cjs.map +1 -1
- package/dist/attribute-redacting-processor.d.cts +1 -1
- package/dist/attribute-redacting-processor.d.ts +1 -1
- package/dist/attribute-redacting-processor.js +4 -4
- package/dist/attribute-redacting-processor.js.map +1 -1
- package/dist/attributes.d.cts +1 -1
- package/dist/attributes.d.ts +1 -1
- package/dist/auto.cjs +1 -1
- package/dist/auto.cjs.map +1 -1
- package/dist/auto.d.cts +1 -1
- package/dist/auto.d.ts +1 -1
- package/dist/auto.js +1 -1
- package/dist/auto.js.map +1 -1
- package/dist/business-baggage.d.cts +2 -3
- package/dist/business-baggage.d.cts.map +1 -1
- package/dist/business-baggage.d.ts +2 -3
- package/dist/business-baggage.d.ts.map +1 -1
- package/dist/{canonical-log-line-processor-xvjMgtpF.d.cts → canonical-log-line-processor-B4WgG-VS.d.cts} +2 -3
- package/dist/canonical-log-line-processor-B4WgG-VS.d.cts.map +1 -0
- package/dist/{canonical-log-line-processor-BcRuAdRk.d.ts → canonical-log-line-processor-CL_J7gb5.d.ts} +2 -3
- package/dist/canonical-log-line-processor-CL_J7gb5.d.ts.map +1 -0
- package/dist/{canonical-log-line-processor-CcrDi6TO.cjs → canonical-log-line-processor-DOjb6Kxy.cjs} +5 -5
- package/dist/canonical-log-line-processor-DOjb6Kxy.cjs.map +1 -0
- package/dist/{canonical-log-line-processor-FLezvFCB.js → canonical-log-line-processor-mKABvGP0.js} +5 -5
- package/dist/canonical-log-line-processor-mKABvGP0.js.map +1 -0
- package/dist/config.d.cts +12 -7
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.ts +12 -7
- package/dist/config.d.ts.map +1 -1
- package/dist/correlation-id.cjs +1 -1
- package/dist/correlation-id.d.cts +0 -1
- package/dist/correlation-id.d.cts.map +1 -1
- package/dist/correlation-id.d.ts +0 -1
- package/dist/correlation-id.d.ts.map +1 -1
- package/dist/correlation-id.js +1 -1
- package/dist/db.d.cts.map +1 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/decorators.cjs +1 -1
- package/dist/decorators.cjs.map +1 -1
- package/dist/decorators.d.cts +1 -2
- package/dist/decorators.d.cts.map +1 -1
- package/dist/decorators.d.ts +1 -2
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +1 -1
- package/dist/decorators.js.map +1 -1
- package/dist/{define-event-CreknLm3.d.ts → define-event-B2z1SBe7.d.ts} +2 -3
- package/dist/define-event-B2z1SBe7.d.ts.map +1 -0
- package/dist/{define-event-HZRizPwz.d.cts → define-event-CGG048HE.d.cts} +2 -3
- package/dist/define-event-CGG048HE.d.cts.map +1 -0
- package/dist/diagnostics.cjs +10 -1
- package/dist/diagnostics.cjs.map +1 -1
- package/dist/diagnostics.d.cts +0 -1
- package/dist/diagnostics.d.cts.map +1 -1
- package/dist/diagnostics.d.ts +0 -1
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +10 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/drain-pipeline.d.cts +12 -5
- package/dist/drain-pipeline.d.cts.map +1 -1
- package/dist/drain-pipeline.d.ts +12 -5
- package/dist/drain-pipeline.d.ts.map +1 -1
- package/dist/enrichers.d.cts.map +1 -1
- package/dist/enrichers.d.ts.map +1 -1
- package/dist/{event-rzA1X5h3.cjs → event-CwIpFdoY.cjs} +3 -3
- package/dist/event-CwIpFdoY.cjs.map +1 -0
- package/dist/{event-BEm5IJ8U.js → event-pLMF5b3d.js} +4 -4
- package/dist/event-pLMF5b3d.js.map +1 -0
- package/dist/{event-subscriber-D1XLkPzi.d.ts → event-subscriber-CWh8sTGh.d.cts} +2 -2
- package/dist/event-subscriber-CWh8sTGh.d.cts.map +1 -0
- package/dist/{event-subscriber-D1XLkPzi.d.cts → event-subscriber-CWh8sTGh.d.ts} +2 -2
- package/dist/event-subscriber-CWh8sTGh.d.ts.map +1 -0
- package/dist/event-subscriber.d.cts +1 -1
- package/dist/event-subscriber.d.ts +1 -1
- package/dist/{event-testing-CfFs3to2.d.ts → event-testing-CA2mIx1E.d.ts} +2 -3
- package/dist/event-testing-CA2mIx1E.d.ts.map +1 -0
- package/dist/{event-testing-BqRnI0z4.d.cts → event-testing-D0qWfqAy.d.cts} +2 -3
- package/dist/event-testing-D0qWfqAy.d.cts.map +1 -0
- package/dist/event-testing.d.cts +1 -1
- package/dist/event-testing.d.ts +1 -1
- package/dist/event.cjs +1 -1
- package/dist/event.d.cts +3 -4
- package/dist/event.d.cts.map +1 -1
- package/dist/event.d.ts +3 -4
- package/dist/event.d.ts.map +1 -1
- package/dist/event.js +1 -1
- package/dist/exporters.d.cts +0 -4
- package/dist/exporters.d.cts.map +1 -1
- package/dist/exporters.d.ts +0 -4
- package/dist/exporters.d.ts.map +1 -1
- package/dist/{filtering-span-processor-B8R8B7Uk.d.ts → filtering-span-processor-BpDagWNa.d.cts} +1 -2
- package/dist/filtering-span-processor-BpDagWNa.d.cts.map +1 -0
- package/dist/{filtering-span-processor-B8R8B7Uk.d.cts → filtering-span-processor-BpDagWNa.d.ts} +1 -2
- package/dist/filtering-span-processor-BpDagWNa.d.ts.map +1 -0
- package/dist/filtering-span-processor.d.cts +1 -1
- package/dist/filtering-span-processor.d.ts +1 -1
- package/dist/functional-Bit6noRu.js +840 -0
- package/dist/functional-Bit6noRu.js.map +1 -0
- package/dist/functional-Cj7PSItS.cjs +890 -0
- package/dist/functional-Cj7PSItS.cjs.map +1 -0
- package/dist/functional.cjs +2 -2
- package/dist/functional.d.cts +79 -130
- package/dist/functional.d.cts.map +1 -1
- package/dist/functional.d.ts +79 -130
- package/dist/functional.d.ts.map +1 -1
- package/dist/functional.js +2 -2
- package/dist/http.cjs +5 -5
- package/dist/http.cjs.map +1 -1
- package/dist/http.d.cts +4 -5
- package/dist/http.d.cts.map +1 -1
- package/dist/http.d.ts +4 -5
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +5 -5
- package/dist/http.js.map +1 -1
- package/dist/{index-eKuioqT1.d.cts → index-BPcxVucm.d.cts} +2 -3
- package/dist/index-BPcxVucm.d.cts.map +1 -0
- package/dist/{index-Ck06vlW2.d.ts → index-DolOVX6F.d.ts} +2 -3
- package/dist/index-DolOVX6F.d.ts.map +1 -0
- package/dist/index.cjs +7 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -14
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +14 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -8
- package/dist/index.js.map +1 -1
- package/dist/{init-BxJEJ9Tn.cjs → init-B2uvZReD.cjs} +19 -10
- package/dist/init-B2uvZReD.cjs.map +1 -0
- package/dist/{init-B7u-DjxM.d.ts → init-CTyqG9qR.d.ts} +24 -17
- package/dist/init-CTyqG9qR.d.ts.map +1 -0
- package/dist/{init-BvBB45-T.js → init-CdEWjhvl.js} +20 -11
- package/dist/init-CdEWjhvl.js.map +1 -0
- package/dist/{init-DSrRmVnz.d.cts → init-a4yPDYqC.d.cts} +24 -17
- package/dist/init-a4yPDYqC.d.cts.map +1 -0
- package/dist/instrumentation.cjs +7 -13
- package/dist/instrumentation.cjs.map +1 -1
- package/dist/instrumentation.d.cts +0 -1
- package/dist/instrumentation.d.cts.map +1 -1
- package/dist/instrumentation.d.ts +0 -1
- package/dist/instrumentation.d.ts.map +1 -1
- package/dist/instrumentation.js +8 -14
- package/dist/instrumentation.js.map +1 -1
- package/dist/{logger-BauSUhUv.d.ts → logger-CN4xpzMd.d.cts} +1 -2
- package/dist/logger-CN4xpzMd.d.cts.map +1 -0
- package/dist/{logger-BauSUhUv.d.cts → logger-CN4xpzMd.d.ts} +1 -2
- package/dist/logger-CN4xpzMd.d.ts.map +1 -0
- package/dist/logger-D3Ej3DII.js.map +1 -1
- package/dist/logger-thMPLpOG.cjs.map +1 -1
- package/dist/logger.d.cts +1 -1
- package/dist/logger.d.ts +1 -1
- package/dist/messaging-adapters.cjs.map +1 -1
- package/dist/messaging-adapters.d.cts +0 -1
- package/dist/messaging-adapters.d.cts.map +1 -1
- package/dist/messaging-adapters.d.ts +0 -1
- package/dist/messaging-adapters.d.ts.map +1 -1
- package/dist/messaging-adapters.js.map +1 -1
- package/dist/messaging-testing.d.cts +0 -1
- package/dist/messaging-testing.d.cts.map +1 -1
- package/dist/messaging-testing.d.ts +0 -1
- package/dist/messaging-testing.d.ts.map +1 -1
- package/dist/messaging.cjs +27 -10
- package/dist/messaging.cjs.map +1 -1
- package/dist/messaging.d.cts +6 -7
- package/dist/messaging.d.cts.map +1 -1
- package/dist/messaging.d.ts +6 -7
- package/dist/messaging.d.ts.map +1 -1
- package/dist/messaging.js +27 -10
- package/dist/messaging.js.map +1 -1
- package/dist/metric-helpers.d.cts +0 -1
- package/dist/metric-helpers.d.cts.map +1 -1
- package/dist/metric-helpers.d.ts +0 -1
- package/dist/metric-helpers.d.ts.map +1 -1
- package/dist/{metric-testing-DXdK3-Q3.d.ts → metric-testing-CWm6UhaR.d.ts} +2 -3
- package/dist/metric-testing-CWm6UhaR.d.ts.map +1 -0
- package/dist/{metric-testing-MxvzChDp.d.cts → metric-testing-CpvP3ZIa.d.cts} +2 -3
- package/dist/metric-testing-CpvP3ZIa.d.cts.map +1 -0
- package/dist/metric-testing.d.cts +1 -1
- package/dist/metric-testing.d.ts +1 -1
- package/dist/metric.d.cts +3 -4
- package/dist/metric.d.cts.map +1 -1
- package/dist/metric.d.ts +3 -4
- package/dist/metric.d.ts.map +1 -1
- package/dist/parse-error.d.cts.map +1 -1
- package/dist/parse-error.d.ts.map +1 -1
- package/dist/processors.cjs +1 -1
- package/dist/processors.d.cts +1 -1
- package/dist/processors.d.ts +1 -1
- package/dist/processors.js +1 -1
- package/dist/register.d.cts +1 -1
- package/dist/register.d.ts +1 -1
- package/dist/{sampling-DfYhDJij.d.cts → sampling-BR9fkSwx.d.cts} +127 -10
- package/dist/sampling-BR9fkSwx.d.cts.map +1 -0
- package/dist/{sampling-CR0Va1VB.d.ts → sampling-CP3e7-Yr.d.ts} +127 -10
- package/dist/sampling-CP3e7-Yr.d.ts.map +1 -0
- package/dist/sampling.cjs +160 -12
- package/dist/sampling.cjs.map +1 -1
- package/dist/sampling.d.cts +2 -2
- package/dist/sampling.d.ts +2 -2
- package/dist/sampling.js +157 -13
- package/dist/sampling.js.map +1 -1
- package/dist/security-schema.d.cts +9 -4
- package/dist/security-schema.d.cts.map +1 -1
- package/dist/security-schema.d.ts +9 -4
- package/dist/security-schema.d.ts.map +1 -1
- package/dist/semantic-conventions-FhSxv-bK.d.cts.map +1 -1
- package/dist/semantic-conventions-FhSxv-bK.d.ts.map +1 -1
- package/dist/semantic-conventions.cjs.map +1 -1
- package/dist/semantic-conventions.js.map +1 -1
- package/dist/semantic-helpers.cjs +85 -304
- package/dist/semantic-helpers.cjs.map +1 -1
- package/dist/semantic-helpers.d.cts +21 -12
- package/dist/semantic-helpers.d.cts.map +1 -1
- package/dist/semantic-helpers.d.ts +21 -12
- package/dist/semantic-helpers.d.ts.map +1 -1
- package/dist/semantic-helpers.js +85 -304
- package/dist/semantic-helpers.js.map +1 -1
- package/dist/slo.cjs +225 -0
- package/dist/slo.cjs.map +1 -0
- package/dist/slo.d.cts +97 -0
- package/dist/slo.d.cts.map +1 -0
- package/dist/slo.d.ts +97 -0
- package/dist/slo.d.ts.map +1 -0
- package/dist/slo.js +223 -0
- package/dist/slo.js.map +1 -0
- package/dist/{span-name-normalizer-8ZOGJuwv.d.ts → span-name-normalizer-CN1-8C76.d.cts} +1 -2
- package/dist/span-name-normalizer-CN1-8C76.d.cts.map +1 -0
- package/dist/{span-name-normalizer-8ZOGJuwv.d.cts → span-name-normalizer-CN1-8C76.d.ts} +1 -2
- package/dist/span-name-normalizer-CN1-8C76.d.ts.map +1 -0
- package/dist/span-name-normalizer.cjs.map +1 -1
- package/dist/span-name-normalizer.d.cts +1 -1
- package/dist/span-name-normalizer.d.ts +1 -1
- package/dist/span-name-normalizer.js.map +1 -1
- package/dist/tail-sampling-processor.d.cts +0 -1
- package/dist/tail-sampling-processor.d.cts.map +1 -1
- package/dist/tail-sampling-processor.d.ts +0 -1
- package/dist/tail-sampling-processor.d.ts.map +1 -1
- package/dist/test-span-collector.cjs.map +1 -1
- package/dist/test-span-collector.d.cts +0 -1
- package/dist/test-span-collector.d.cts.map +1 -1
- package/dist/test-span-collector.d.ts +0 -1
- package/dist/test-span-collector.d.ts.map +1 -1
- package/dist/test-span-collector.js.map +1 -1
- package/dist/testing.cjs +76 -11
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +30 -5
- package/dist/testing.d.cts.map +1 -1
- package/dist/testing.d.ts +30 -5
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +73 -12
- package/dist/testing.js.map +1 -1
- package/dist/{trace-context-Cijqoi6e.d.ts → trace-context-IuyoPyNq.d.cts} +9 -9
- package/dist/trace-context-IuyoPyNq.d.cts.map +1 -0
- package/dist/{trace-context-Cijqoi6e.d.cts → trace-context-IuyoPyNq.d.ts} +9 -9
- package/dist/trace-context-IuyoPyNq.d.ts.map +1 -0
- package/dist/trace-factory-validation-BjVAinz6.js +13 -0
- package/dist/trace-factory-validation-BjVAinz6.js.map +1 -0
- package/dist/trace-factory-validation-Dc8epn87.cjs +19 -0
- package/dist/trace-factory-validation-Dc8epn87.cjs.map +1 -0
- package/dist/trace-helpers.cjs +7 -7
- package/dist/trace-helpers.cjs.map +1 -1
- package/dist/trace-helpers.d.cts +6 -7
- package/dist/trace-helpers.d.cts.map +1 -1
- package/dist/trace-helpers.d.ts +6 -7
- package/dist/trace-helpers.d.ts.map +1 -1
- package/dist/trace-helpers.js +7 -7
- package/dist/trace-helpers.js.map +1 -1
- package/dist/tracer-provider.d.cts +0 -1
- package/dist/tracer-provider.d.cts.map +1 -1
- package/dist/tracer-provider.d.ts +0 -1
- package/dist/tracer-provider.d.ts.map +1 -1
- package/dist/{track-D7O7oIZa.js → track-BBcxEJEC.js} +7 -12
- package/dist/track-BBcxEJEC.js.map +1 -0
- package/dist/{track-eovhCJ-I.cjs → track-BI6dmZ2X.cjs} +6 -17
- package/dist/track-BI6dmZ2X.cjs.map +1 -0
- package/dist/validate.cjs.map +1 -1
- package/dist/validate.d.cts +1 -2
- package/dist/validate.d.cts.map +1 -1
- package/dist/validate.d.ts +1 -2
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js.map +1 -1
- package/dist/validation-attributes.d.cts +17 -8
- package/dist/validation-attributes.d.cts.map +1 -1
- package/dist/validation-attributes.d.ts +17 -8
- package/dist/validation-attributes.d.ts.map +1 -1
- package/dist/webhook.cjs +5 -4
- package/dist/webhook.cjs.map +1 -1
- package/dist/webhook.d.cts +4 -4
- package/dist/webhook.d.cts.map +1 -1
- package/dist/webhook.d.ts +4 -4
- package/dist/webhook.d.ts.map +1 -1
- package/dist/webhook.js +5 -4
- package/dist/webhook.js.map +1 -1
- package/dist/workflow-distributed.cjs +5 -5
- package/dist/workflow-distributed.cjs.map +1 -1
- package/dist/workflow-distributed.d.cts +25 -15
- package/dist/workflow-distributed.d.cts.map +1 -1
- package/dist/workflow-distributed.d.ts +25 -15
- package/dist/workflow-distributed.d.ts.map +1 -1
- package/dist/workflow-distributed.js +5 -5
- package/dist/workflow-distributed.js.map +1 -1
- package/dist/workflow.cjs +24 -30
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +11 -6
- package/dist/workflow.d.cts.map +1 -1
- package/dist/workflow.d.ts +11 -6
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +24 -30
- package/dist/workflow.js.map +1 -1
- package/dist/yaml-config.d.cts +2 -3
- package/dist/yaml-config.d.cts.map +1 -1
- package/dist/yaml-config.d.ts +2 -3
- package/dist/yaml-config.d.ts.map +1 -1
- package/package.json +23 -14
- package/skills/analyze-traces/SKILL.md +42 -13
- package/skills/autotel-core/SKILL.md +24 -17
- package/skills/autotel-events/SKILL.md +1 -1
- package/skills/autotel-frameworks/SKILL.md +41 -6
- package/skills/autotel-instrumentation/SKILL.md +14 -9
- package/skills/autotel-request-logging/SKILL.md +19 -14
- package/skills/autotel-structured-errors/SKILL.md +2 -2
- package/skills/build-audit-trails/SKILL.md +11 -11
- package/skills/build-audit-trails/references/audit-queries.md +3 -3
- package/skills/debug-missing-spans/SKILL.md +12 -12
- package/skills/migrate-to-autotel/SKILL.md +20 -20
- package/skills/review-otel-patterns/SKILL.md +44 -42
- package/skills/review-otel-patterns/references/code-review.md +4 -4
- package/skills/review-otel-patterns/references/processor-pipeline.md +3 -3
- package/skills/review-otel-patterns/references/structured-errors.md +1 -1
- package/skills/review-otel-patterns/references/wide-spans.md +2 -2
- package/skills/tune-sampling/SKILL.md +91 -16
- package/dist/attribute-redacting-processor-DtTS9xxh.d.cts.map +0 -1
- package/dist/attribute-redacting-processor-DtTS9xxh.d.ts.map +0 -1
- package/dist/canonical-log-line-processor-BcRuAdRk.d.ts.map +0 -1
- package/dist/canonical-log-line-processor-CcrDi6TO.cjs.map +0 -1
- package/dist/canonical-log-line-processor-FLezvFCB.js.map +0 -1
- package/dist/canonical-log-line-processor-xvjMgtpF.d.cts.map +0 -1
- package/dist/define-event-CreknLm3.d.ts.map +0 -1
- package/dist/define-event-HZRizPwz.d.cts.map +0 -1
- package/dist/event-BEm5IJ8U.js.map +0 -1
- package/dist/event-rzA1X5h3.cjs.map +0 -1
- package/dist/event-subscriber-D1XLkPzi.d.cts.map +0 -1
- package/dist/event-subscriber-D1XLkPzi.d.ts.map +0 -1
- package/dist/event-testing-BqRnI0z4.d.cts.map +0 -1
- package/dist/event-testing-CfFs3to2.d.ts.map +0 -1
- package/dist/filtering-span-processor-B8R8B7Uk.d.cts.map +0 -1
- package/dist/filtering-span-processor-B8R8B7Uk.d.ts.map +0 -1
- package/dist/functional-CwsPyc4l.cjs +0 -1298
- package/dist/functional-CwsPyc4l.cjs.map +0 -1
- package/dist/functional-dAYhXQPA.js +0 -1248
- package/dist/functional-dAYhXQPA.js.map +0 -1
- package/dist/index-Ck06vlW2.d.ts.map +0 -1
- package/dist/index-eKuioqT1.d.cts.map +0 -1
- package/dist/init-B7u-DjxM.d.ts.map +0 -1
- package/dist/init-BvBB45-T.js.map +0 -1
- package/dist/init-BxJEJ9Tn.cjs.map +0 -1
- package/dist/init-DSrRmVnz.d.cts.map +0 -1
- package/dist/logger-BauSUhUv.d.cts.map +0 -1
- package/dist/logger-BauSUhUv.d.ts.map +0 -1
- package/dist/metric-testing-DXdK3-Q3.d.ts.map +0 -1
- package/dist/metric-testing-MxvzChDp.d.cts.map +0 -1
- package/dist/sampling-CR0Va1VB.d.ts.map +0 -1
- package/dist/sampling-DfYhDJij.d.cts.map +0 -1
- package/dist/span-name-normalizer-8ZOGJuwv.d.cts.map +0 -1
- package/dist/span-name-normalizer-8ZOGJuwv.d.ts.map +0 -1
- package/dist/trace-context-Cijqoi6e.d.cts.map +0 -1
- package/dist/trace-context-Cijqoi6e.d.ts.map +0 -1
- package/dist/track-D7O7oIZa.js.map +0 -1
- package/dist/track-eovhCJ-I.cjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "autotel",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "Write Once, Observe Anywhere",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -35,6 +35,11 @@
|
|
|
35
35
|
"import": "./dist/sampling.js",
|
|
36
36
|
"require": "./dist/sampling.cjs"
|
|
37
37
|
},
|
|
38
|
+
"./analysis": {
|
|
39
|
+
"types": "./dist/analysis.d.ts",
|
|
40
|
+
"import": "./dist/analysis.js",
|
|
41
|
+
"require": "./dist/analysis.cjs"
|
|
42
|
+
},
|
|
38
43
|
"./event": {
|
|
39
44
|
"types": "./dist/event.d.ts",
|
|
40
45
|
"import": "./dist/event.js",
|
|
@@ -60,6 +65,11 @@
|
|
|
60
65
|
"import": "./dist/metric.js",
|
|
61
66
|
"require": "./dist/metric.cjs"
|
|
62
67
|
},
|
|
68
|
+
"./slo": {
|
|
69
|
+
"types": "./dist/slo.d.ts",
|
|
70
|
+
"import": "./dist/slo.js",
|
|
71
|
+
"require": "./dist/slo.cjs"
|
|
72
|
+
},
|
|
63
73
|
"./metric-testing": {
|
|
64
74
|
"types": "./dist/metric-testing.d.ts",
|
|
65
75
|
"import": "./dist/metric-testing.js",
|
|
@@ -280,8 +290,8 @@
|
|
|
280
290
|
"@opentelemetry/sdk-metrics": "^2.9.0",
|
|
281
291
|
"@opentelemetry/sdk-node": "^0.220.0",
|
|
282
292
|
"@opentelemetry/sdk-trace-base": "^2.9.0",
|
|
283
|
-
"@opentelemetry/semantic-conventions": "^1.
|
|
284
|
-
"import-in-the-middle": "^3.3.
|
|
293
|
+
"@opentelemetry/semantic-conventions": "^1.43.0",
|
|
294
|
+
"import-in-the-middle": "^3.3.2"
|
|
285
295
|
},
|
|
286
296
|
"peerDependencies": {
|
|
287
297
|
"@opentelemetry/auto-instrumentations-node": "^0.78.0",
|
|
@@ -336,7 +346,7 @@
|
|
|
336
346
|
}
|
|
337
347
|
},
|
|
338
348
|
"devDependencies": {
|
|
339
|
-
"@arethetypeswrong/cli": "^0.18.
|
|
349
|
+
"@arethetypeswrong/cli": "^0.18.5",
|
|
340
350
|
"@edge-runtime/vm": "^5.0.0",
|
|
341
351
|
"@opentelemetry/auto-instrumentations-node": "^0.78.0",
|
|
342
352
|
"@opentelemetry/context-async-hooks": "^2.9.0",
|
|
@@ -347,26 +357,26 @@
|
|
|
347
357
|
"@opentelemetry/resource-detector-container": "^0.8.11",
|
|
348
358
|
"@opentelemetry/resource-detector-gcp": "^0.55.0",
|
|
349
359
|
"@opentelemetry/sdk-trace-node": "^2.9.0",
|
|
350
|
-
"@swc/core": "^1.15.
|
|
360
|
+
"@swc/core": "^1.15.46",
|
|
351
361
|
"@total-typescript/ts-reset": "^0.6.1",
|
|
352
362
|
"@total-typescript/tsconfig": "^1.0.4",
|
|
353
363
|
"@types/eslint-config-prettier": "^6.11.3",
|
|
354
|
-
"@types/node": "^26.1.
|
|
355
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
356
|
-
"@typescript-eslint/parser": "^8.
|
|
364
|
+
"@types/node": "^26.1.1",
|
|
365
|
+
"@typescript-eslint/eslint-plugin": "^8.65.0",
|
|
366
|
+
"@typescript-eslint/parser": "^8.65.0",
|
|
357
367
|
"eslint-config-prettier": "^10.1.8",
|
|
358
368
|
"eslint-plugin-unicorn": "^64.0.0",
|
|
359
369
|
"pino": "^10.3.1",
|
|
360
|
-
"prettier": "^3.9.
|
|
370
|
+
"prettier": "^3.9.6",
|
|
361
371
|
"rimraf": "^6.1.3",
|
|
362
|
-
"tsdown": "^0.22.
|
|
363
|
-
"tsx": "^4.23.
|
|
372
|
+
"tsdown": "^0.22.12",
|
|
373
|
+
"tsx": "^4.23.1",
|
|
364
374
|
"typescript": "^6.0.3",
|
|
365
|
-
"typescript-eslint": "^8.
|
|
375
|
+
"typescript-eslint": "^8.65.0",
|
|
366
376
|
"unplugin-swc": "^1.5.9",
|
|
367
377
|
"vite-tsconfig-paths": "^6.1.1",
|
|
368
378
|
"vitest": "^4.1.10",
|
|
369
|
-
"vitest-mock-extended": "^
|
|
379
|
+
"vitest-mock-extended": "^5.1.0",
|
|
370
380
|
"winston": "^3.19.0",
|
|
371
381
|
"yaml": "^2.9.0"
|
|
372
382
|
},
|
|
@@ -384,7 +394,6 @@
|
|
|
384
394
|
"dev": "tsdown --watch",
|
|
385
395
|
"lint": "eslint src/**/*.ts",
|
|
386
396
|
"lint:fix": "eslint src/**/*.ts --fix",
|
|
387
|
-
"format": "prettier --write .",
|
|
388
397
|
"format:check": "prettier --check src/**/*.ts",
|
|
389
398
|
"type-check": "tsc --noEmit",
|
|
390
399
|
"test": "vitest run --config vitest.unit.config.ts",
|
|
@@ -10,7 +10,7 @@ license: MIT
|
|
|
10
10
|
|
|
11
11
|
# Analyze traces
|
|
12
12
|
|
|
13
|
-
This skill teaches an AI assistant how to read and reason about OpenTelemetry traces produced by autotel
|
|
13
|
+
This skill teaches an AI assistant how to read and reason about OpenTelemetry traces produced by autotel. Whether they're sitting in a backend, exported to a local JSON dump, or captured in a test.
|
|
14
14
|
|
|
15
15
|
## When to use
|
|
16
16
|
|
|
@@ -24,7 +24,7 @@ This skill teaches an AI assistant how to read and reason about OpenTelemetry tr
|
|
|
24
24
|
|
|
25
25
|
| Source | How to access |
|
|
26
26
|
| ------------------------------ | ------------------------------------------------------------------ |
|
|
27
|
-
| Local debug dump | `.autotel/spans/*.ndjson
|
|
27
|
+
| Local debug dump | `.autotel/spans/*.ndjson`: one span per line, OTLP JSON shape |
|
|
28
28
|
| `InMemorySpanExporter` (tests) | `exporter.getFinishedSpans()` |
|
|
29
29
|
| Backend (interactive) | Jaeger / Tempo / Honeycomb UI; Datadog Trace Search; etc. |
|
|
30
30
|
| Backend (programmatic) | Honeycomb Query API, Tempo `/api/search`, Datadog Logs / Trace API |
|
|
@@ -79,18 +79,47 @@ Key conventions to recognise:
|
|
|
79
79
|
1. Find the trace: filter `service.name = "<svc>" AND http.route = "<route>" AND status = error` for the last hour.
|
|
80
80
|
2. Open the slowest / latest matching trace.
|
|
81
81
|
3. Inspect the root span's `exception.message` and `exception.stacktrace`.
|
|
82
|
-
4. Walk down the child spans
|
|
82
|
+
4. Walk down the child spans: the deepest span with `status.code = ERROR` is usually the culprit.
|
|
83
83
|
5. If using `createStructuredError`, look for `code`, `why`, `internal.*` attributes. They usually answer the "why" without you reading code.
|
|
84
84
|
|
|
85
85
|
### "Why is endpoint X slow?"
|
|
86
86
|
|
|
87
87
|
1. Find a slow trace: `service.name = "<svc>" AND http.route = "<route>" AND duration > p99(duration)`.
|
|
88
|
-
2. View the waterfall
|
|
88
|
+
2. View the waterfall: pinpoint the longest child span by self-time (not wall time).
|
|
89
89
|
3. Common offenders:
|
|
90
|
-
- **Sequential awaits that should be parallel
|
|
91
|
-
- **N+1 queries
|
|
92
|
-
- **Cold starts
|
|
93
|
-
- **Tool retries
|
|
90
|
+
- **Sequential awaits that should be parallel**: sibling spans run end-to-end instead of overlapping.
|
|
91
|
+
- **N+1 queries**: many short same-named spans (`SELECT * FROM …`) under one parent.
|
|
92
|
+
- **Cold starts**: `faas.coldstart=true` in Workers or Lambda.
|
|
93
|
+
- **Tool retries**: gen-ai spans with `gen_ai.response.finish_reasons` containing `error` followed by another call.
|
|
94
|
+
|
|
95
|
+
### "Which requests are affected?"
|
|
96
|
+
|
|
97
|
+
A waterfall explains one slow request. It cannot tell you what the slow ones
|
|
98
|
+
share. Run the core analysis loop instead: split the population on the symptom,
|
|
99
|
+
then score every recorded field by how much the two groups disagree.
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { compareCohorts } from 'autotel/analysis';
|
|
103
|
+
|
|
104
|
+
const isSlow = (event) => Number(event['checkout.duration_ms']) >= 800;
|
|
105
|
+
|
|
106
|
+
const ranked = compareCohorts({
|
|
107
|
+
outlier: events.filter(isSlow),
|
|
108
|
+
baseline: events.filter((event) => !isSlow(event)),
|
|
109
|
+
});
|
|
110
|
+
// [{ field: 'payment.provider', value: 'bank-beta', difference: 0.67, … }]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Feed it any array of flat records: `span.attributes` from a collector, wide
|
|
114
|
+
events from `getRequestLogger()`, or rows returned by a backend query.
|
|
115
|
+
|
|
116
|
+
The loop skips fields whose values never repeat. A request id takes a fresh
|
|
117
|
+
value on every event, so it would bury the answer under noise. Bucket durations
|
|
118
|
+
and payload sizes when you instrument them if you want the loop to rank them.
|
|
119
|
+
|
|
120
|
+
The top row is a hypothesis. A field can move with the problem without causing
|
|
121
|
+
it. You are done when you have named the cohort and confirmed the mechanism in
|
|
122
|
+
two traces drawn from it.
|
|
94
123
|
|
|
95
124
|
### "Follow this user across services"
|
|
96
125
|
|
|
@@ -127,10 +156,10 @@ init({ service: 'my-app', debug: 'pretty', spanDumpPath: '.autotel/spans' });
|
|
|
127
156
|
|
|
128
157
|
| Check | Query / heuristic |
|
|
129
158
|
| ----------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
130
|
-
| **Span name cardinality** | Top-K distinct `name` per service. Anything > a few hundred is a red flag
|
|
159
|
+
| **Span name cardinality** | Top-K distinct `name` per service. Anything > a few hundred is a red flag: likely an unnormalised URL. |
|
|
131
160
|
| **Per-attribute cardinality** | `unique(attribute_value)` per `attribute_key`. UUIDs / emails / `Date.now()` ids in attributes blow up storage. |
|
|
132
|
-
| **Missing `service.name`** | Spans where the resource attribute is empty or `"app"
|
|
133
|
-
| **PII smell** | Look for raw `@`, leading digit-runs of length 16, or `eyJ` prefixes
|
|
161
|
+
| **Missing `service.name`** | Spans where the resource attribute is empty or `"app"`: fix at the SDK init. |
|
|
162
|
+
| **PII smell** | Look for raw `@`, leading digit-runs of length 16, or `eyJ` prefixes: your redactor is off. |
|
|
134
163
|
| **Health-check noise** | Spans with `http.route in (/healthz, /ready)`. Drop with `FilteringSpanProcessor`. |
|
|
135
164
|
|
|
136
165
|
## Reading gen-ai traces
|
|
@@ -161,8 +190,8 @@ If you expected a span and there isn't one:
|
|
|
161
190
|
|
|
162
191
|
1. **Sampling.** Did head sampling drop it? Check `sampling.rates` and `recordedSpans` in any subscriber.
|
|
163
192
|
2. **Workers without `waitUntil`.** Did the request return before the exporter flushed? Move to `defineWorkerFetch` / `wrapModule`.
|
|
164
|
-
3. **`instrumentation.disabled = true
|
|
165
|
-
4. **Exporter rejected.** Check service logs for `OTLP exporter` 4xx / 5xx
|
|
193
|
+
3. **`instrumentation.disabled = true`**: check env-conditional config.
|
|
194
|
+
4. **Exporter rejected.** Check service logs for `OTLP exporter` 4xx / 5xx: bad token, wrong dataset.
|
|
166
195
|
|
|
167
196
|
## Output format
|
|
168
197
|
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
When to use trace vs span vs request logger vs events in Autotel. Init once at startup, package exports (autotel, autotel/event, autotel/testing). Use for setup and choosing the right API.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# Autotel
|
|
7
|
+
# Autotel: Core
|
|
8
8
|
|
|
9
9
|
OpenTelemetry instrumentation for Node.js and edge. Instrument once; stream to any OTLP backend. Use `trace()`/`span()` for spans, `getRequestLogger()` for one snapshot per request, `createStructuredError`/`parseError` for errors, `track()` for product events.
|
|
10
10
|
|
|
@@ -29,17 +29,19 @@ Backend config rule of thumb: use `endpoint` for one OTLP destination, `destinat
|
|
|
29
29
|
## Setup
|
|
30
30
|
|
|
31
31
|
```typescript
|
|
32
|
-
import { init,
|
|
32
|
+
import { init, withTracing, getRequestLogger } from 'autotel';
|
|
33
33
|
|
|
34
34
|
init({ service: 'my-app' });
|
|
35
35
|
|
|
36
|
-
const handler =
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
const handler = withTracing({ name: 'http.request' })(
|
|
37
|
+
(ctx) => async (req: Request) => {
|
|
38
|
+
const log = getRequestLogger(ctx);
|
|
39
|
+
log.set({ path: req.url });
|
|
40
|
+
const result = await doWork(req);
|
|
41
|
+
log.emitNow();
|
|
42
|
+
return result;
|
|
43
|
+
},
|
|
44
|
+
);
|
|
43
45
|
```
|
|
44
46
|
|
|
45
47
|
## Core Patterns
|
|
@@ -47,12 +49,14 @@ const handler = trace((ctx) => async (req: Request) => {
|
|
|
47
49
|
**Factory pattern when you need context (attributes, request logger):**
|
|
48
50
|
|
|
49
51
|
```typescript
|
|
50
|
-
const createUser =
|
|
51
|
-
ctx
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
const createUser = withTracing({ name: 'user.create' })(
|
|
53
|
+
(ctx) => async (data: UserInput) => {
|
|
54
|
+
ctx.setAttribute('user.id', data.id);
|
|
55
|
+
const log = getRequestLogger(ctx);
|
|
56
|
+
log.set({ user: { id: data.id } });
|
|
57
|
+
return db.users.create(data);
|
|
58
|
+
},
|
|
59
|
+
);
|
|
56
60
|
```
|
|
57
61
|
|
|
58
62
|
**Direct pattern when you don't need context:**
|
|
@@ -142,7 +146,7 @@ const handler = trace(async (req) => {
|
|
|
142
146
|
Correct:
|
|
143
147
|
|
|
144
148
|
```typescript
|
|
145
|
-
const handler =
|
|
149
|
+
const handler = withTracing({ name: 'http.request' })((ctx) => async (req) => {
|
|
146
150
|
const log = getRequestLogger(ctx);
|
|
147
151
|
log.set({ route: req.url });
|
|
148
152
|
});
|
|
@@ -156,4 +160,7 @@ Source: docs/AGENT-GUIDE.md
|
|
|
156
160
|
|
|
157
161
|
Targets autotel v2.23.x.
|
|
158
162
|
|
|
159
|
-
See also:
|
|
163
|
+
See also:
|
|
164
|
+
|
|
165
|
+
- `autotel-instrumentation/SKILL.md` for init and trace/span in depth
|
|
166
|
+
- `autotel-request-logging/SKILL.md` for request logger usage
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
track(), Event API, subscribers (e.g. PostHog). Configure subscribers in init(); use track() or Event for product/analytics events.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# Autotel
|
|
7
|
+
# Autotel: Events
|
|
8
8
|
|
|
9
9
|
Send product and analytics events with `track(name, attributes)` or the `Event` class from `autotel/event`. Configure subscribers (e.g. PostHog) in `init()`; they receive events automatically.
|
|
10
10
|
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: autotel-frameworks
|
|
3
3
|
description: >
|
|
4
|
-
Hono, Fastify, TanStack Start, Cloudflare Workers. Middleware and init; getRequestLogger() in handlers. Load when adding Autotel to a web framework.
|
|
4
|
+
Hono, Fastify, TanStack Start, Cloudflare Workers, NestJS, SvelteKit, Elysia, Nuxt. Middleware and init; getRequestLogger() in handlers. Load when adding Autotel to a web framework.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# Autotel
|
|
7
|
+
# Autotel: Framework Integration
|
|
8
8
|
|
|
9
9
|
This skill builds on autotel-instrumentation. Read it first for init() and span creation.
|
|
10
10
|
|
|
11
|
-
Use framework-specific middleware or wrappers to create a span per request; then call `getRequestLogger()` inside handlers.
|
|
11
|
+
Use framework-specific middleware or wrappers to create a span per request; then call `getRequestLogger()` inside handlers. Most frameworks use `autotel-adapters` subpaths (or a thin wrapper package like `autotel-hono`, `autotel-tanstack`, `autotel-cloudflare`, `autotel-nuxt`).
|
|
12
12
|
|
|
13
13
|
When adding new request/exception events in framework handlers, prefer correlated logs (`getRequestLogger().info/warn/error`) instead of introducing new `span.addEvent()` usage.
|
|
14
14
|
|
|
15
|
+
For custom HTTP frameworks, start from `autotel-adapters/toolkit` (`defineFrameworkIntegration`, `createMiddlewareLogger`, `finishResponse` for streaming, `waitUntil` on edge runtimes).
|
|
16
|
+
|
|
15
17
|
## Setup
|
|
16
18
|
|
|
17
19
|
### Hono
|
|
@@ -46,13 +48,43 @@ See packages/autotel-tanstack and apps/example-tanstack-start: middleware and en
|
|
|
46
48
|
|
|
47
49
|
### Cloudflare Workers
|
|
48
50
|
|
|
49
|
-
See packages/autotel-cloudflare: init at top level, wrap the fetch handler so each request gets a span. Use `getRequestLogger()` or trace context inside the handler.
|
|
51
|
+
See packages/autotel-cloudflare: init at top level, wrap the fetch handler so each request gets a span. Use `getRequestLogger()` or trace context inside the handler. Pass `ctx.waitUntil` through adapter options so emit/drain completes after the response.
|
|
52
|
+
|
|
53
|
+
### NestJS
|
|
54
|
+
|
|
55
|
+
Use `AutotelInterceptor` from `autotel-adapters/nestjs` and `useLogger()` in controllers/services (see apps/example-nestjs):
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import { APP_INTERCEPTOR } from '@nestjs/core';
|
|
59
|
+
import { AutotelInterceptor } from 'autotel-adapters/nestjs';
|
|
60
|
+
|
|
61
|
+
@Module({
|
|
62
|
+
providers: [{ provide: APP_INTERCEPTOR, useClass: AutotelInterceptor }],
|
|
63
|
+
})
|
|
64
|
+
export class AppModule {}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### SvelteKit
|
|
68
|
+
|
|
69
|
+
Add `autotelHandle()` in `hooks.server.ts` from `autotel-adapters/sveltekit`; call `useLogger()` in `+server.ts` / server loads. Use `finishResponse` semantics for streaming routes (see toolkit `stream-response`).
|
|
70
|
+
|
|
71
|
+
### Elysia
|
|
72
|
+
|
|
73
|
+
Wrap handlers with `withAutotelHandler()` from `autotel-adapters/elysia` (or the `autotel` alias); use `useLogger()` inside handlers (see apps/example-elysia).
|
|
74
|
+
|
|
75
|
+
### Nuxt
|
|
76
|
+
|
|
77
|
+
Add the `autotel-nuxt` module for zero-config Nitro wiring; server code can use `useLogger()` via `autotel-adapters/nitro` re-exports from `autotel-nuxt/runtime/nitro`.
|
|
50
78
|
|
|
51
79
|
## Core Patterns
|
|
52
80
|
|
|
53
81
|
**Register middleware before routes:** Middleware creates the span; getRequestLogger() needs that active span.
|
|
54
82
|
|
|
55
|
-
**Framework-specific packages:** autotel-hono, autotel-tanstack, autotel-cloudflare. Install the package for your framework and follow its README or CLAUDE.md.
|
|
83
|
+
**Framework-specific packages:** autotel-hono, autotel-tanstack, autotel-cloudflare, autotel-nuxt. Adapter subpaths: autotel-adapters/{express,fastify,next,nitro,nestjs,sveltekit,elysia,...}. Install the package for your framework and follow its README or CLAUDE.md.
|
|
84
|
+
|
|
85
|
+
**Streaming responses:** defer `emitNow` until the body finishes via adapter `finishResponse` / toolkit `bindStreamingResponseLifecycle`.
|
|
86
|
+
|
|
87
|
+
**Edge drain:** pass `waitUntil` (Cloudflare `ExecutionContext`, etc.) so async emit/drain does not block the response.
|
|
56
88
|
|
|
57
89
|
## Common Mistakes
|
|
58
90
|
|
|
@@ -87,4 +119,7 @@ Source: packages/autotel-hono, docs/AGENT-GUIDE.md
|
|
|
87
119
|
|
|
88
120
|
Targets autotel v2.23.x.
|
|
89
121
|
|
|
90
|
-
See also:
|
|
122
|
+
See also:
|
|
123
|
+
|
|
124
|
+
- `autotel-instrumentation/SKILL.md` for init and spans
|
|
125
|
+
- `autotel-request-logging/SKILL.md` for request logger usage
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
trace(), span(), instrument(), init(). Factory vs direct pattern, name inference. Sync init; use node-require for optional deps. Load when wrapping handlers or functions with spans.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# Autotel
|
|
7
|
+
# Autotel: Instrumentation
|
|
8
8
|
|
|
9
9
|
Wrap functions and handlers with `trace()`, `span()`, or `instrument()`. Call `init()` once at app startup. Keep init synchronous; use `safeRequire`/`requireModule` for optional dependencies.
|
|
10
10
|
|
|
@@ -13,7 +13,7 @@ For new event emission, prefer correlated logs (OTel Logs API path) over adding
|
|
|
13
13
|
## Setup
|
|
14
14
|
|
|
15
15
|
```typescript
|
|
16
|
-
import { init, trace } from 'autotel';
|
|
16
|
+
import { init, trace, withTracing } from 'autotel';
|
|
17
17
|
|
|
18
18
|
init({ service: 'my-app' });
|
|
19
19
|
|
|
@@ -25,12 +25,14 @@ const handler = trace(async (req: Request) => {
|
|
|
25
25
|
With span context (attributes, request logger):
|
|
26
26
|
|
|
27
27
|
```typescript
|
|
28
|
-
const handler =
|
|
29
|
-
ctx
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
const handler = withTracing({ name: 'http.request' })(
|
|
29
|
+
(ctx) => async (req: Request) => {
|
|
30
|
+
ctx.setAttribute('http.route', '/api/checkout');
|
|
31
|
+
const log = getRequestLogger(ctx);
|
|
32
|
+
log.set({ path: req.url });
|
|
33
|
+
return processRequest(req);
|
|
34
|
+
},
|
|
35
|
+
);
|
|
34
36
|
```
|
|
35
37
|
|
|
36
38
|
## Core Patterns
|
|
@@ -142,4 +144,7 @@ Source: packages/autotel/package.json exports
|
|
|
142
144
|
|
|
143
145
|
Targets autotel v2.23.x.
|
|
144
146
|
|
|
145
|
-
See also:
|
|
147
|
+
See also:
|
|
148
|
+
|
|
149
|
+
- `autotel-core/SKILL.md` for when to use what
|
|
150
|
+
- `autotel-request-logging/SKILL.md`, since `getRequestLogger` requires an active span
|
|
@@ -4,33 +4,35 @@ description: >
|
|
|
4
4
|
getRequestLogger(), set(), info/warn/error, emitNow(). One snapshot per request; requires active span. Use when adding request-scoped context or replacing scattered console.log.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# Autotel
|
|
7
|
+
# Autotel: Request Logging
|
|
8
8
|
|
|
9
9
|
This skill builds on autotel-instrumentation. Read it first for init and span creation.
|
|
10
10
|
|
|
11
|
-
Accumulate context with `getRequestLogger(ctx)`, `.set()`, and `.info()`/`.warn()`/`.error()`. Call `.emitNow()` (or rely on middleware) to emit one snapshot per request. Request logger requires an active span
|
|
11
|
+
Accumulate context with `getRequestLogger(ctx)`, `.set()`, and `.info()`/`.warn()`/`.error()`. Call `.emitNow()` (or rely on middleware) to emit one snapshot per request. Request logger requires an active span. Use inside `trace()` or framework middleware.
|
|
12
12
|
|
|
13
13
|
Preferred event model: treat request logger emissions as the default way to capture request-correlated events in new code. If a backend still expects span-event rendering, keep compatibility at export/processor level rather than adding new `span.addEvent()` calls in application code.
|
|
14
14
|
|
|
15
15
|
## Setup
|
|
16
16
|
|
|
17
17
|
```typescript
|
|
18
|
-
import { init,
|
|
18
|
+
import { init, withTracing, getRequestLogger } from 'autotel';
|
|
19
19
|
|
|
20
20
|
init({ service: 'my-app' });
|
|
21
21
|
|
|
22
|
-
const handler =
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
const handler = withTracing({ name: 'http.request' })(
|
|
23
|
+
(ctx) => async (req: Request, res: Response) => {
|
|
24
|
+
const log = getRequestLogger(ctx);
|
|
25
|
+
log.set({ method: req.method, path: req.url });
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
const user = await getAuth(req);
|
|
28
|
+
log.set({ user: { id: user.id } });
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
30
|
+
const result = await doWork(req);
|
|
31
|
+
log.set({ result: { id: result.id } });
|
|
32
|
+
log.emitNow();
|
|
33
|
+
return res.json(result);
|
|
34
|
+
},
|
|
35
|
+
);
|
|
34
36
|
```
|
|
35
37
|
|
|
36
38
|
When the framework creates the span (e.g. Hono middleware), call `getRequestLogger()` with no args:
|
|
@@ -91,4 +93,7 @@ Source: packages/autotel/src/request-logger.ts
|
|
|
91
93
|
|
|
92
94
|
Targets autotel v2.23.x.
|
|
93
95
|
|
|
94
|
-
See also:
|
|
96
|
+
See also:
|
|
97
|
+
|
|
98
|
+
- `autotel-instrumentation/SKILL.md` for creating the span
|
|
99
|
+
- `autotel-structured-errors/SKILL.md`, which uses `.error()` to record errors in the snapshot
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
createStructuredError, parseError, recordStructuredError. API errors with message, why, fix, link; client parsing for UI. Use in API routes and client catch blocks.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# Autotel
|
|
7
|
+
# Autotel: Structured Errors
|
|
8
8
|
|
|
9
9
|
Throw errors with `createStructuredError({ message, why?, fix?, link?, status?, cause? })` in API routes and services. On the client, use `parseError(caught)` to get `message`, `status`, `why`, `fix`, `link` for toasts and UI.
|
|
10
10
|
|
|
@@ -122,4 +122,4 @@ Source: docs/AGENT-GUIDE.md
|
|
|
122
122
|
|
|
123
123
|
Targets autotel v2.23.x.
|
|
124
124
|
|
|
125
|
-
See also: autotel-request-logging/SKILL.md
|
|
125
|
+
See also: autotel-request-logging/SKILL.md. Use .error() to record errors in the request snapshot.
|
|
@@ -17,9 +17,9 @@ license: MIT
|
|
|
17
17
|
|
|
18
18
|
# Build audit trails
|
|
19
19
|
|
|
20
|
-
An _audit trail_ is a record of who did what to which resource, when, and whether it was permitted
|
|
20
|
+
An _audit trail_ is a record of who did what to which resource, when, and whether it was permitted. Durable, tamper-evident, and admissible. Operational telemetry (latency, errors, span shapes) is for engineers; audit trails are for compliance, security, and forensics. They overlap technically but differ on every other axis.
|
|
21
21
|
|
|
22
|
-
autotel lets you express both with the same primitive
|
|
22
|
+
autotel lets you express both with the same primitive, a span, but you should keep them on **separate processors** so an audit event never gets dropped by sampling, never gets redacted by a debug rule, and never goes to the same backend as your ops data.
|
|
23
23
|
|
|
24
24
|
## When to use
|
|
25
25
|
|
|
@@ -251,14 +251,14 @@ Verify on the read side: recompute the HMAC over the same sorted attribute set (
|
|
|
251
251
|
|
|
252
252
|
For multi-tenant or extra-strict (HIPAA), use Ed25519 with per-environment keys and rotate.
|
|
253
253
|
|
|
254
|
-
## Step 5: Redaction
|
|
254
|
+
## Step 5: Redaction: what stays and what goes
|
|
255
255
|
|
|
256
256
|
| Field | In audit span? | Notes |
|
|
257
257
|
| ------------------------ | -------------- | ------------------------------------------------------------------------------------- |
|
|
258
258
|
| `enduser.id` | ✅ | Internal user id; never the email |
|
|
259
259
|
| `audit.resource.id` | ✅ | Required for forensics |
|
|
260
260
|
| `client.address` | ✅ | Last-octet redaction acceptable for IPv4 |
|
|
261
|
-
| Free-form payload bodies | ❌ | Never inline raw input
|
|
261
|
+
| Free-form payload bodies | ❌ | Never inline raw input: link by id (`audit.evidence.id`) |
|
|
262
262
|
| Secret values | ❌ | Use `audit.action=secret.read` + `audit.resource.id=sec_abc`, never the secret itself |
|
|
263
263
|
| Authorization headers | ❌ | Token names ok (`bearer.*`), values never |
|
|
264
264
|
|
|
@@ -356,7 +356,7 @@ app.post('/secrets/:id/read', async (c) => {
|
|
|
356
356
|
|
|
357
357
|
### Cloudflare Workers
|
|
358
358
|
|
|
359
|
-
`audit()` from inside `defineWorkerFetch
|
|
359
|
+
`audit()` from inside `defineWorkerFetch`. `ctx.waitUntil` makes sure the audit span is exported before the response returns:
|
|
360
360
|
|
|
361
361
|
```typescript
|
|
362
362
|
export default defineWorkerFetch(
|
|
@@ -452,9 +452,9 @@ To query the trail (denials, per-actor history, tamper detection) across Honeyco
|
|
|
452
452
|
|
|
453
453
|
## Glossary
|
|
454
454
|
|
|
455
|
-
- **Audit span
|
|
456
|
-
- **Force-keep
|
|
457
|
-
- **Denial
|
|
458
|
-
- **Hash-chain
|
|
459
|
-
- **Crypto-shredding
|
|
460
|
-
- **Append-only store
|
|
455
|
+
- **Audit span**: an OpenTelemetry span that records who did what to which resource, marked `audit` / `autotel.audit` so it is routed and retained separately from ops telemetry.
|
|
456
|
+
- **Force-keep**: opting a span out of tail sampling so it is always exported; `forceKeepAuditEvent()` sets the autotel tail-keep flags.
|
|
457
|
+
- **Denial**: an authorization decision that blocked an action; recorded with `audit.outcome = 'deny'` and a reason. Logging denials is as important as logging successes.
|
|
458
|
+
- **Hash-chain**: linking each audit record to the hash of the previous one so removing or reordering records is detectable.
|
|
459
|
+
- **Crypto-shredding**: satisfying an erasure request by destroying the per-subject encryption key rather than deleting the immutable record.
|
|
460
|
+
- **Append-only store**: a backend that rejects updates and deletes (S3 Object Lock, immutable bucket, WORM storage), the destination for audit spans.
|
|
@@ -8,7 +8,7 @@ Run these against the **audit backend** (the append-only one), not your ops back
|
|
|
8
8
|
|
|
9
9
|
A spike in denials is a security signal (credential stuffing, privilege probing).
|
|
10
10
|
|
|
11
|
-
- **Honeycomb
|
|
11
|
+
- **Honeycomb**: filter `autotel.audit = true` AND `audit.outcome = deny`, group by `audit.action` and `enduser.id`, visualize `COUNT`.
|
|
12
12
|
- **Grafana Tempo (TraceQL)**:
|
|
13
13
|
```
|
|
14
14
|
{ span.autotel.audit = true && span.audit.outcome = "deny" }
|
|
@@ -22,7 +22,7 @@ A spike in denials is a security signal (credential stuffing, privilege probing)
|
|
|
22
22
|
|
|
23
23
|
Answer "everything user X did" for an access review or incident.
|
|
24
24
|
|
|
25
|
-
- **Honeycomb
|
|
25
|
+
- **Honeycomb**: filter `enduser.id = "usr_42"`, group by `audit.action`, `audit.resource.type`, order by timestamp.
|
|
26
26
|
- **TraceQL**:
|
|
27
27
|
```
|
|
28
28
|
{ span.enduser.id = "usr_42" && span.autotel.audit = true }
|
|
@@ -49,7 +49,7 @@ Answer "everyone who accessed secret `sec_abc`".
|
|
|
49
49
|
|
|
50
50
|
Confirm sensitive actions are actually being recorded. Group audit spans by `audit.action` and compare against your list of auditable actions. An action that never appears is either never exercised or never audited; both deserve a look.
|
|
51
51
|
|
|
52
|
-
- **Honeycomb
|
|
52
|
+
- **Honeycomb**: group by `audit.action`, `COUNT`, over 30 days.
|
|
53
53
|
|
|
54
54
|
## Detect tampering or missing signatures
|
|
55
55
|
|
|
@@ -18,7 +18,7 @@ When a span you expect isn't in the backend, the cause is somewhere in this chai
|
|
|
18
18
|
code → SDK init → head sampler → processor → exporter → network → backend ingest → backend index
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
This skill walks each link in order with a quick check you can run. Don't skip steps
|
|
21
|
+
This skill walks each link in order with a quick check you can run. Don't skip steps. The cause is rarely where you'd guess.
|
|
22
22
|
|
|
23
23
|
## Step 0: Reproduce locally with the pretty exporter
|
|
24
24
|
|
|
@@ -31,7 +31,7 @@ init({
|
|
|
31
31
|
});
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
If you see the span in stdout, the SDK + sampler are fine
|
|
34
|
+
If you see the span in stdout, the SDK + sampler are fine. Skip to "exporter / network". If you don't, keep reading.
|
|
35
35
|
|
|
36
36
|
## Step 1: Is the SDK actually initialised?
|
|
37
37
|
|
|
@@ -60,9 +60,9 @@ console.log('[autotel-debug] sampling:', getActiveConfig()?.sampling);
|
|
|
60
60
|
|
|
61
61
|
Common gotchas:
|
|
62
62
|
|
|
63
|
-
- `sampling.rates: { server: 5 }
|
|
63
|
+
- `sampling.rates: { server: 5 }`: 5 % means 95 % of spans never start.
|
|
64
64
|
- Inheriting `OTEL_TRACES_SAMPLER_ARG=0.01` from the environment via the OTel default sampler.
|
|
65
|
-
- Your test happens to hit the unsampled branch
|
|
65
|
+
- Your test happens to hit the unsampled branch: instrument with `sampling: { rates: { server: 100 } }` while reproducing.
|
|
66
66
|
|
|
67
67
|
To force sampling for one request, send a `traceparent` with the sampled flag set:
|
|
68
68
|
|
|
@@ -72,13 +72,13 @@ traceparent: 00-<traceid>-<spanid>-01
|
|
|
72
72
|
|
|
73
73
|
(`-01` at the end = sampled.) autotel's parent-based sampler will respect it.
|
|
74
74
|
|
|
75
|
-
## Step 3: Cloudflare Workers
|
|
75
|
+
## Step 3: Cloudflare Workers: `ctx.waitUntil`
|
|
76
76
|
|
|
77
77
|
The single biggest cause of missing spans on the edge: **the response returned before the exporter flushed**.
|
|
78
78
|
|
|
79
79
|
If you're using `addEventListener('fetch', …)` or a hand-rolled `fetch` in a module worker without wiring `ctx.waitUntil(…)` to the export call, async drains drop silently.
|
|
80
80
|
|
|
81
|
-
Fix
|
|
81
|
+
Fix. Switch to `defineWorkerFetch` or `wrapModule`, both of which wire `waitUntil` automatically:
|
|
82
82
|
|
|
83
83
|
```typescript
|
|
84
84
|
import { defineWorkerFetch } from 'autotel-cloudflare';
|
|
@@ -164,16 +164,16 @@ curl -v -X POST $OTLP_ENDPOINT \
|
|
|
164
164
|
-d '{"resourceSpans":[]}'
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
-
Should return `200`. If it doesn't, the problem is between you and the Collector
|
|
167
|
+
Should return `200`. If it doesn't, the problem is between you and the Collector. Not autotel.
|
|
168
168
|
|
|
169
169
|
For Cloudflare Workers, run `wrangler tail` and look for `OTLPExporter` errors.
|
|
170
170
|
|
|
171
|
-
## Step 7: Backend ingest
|
|
171
|
+
## Step 7: Backend ingest: silent rejection
|
|
172
172
|
|
|
173
173
|
Some backends accept the request with a 200 but drop the events:
|
|
174
174
|
|
|
175
175
|
- **Honeycomb**: dataset must exist _and_ the API key must have write access to it. Mismatched key/dataset → silent drop.
|
|
176
|
-
- **Datadog**: check `service` is set (resource attribute `service.name`)
|
|
176
|
+
- **Datadog**: check `service` is set (resource attribute `service.name`): they ignore spans without it.
|
|
177
177
|
- **Sentry**: SDK version mismatch on envelope → 200 but events disappear.
|
|
178
178
|
- **Grafana Cloud Tempo**: spans without `service.name` go to a fallback service called `unknown_service`.
|
|
179
179
|
|
|
@@ -219,9 +219,9 @@ Don't conclude the span is missing until you've waited > 2× the expected lag.
|
|
|
219
219
|
|
|
220
220
|
Some spans land, some don't:
|
|
221
221
|
|
|
222
|
-
- **Trace context broken between services
|
|
223
|
-
- **Async boundary loses context
|
|
224
|
-
- **Cross-runtime call
|
|
222
|
+
- **Trace context broken between services**: outbound HTTP calls aren't propagating `traceparent`. Confirm autotel's global fetch instrumentation is on (`instrumentation.instrumentGlobalFetch: true`, default).
|
|
223
|
+
- **Async boundary loses context**: a `setTimeout` / queue callback ran outside the AsyncLocalStorage scope. Wrap with `trace()` or use `context.with()`.
|
|
224
|
+
- **Cross-runtime call**: Node service → Workers → browser; verify `traceparent` arrives at each leg via response headers / network panel.
|
|
225
225
|
|
|
226
226
|
## When the SDK itself crashes
|
|
227
227
|
|