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/README.md
CHANGED
|
@@ -142,20 +142,20 @@ Replace `NODE_OPTIONS` and 30+ lines of SDK boilerplate with `init()`, wrap func
|
|
|
142
142
|
|
|
143
143
|
`autotel` has ~35 subpath exports. For most scenarios you only need one or two. Cloudflare Workers and other edge runtimes should use [`autotel-cloudflare`](../autotel-cloudflare) or [`autotel-edge`](../autotel-edge), not `autotel` (which expects Node).
|
|
144
144
|
|
|
145
|
-
| Scenario
|
|
146
|
-
|
|
|
147
|
-
| Node service
|
|
148
|
-
| Node service
|
|
149
|
-
| Node service
|
|
150
|
-
| Node service
|
|
151
|
-
| Node service
|
|
152
|
-
| Cloudflare Worker
|
|
153
|
-
| Cloudflare Worker
|
|
154
|
-
| Cloudflare Worker
|
|
155
|
-
| Cloudflare Worker
|
|
156
|
-
| Hono on Workers
|
|
157
|
-
| Vercel Edge / Netlify Edge / Deno Deploy
|
|
158
|
-
| Edge runtime
|
|
145
|
+
| Scenario | Package | Import |
|
|
146
|
+
| -------------------------------------------------- | ------------------------------------- | --------------------------------------------------------------------------- |
|
|
147
|
+
| Node service: init + spans | `autotel` | `import { init, trace, span, withTracing, span } from 'autotel'` |
|
|
148
|
+
| Node service: pino-style logger with trace context | `autotel` | `import { createLogger } from 'autotel/logger'` |
|
|
149
|
+
| Node service: class decorators | `autotel` | `import { Trace, Span } from 'autotel/decorators'` |
|
|
150
|
+
| Node service: Drizzle ORM spans | `autotel-drizzle` | `import { instrumentDrizzleClient } from 'autotel-drizzle'` |
|
|
151
|
+
| Node service: testing assertions | `autotel` | `import { createTraceCollector } from 'autotel/testing'` |
|
|
152
|
+
| Cloudflare Worker: fetch with spans | `autotel-cloudflare` | `import { wrapModule, trace, span, withTracing } from 'autotel-cloudflare'` |
|
|
153
|
+
| Cloudflare Worker: logs only, no `nodejs_compat` | `autotel-cloudflare` | `import { createEdgeLogger } from 'autotel-cloudflare/logger'` |
|
|
154
|
+
| Cloudflare Worker: queue consumer | `autotel-cloudflare` | `import { wrapModule, getQueueLogger } from 'autotel-cloudflare'` |
|
|
155
|
+
| Cloudflare Worker: Durable Object | `autotel-cloudflare` | `import { wrapDurableObject } from 'autotel-cloudflare'` |
|
|
156
|
+
| Hono on Workers | `autotel-cloudflare` + `autotel-hono` | `wrapModule` from `autotel-cloudflare`, middleware from `autotel-hono` |
|
|
157
|
+
| Vercel Edge / Netlify Edge / Deno Deploy | `autotel-edge` | `import { init, trace, span, withTracing } from 'autotel-edge'` |
|
|
158
|
+
| Edge runtime: logs only | `autotel-edge` | `import { createEdgeLogger } from 'autotel-edge/logger'` |
|
|
159
159
|
|
|
160
160
|
## Quick Start
|
|
161
161
|
|
|
@@ -224,7 +224,7 @@ Sampling presets:
|
|
|
224
224
|
### 3. Instrument code with `trace()`
|
|
225
225
|
|
|
226
226
|
```typescript
|
|
227
|
-
import { trace } from 'autotel';
|
|
227
|
+
import { trace, span, withTracing, getActiveTraceContext } from 'autotel';
|
|
228
228
|
|
|
229
229
|
export const createUser = trace(async function createUser(
|
|
230
230
|
data: CreateUserData,
|
|
@@ -236,6 +236,9 @@ export const createUser = trace(async function createUser(
|
|
|
236
236
|
|
|
237
237
|
- Named function expressions automatically become span names (`code.function`).
|
|
238
238
|
- Errors are recorded, spans are ended, and status is set automatically.
|
|
239
|
+
- When inference may be unreliable, use `trace('user.create', fn)` or
|
|
240
|
+
`instrument({ key: 'user.create', fn })`. For a module-sized batch, use
|
|
241
|
+
`instrument({ functions: { createUser, updateUser } })`.
|
|
239
242
|
|
|
240
243
|
### 4. See the value everywhere
|
|
241
244
|
|
|
@@ -522,7 +525,7 @@ These use the `autotel.*` namespace intentionally. OpenTelemetry does not define
|
|
|
522
525
|
Wrap any sync/async function to create spans automatically.
|
|
523
526
|
|
|
524
527
|
```typescript
|
|
525
|
-
import { trace } from 'autotel';
|
|
528
|
+
import { trace, span, withTracing } from 'autotel';
|
|
526
529
|
|
|
527
530
|
export const updateUser = trace(async function updateUser(
|
|
528
531
|
id: string,
|
|
@@ -536,26 +539,27 @@ export const deleteUser = trace('user.delete', async (id: string) => {
|
|
|
536
539
|
return db.users.delete(id);
|
|
537
540
|
});
|
|
538
541
|
|
|
539
|
-
//
|
|
540
|
-
export const createOrder =
|
|
541
|
-
ctx
|
|
542
|
-
|
|
543
|
-
|
|
542
|
+
// Explicit factory form exposes the `ctx` helper
|
|
543
|
+
export const createOrder = withTracing({ name: 'order.create' })(
|
|
544
|
+
(ctx) => async (order: Order) => {
|
|
545
|
+
ctx.setAttribute('order.id', order.id);
|
|
546
|
+
return submit(order);
|
|
547
|
+
},
|
|
548
|
+
);
|
|
544
549
|
|
|
545
|
-
//
|
|
550
|
+
// For one-off work, create the wrapper and call it
|
|
546
551
|
function timed<T>(operation: string, fn: () => Promise<T>): Promise<T> {
|
|
547
|
-
return trace(operation, async (
|
|
548
|
-
|
|
552
|
+
return trace(operation, async () => {
|
|
553
|
+
getActiveTraceContext()?.setAttribute('operation', operation);
|
|
549
554
|
return await fn();
|
|
550
|
-
});
|
|
555
|
+
})();
|
|
551
556
|
}
|
|
552
|
-
// Executes immediately, returns Promise<T> directly
|
|
553
557
|
```
|
|
554
558
|
|
|
555
|
-
**
|
|
559
|
+
**Context access:**
|
|
556
560
|
|
|
557
|
-
1.
|
|
558
|
-
2.
|
|
561
|
+
1. Plain `trace(name?, fn)` wrappers receive their real arguments; use `getActiveTraceContext()` inside.
|
|
562
|
+
2. Explicit factories use `withTracing({ name })(ctx => (...args) => result)`.
|
|
559
563
|
|
|
560
564
|
- Automatic span lifecycle (`start`, `end`, status, and error recording).
|
|
561
565
|
- Function names feed `operation.name`, `code.function`, and events enrichment.
|
|
@@ -566,7 +570,7 @@ function timed<T>(operation: string, fn: () => Promise<T>): Promise<T> {
|
|
|
566
570
|
Create nested spans for individual code blocks without wrapping entire functions.
|
|
567
571
|
|
|
568
572
|
```typescript
|
|
569
|
-
import { span, trace } from 'autotel';
|
|
573
|
+
import { span, trace, withTracing } from 'autotel';
|
|
570
574
|
|
|
571
575
|
export const rollDice = trace(async function rollDice(rolls: number) {
|
|
572
576
|
const results: number[] = [];
|
|
@@ -591,27 +595,29 @@ Nested spans automatically inherit context and correlation IDs.
|
|
|
591
595
|
|
|
592
596
|
### Trace Context (`ctx`)
|
|
593
597
|
|
|
594
|
-
Every `
|
|
598
|
+
Every `withTracing({})((ctx) => ...)` factory receives a type-safe helper backed by `AsyncLocalStorage`.
|
|
595
599
|
|
|
596
600
|
```typescript
|
|
597
|
-
import { trace, recordStructuredError } from 'autotel';
|
|
601
|
+
import { trace, span, withTracing, recordStructuredError } from 'autotel';
|
|
598
602
|
import { SpanStatusCode } from '@opentelemetry/api';
|
|
599
603
|
|
|
600
|
-
export const createUser =
|
|
601
|
-
|
|
602
|
-
|
|
604
|
+
export const createUser = withTracing({})(
|
|
605
|
+
(ctx) => async (input: CreateUserData) => {
|
|
606
|
+
logger.info({ traceId: ctx.traceId }, 'Handling request');
|
|
607
|
+
ctx.setAttributes({ 'user.id': input.id, 'user.plan': input.plan });
|
|
603
608
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
}
|
|
609
|
+
try {
|
|
610
|
+
const user = await db.users.create(input);
|
|
611
|
+
ctx.setStatus({ code: SpanStatusCode.OK });
|
|
612
|
+
return user;
|
|
613
|
+
} catch (error) {
|
|
614
|
+
// Records the error on the span and sets ERROR status. Pair with
|
|
615
|
+
// `getRequestLogger(ctx).error(error)` if you also want a correlated log.
|
|
616
|
+
recordStructuredError(ctx, error as Error);
|
|
617
|
+
throw error;
|
|
618
|
+
}
|
|
619
|
+
},
|
|
620
|
+
);
|
|
615
621
|
```
|
|
616
622
|
|
|
617
623
|
Available helpers: `traceId`, `spanId`, `correlationId`, `setAttribute`, `setAttributes`, `setStatus`, `getBaggage`, `setBaggage`, `deleteBaggage`, `getAllBaggage`.
|
|
@@ -626,11 +632,11 @@ Available helpers: `traceId`, `spanId`, `correlationId`, `setAttribute`, `setAtt
|
|
|
626
632
|
Baggage allows you to propagate custom key-value pairs across distributed traces. Baggage is automatically included in HTTP headers when using `injectTraceContext()` from `autotel/http`.
|
|
627
633
|
|
|
628
634
|
```typescript
|
|
629
|
-
import { trace, withBaggage } from 'autotel';
|
|
635
|
+
import { trace, span, withTracing, withBaggage } from 'autotel';
|
|
630
636
|
import { injectTraceContext } from 'autotel/http';
|
|
631
637
|
|
|
632
638
|
// Set baggage for downstream services
|
|
633
|
-
export const createOrder =
|
|
639
|
+
export const createOrder = withTracing({})((ctx) => async (order: Order) => {
|
|
634
640
|
return await withBaggage({
|
|
635
641
|
baggage: {
|
|
636
642
|
'tenant.id': order.tenantId,
|
|
@@ -654,7 +660,7 @@ export const createOrder = trace((ctx) => async (order: Order) => {
|
|
|
654
660
|
For type-safe baggage operations, use `defineBaggageSchema()`:
|
|
655
661
|
|
|
656
662
|
```typescript
|
|
657
|
-
import { trace, defineBaggageSchema } from 'autotel';
|
|
663
|
+
import { trace, span, withTracing, defineBaggageSchema } from 'autotel';
|
|
658
664
|
|
|
659
665
|
type TenantBaggage = { tenantId: string; region?: string };
|
|
660
666
|
const tenantBaggage = defineBaggageSchema<TenantBaggage>('tenant');
|
|
@@ -678,14 +684,14 @@ export const handler = trace<TenantBaggage>((ctx) => async () => {
|
|
|
678
684
|
Enable `baggage: true` in `init()` to automatically copy all baggage entries to span attributes, making them visible in trace UIs without manual `ctx.setAttribute()` calls:
|
|
679
685
|
|
|
680
686
|
```typescript
|
|
681
|
-
import { init, trace, withBaggage } from 'autotel';
|
|
687
|
+
import { init, trace, span, withTracing, withBaggage } from 'autotel';
|
|
682
688
|
|
|
683
689
|
init({
|
|
684
690
|
service: 'my-app',
|
|
685
691
|
baggage: true, // Auto-copy baggage to span attributes
|
|
686
692
|
});
|
|
687
693
|
|
|
688
|
-
export const processOrder =
|
|
694
|
+
export const processOrder = withTracing({})((ctx) => async (order: Order) => {
|
|
689
695
|
return await withBaggage({
|
|
690
696
|
baggage: {
|
|
691
697
|
'tenant.id': order.tenantId,
|
|
@@ -713,7 +719,13 @@ init({
|
|
|
713
719
|
**Extracting Baggage from Incoming Requests:**
|
|
714
720
|
|
|
715
721
|
```typescript
|
|
716
|
-
import {
|
|
722
|
+
import {
|
|
723
|
+
extractTraceContext,
|
|
724
|
+
trace,
|
|
725
|
+
span,
|
|
726
|
+
withTracing,
|
|
727
|
+
context,
|
|
728
|
+
} from 'autotel';
|
|
717
729
|
|
|
718
730
|
// In Express middleware
|
|
719
731
|
app.use((req, res, next) => {
|
|
@@ -888,7 +900,7 @@ Attachers know WHERE to attach attributes - they handle spans, resources, and ap
|
|
|
888
900
|
import { setUser, httpServer, identify, dbClient } from 'autotel/attributes';
|
|
889
901
|
|
|
890
902
|
// Set user attributes with automatic PII redaction
|
|
891
|
-
export const handleRequest =
|
|
903
|
+
export const handleRequest = withTracing({})((ctx) => async (req) => {
|
|
892
904
|
setUser(ctx, {
|
|
893
905
|
id: req.userId,
|
|
894
906
|
email: req.userEmail, // Automatically redacted by default
|
|
@@ -904,7 +916,7 @@ export const handleRequest = trace((ctx) => async (req) => {
|
|
|
904
916
|
});
|
|
905
917
|
|
|
906
918
|
// Bundle user, session, and device attributes together
|
|
907
|
-
export const identifyUser =
|
|
919
|
+
export const identifyUser = withTracing({})((ctx) => async (data) => {
|
|
908
920
|
identify(ctx, {
|
|
909
921
|
user: { id: data.userId, name: data.userName },
|
|
910
922
|
session: { id: data.sessionId },
|
|
@@ -913,7 +925,7 @@ export const identifyUser = trace((ctx) => async (data) => {
|
|
|
913
925
|
});
|
|
914
926
|
|
|
915
927
|
// Database client attributes
|
|
916
|
-
export const queryUsers =
|
|
928
|
+
export const queryUsers = withTracing({})((ctx) => async () => {
|
|
917
929
|
dbClient(ctx, {
|
|
918
930
|
system: 'postgresql',
|
|
919
931
|
operation: 'SELECT',
|
|
@@ -930,7 +942,7 @@ export const queryUsers = trace((ctx) => async () => {
|
|
|
930
942
|
```typescript
|
|
931
943
|
import { safeSetAttributes, attrs } from 'autotel/attributes';
|
|
932
944
|
|
|
933
|
-
export const processUser =
|
|
945
|
+
export const processUser = withTracing({})((ctx) => async (user) => {
|
|
934
946
|
// Default: PII is redacted automatically
|
|
935
947
|
safeSetAttributes(ctx, attrs.user.data({ email: 'user@example.com' }));
|
|
936
948
|
// → { 'user.email': '[REDACTED]' }
|
|
@@ -980,7 +992,7 @@ Domain helpers bundle multiple attribute groups for common scenarios:
|
|
|
980
992
|
import { transaction } from 'autotel/attributes';
|
|
981
993
|
|
|
982
994
|
// Bundle HTTP request with user context
|
|
983
|
-
export const handleRequest =
|
|
995
|
+
export const handleRequest = withTracing({})((ctx) => async (req) => {
|
|
984
996
|
transaction(ctx, {
|
|
985
997
|
user: { id: req.userId },
|
|
986
998
|
session: { id: req.sessionId },
|
|
@@ -1248,9 +1260,9 @@ Baggage allows key-value pairs to propagate across service boundaries. Autotel p
|
|
|
1248
1260
|
Use the pre-built `BusinessBaggage` schema for common business context:
|
|
1249
1261
|
|
|
1250
1262
|
```typescript
|
|
1251
|
-
import { BusinessBaggage, trace } from 'autotel';
|
|
1263
|
+
import { BusinessBaggage, trace, span, withTracing } from 'autotel';
|
|
1252
1264
|
|
|
1253
|
-
export const processOrder =
|
|
1265
|
+
export const processOrder = withTracing({})((ctx) => async (order: Order) => {
|
|
1254
1266
|
// Set business context (propagates to downstream services)
|
|
1255
1267
|
BusinessBaggage.set(ctx, {
|
|
1256
1268
|
tenantId: order.tenantId,
|
|
@@ -1266,7 +1278,7 @@ export const processOrder = trace((ctx) => async (order: Order) => {
|
|
|
1266
1278
|
});
|
|
1267
1279
|
|
|
1268
1280
|
// In downstream service
|
|
1269
|
-
export const chargeOrder =
|
|
1281
|
+
export const chargeOrder = withTracing({})((ctx) => async () => {
|
|
1270
1282
|
// Read business context
|
|
1271
1283
|
const { tenantId, userId, priority } = BusinessBaggage.get(ctx);
|
|
1272
1284
|
|
|
@@ -1311,7 +1323,7 @@ const OrderBaggage = createSafeBaggageSchema(
|
|
|
1311
1323
|
);
|
|
1312
1324
|
|
|
1313
1325
|
// Use in traced functions
|
|
1314
|
-
export const processOrder =
|
|
1326
|
+
export const processOrder = withTracing({})((ctx) => async (order: Order) => {
|
|
1315
1327
|
// Type-safe set (TypeScript validates fields)
|
|
1316
1328
|
OrderBaggage.set(ctx, {
|
|
1317
1329
|
orderId: order.id,
|
|
@@ -1443,12 +1455,12 @@ export const orderSaga = traceWorkflow({
|
|
|
1443
1455
|
// 2. ReserveInventory.compensate (release)
|
|
1444
1456
|
```
|
|
1445
1457
|
|
|
1446
|
-
**
|
|
1458
|
+
**Context Methods:**
|
|
1447
1459
|
|
|
1448
1460
|
- `ctx.getWorkflowId()` - Get current workflow instance ID
|
|
1449
1461
|
- `ctx.getWorkflowName()` - Get workflow type name
|
|
1450
|
-
- `
|
|
1451
|
-
|
|
1462
|
+
- Step factories receive `StepContext`, which adds `getStepName()`,
|
|
1463
|
+
`getStepIndex()`, and `getWorkflowContext()`
|
|
1452
1464
|
|
|
1453
1465
|
**Compensation Attributes:**
|
|
1454
1466
|
|
|
@@ -1468,7 +1480,7 @@ import { Metric, createHistogram } from 'autotel';
|
|
|
1468
1480
|
const metrics = new Metric('checkout');
|
|
1469
1481
|
const revenue = createHistogram('checkout.revenue');
|
|
1470
1482
|
|
|
1471
|
-
export const processOrder =
|
|
1483
|
+
export const processOrder = withTracing({})((ctx) => async (order) => {
|
|
1472
1484
|
metrics.trackEvent('order.completed', {
|
|
1473
1485
|
orderId: order.id,
|
|
1474
1486
|
amount: order.total,
|
|
@@ -1488,7 +1500,7 @@ Track user behavior, conversion funnels, and business outcomes alongside your Op
|
|
|
1488
1500
|
**Recommended: Configure subscribers in `init()`, use global `track()` function:**
|
|
1489
1501
|
|
|
1490
1502
|
```typescript
|
|
1491
|
-
import { init, track, trace } from 'autotel';
|
|
1503
|
+
import { init, track, trace, span, withTracing } from 'autotel';
|
|
1492
1504
|
import { PostHogSubscriber } from 'autotel-subscribers/posthog';
|
|
1493
1505
|
|
|
1494
1506
|
init({
|
|
@@ -1559,7 +1571,7 @@ npm install @opentelemetry/instrumentation-pino
|
|
|
1559
1571
|
|
|
1560
1572
|
```typescript
|
|
1561
1573
|
import pino from 'pino';
|
|
1562
|
-
import { init, trace } from 'autotel';
|
|
1574
|
+
import { init, trace, span, withTracing } from 'autotel';
|
|
1563
1575
|
|
|
1564
1576
|
const logger = pino({
|
|
1565
1577
|
level: process.env.LOG_LEVEL || 'info',
|
|
@@ -1665,7 +1677,7 @@ init({
|
|
|
1665
1677
|
### Basic Usage
|
|
1666
1678
|
|
|
1667
1679
|
```typescript
|
|
1668
|
-
import { init, trace, setUser, httpServer } from 'autotel';
|
|
1680
|
+
import { init, trace, span, withTracing, setUser, httpServer } from 'autotel';
|
|
1669
1681
|
import pino from 'pino';
|
|
1670
1682
|
|
|
1671
1683
|
const logger = pino();
|
|
@@ -1679,28 +1691,30 @@ init({
|
|
|
1679
1691
|
},
|
|
1680
1692
|
});
|
|
1681
1693
|
|
|
1682
|
-
export const processCheckout =
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1694
|
+
export const processCheckout = withTracing({})(
|
|
1695
|
+
(ctx) => async (order: Order) => {
|
|
1696
|
+
setUser(ctx, {
|
|
1697
|
+
id: order.userId,
|
|
1698
|
+
subscription: order.plan,
|
|
1699
|
+
accountAgeDays: daysSince(order.userCreatedAt),
|
|
1700
|
+
});
|
|
1688
1701
|
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1702
|
+
httpServer(ctx, {
|
|
1703
|
+
method: 'POST',
|
|
1704
|
+
route: '/api/checkout',
|
|
1705
|
+
statusCode: 200,
|
|
1706
|
+
});
|
|
1694
1707
|
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1708
|
+
ctx.setAttributes({
|
|
1709
|
+
'cart.total_cents': order.total,
|
|
1710
|
+
'payment.method': order.paymentMethod,
|
|
1711
|
+
'payment.provider': 'stripe',
|
|
1712
|
+
});
|
|
1700
1713
|
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
}
|
|
1714
|
+
// When this span ends, a canonical log line is automatically emitted
|
|
1715
|
+
// with ALL attributes: user.id, user.subscription, cart.total_cents, etc.
|
|
1716
|
+
},
|
|
1717
|
+
);
|
|
1704
1718
|
```
|
|
1705
1719
|
|
|
1706
1720
|
### What You Get
|
|
@@ -1798,9 +1812,15 @@ It writes correlated request context and log records, so canonical log lines sti
|
|
|
1798
1812
|
wide event per request.
|
|
1799
1813
|
|
|
1800
1814
|
```typescript
|
|
1801
|
-
import {
|
|
1802
|
-
|
|
1803
|
-
|
|
1815
|
+
import {
|
|
1816
|
+
trace,
|
|
1817
|
+
span,
|
|
1818
|
+
withTracing,
|
|
1819
|
+
getRequestLogger,
|
|
1820
|
+
createStructuredError,
|
|
1821
|
+
} from 'autotel';
|
|
1822
|
+
|
|
1823
|
+
export const checkout = withTracing({})((ctx) => async (order: Order) => {
|
|
1804
1824
|
const log = getRequestLogger(ctx);
|
|
1805
1825
|
|
|
1806
1826
|
log.set({ user: { id: order.userId, plan: order.plan } });
|
|
@@ -1884,7 +1904,7 @@ try {
|
|
|
1884
1904
|
|
|
1885
1905
|
`autotel/diagnostics` bridges Node's built-in
|
|
1886
1906
|
[`diagnostics_channel`](https://nodejs.org/api/diagnostics_channel.html) into
|
|
1887
|
-
autotel spans and events
|
|
1907
|
+
autotel spans and events. No monkey-patching, no `import-in-the-middle`. Every
|
|
1888
1908
|
entry point is opt-in and degrades to a no-op on runtimes (edge, old Node) that
|
|
1889
1909
|
lack the underlying channels.
|
|
1890
1910
|
|
|
@@ -1915,8 +1935,8 @@ const stop = instrumentHttp(); // SERVER span per inbound request (parented to t
|
|
|
1915
1935
|
|
|
1916
1936
|
This is an opt-in alternative to `@opentelemetry/instrumentation-http` for span
|
|
1917
1937
|
coverage and propagation. Limitation: a plain channel can't wrap the request
|
|
1918
|
-
handler, so it does **not** set an ambient context for the handler's duration
|
|
1919
|
-
|
|
1938
|
+
handler, so it does **not** set an ambient context for the handler's duration.
|
|
1939
|
+
Application spans created inside a handler won't auto-nest under the SERVER span.
|
|
1920
1940
|
Use `@opentelemetry/instrumentation-http` if you need that nesting.
|
|
1921
1941
|
|
|
1922
1942
|
**Bridge any channel** with the shared primitive (also used by
|
|
@@ -2332,7 +2352,7 @@ Autotel is designed as an **enabler** - it provides composable primitives that l
|
|
|
2332
2352
|
### Instrumenting Queue Consumers
|
|
2333
2353
|
|
|
2334
2354
|
```typescript
|
|
2335
|
-
import { trace, span, track } from 'autotel';
|
|
2355
|
+
import { trace, span, withTracing, span, track } from 'autotel';
|
|
2336
2356
|
|
|
2337
2357
|
// Wrap your consumer handler with trace()
|
|
2338
2358
|
export const processMessage = trace(async function processMessage(
|
|
@@ -2369,7 +2389,7 @@ consumer.on('message', async (msg) => {
|
|
|
2369
2389
|
### Instrumenting Scheduled Jobs / Cron
|
|
2370
2390
|
|
|
2371
2391
|
```typescript
|
|
2372
|
-
import { trace, getMetrics } from 'autotel';
|
|
2392
|
+
import { trace, span, withTracing, getMetrics } from 'autotel';
|
|
2373
2393
|
|
|
2374
2394
|
export const dailyReportJob = trace(async function dailyReportJob() {
|
|
2375
2395
|
const metrics = getMetrics();
|
|
@@ -2632,7 +2652,7 @@ For edge runtimes with different constraints:
|
|
|
2632
2652
|
Cloudflare Workers example:
|
|
2633
2653
|
|
|
2634
2654
|
```typescript
|
|
2635
|
-
import { wrapModule, trace, init } from 'autotel-cloudflare';
|
|
2655
|
+
import { wrapModule, trace, span, withTracing, init } from 'autotel-cloudflare';
|
|
2636
2656
|
|
|
2637
2657
|
const processOrder = trace(async (orderId: string, kv: KVNamespace) => {
|
|
2638
2658
|
return kv.get(orderId);
|
|
@@ -2799,7 +2819,7 @@ Autotel provides utilities that make it easy to instrument any library with Open
|
|
|
2799
2819
|
Here's the minimal code to instrument any library:
|
|
2800
2820
|
|
|
2801
2821
|
```typescript
|
|
2802
|
-
import { trace, SpanKind } from '@opentelemetry/api';
|
|
2822
|
+
import { trace, span, withTracing, SpanKind } from '@opentelemetry/api';
|
|
2803
2823
|
import { runWithSpan, finalizeSpan } from 'autotel/trace-helpers';
|
|
2804
2824
|
|
|
2805
2825
|
const INSTRUMENTED_FLAG = Symbol('instrumented');
|
|
@@ -2837,7 +2857,7 @@ export function instrumentMyLibrary(client) {
|
|
|
2837
2857
|
Let's walk through instrumenting the popular axios HTTP client:
|
|
2838
2858
|
|
|
2839
2859
|
```typescript
|
|
2840
|
-
import { trace, SpanKind } from '@opentelemetry/api';
|
|
2860
|
+
import { trace, span, withTracing, SpanKind } from '@opentelemetry/api';
|
|
2841
2861
|
import { runWithSpan, finalizeSpan } from 'autotel/trace-helpers';
|
|
2842
2862
|
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2843
2863
|
|
|
@@ -3087,7 +3107,7 @@ import {
|
|
|
3087
3107
|
finalizeSpan, // Set status and end span with error handling
|
|
3088
3108
|
getActiveSpan, // Get currently active span
|
|
3089
3109
|
getTraceContext, // Get trace IDs for correlation
|
|
3090
|
-
enrichWithTraceContext, // Add trace context to objects
|
|
3110
|
+
enrichWithTraceContext, // Add trace, withTracing context to objects
|
|
3091
3111
|
getActiveContext, // Get current OpenTelemetry context
|
|
3092
3112
|
} from 'autotel/trace-helpers';
|
|
3093
3113
|
|
|
@@ -3131,7 +3151,9 @@ logger.info(
|
|
|
3131
3151
|
|
|
3132
3152
|
```typescript
|
|
3133
3153
|
import {
|
|
3134
|
-
trace,
|
|
3154
|
+
trace,
|
|
3155
|
+
span,
|
|
3156
|
+
withTracing, // Access to tracer provider
|
|
3135
3157
|
context, // Context management (advanced)
|
|
3136
3158
|
SpanKind, // CLIENT, SERVER, INTERNAL, PRODUCER, CONSUMER
|
|
3137
3159
|
SpanStatusCode, // OK, ERROR, UNSET
|
|
@@ -3226,8 +3248,8 @@ init({
|
|
|
3226
3248
|
|
|
3227
3249
|
## See also
|
|
3228
3250
|
|
|
3229
|
-
- [autotel-cloudflare](../autotel-cloudflare)
|
|
3230
|
-
- [autotel-edge](../autotel-edge)
|
|
3231
|
-
- [autotel-drizzle](../autotel-drizzle)
|
|
3251
|
+
- [autotel-cloudflare](../autotel-cloudflare): Cloudflare Workers with KV/R2/D1/DO instrumentation
|
|
3252
|
+
- [autotel-edge](../autotel-edge): vendor-agnostic edge runtime foundation
|
|
3253
|
+
- [autotel-drizzle](../autotel-drizzle): Drizzle ORM query spans
|
|
3232
3254
|
|
|
3233
3255
|
Happy observing!
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
//#region src/analysis.ts
|
|
4
|
+
const DEFAULT_MAX_VALUES_PER_FIELD = 50;
|
|
5
|
+
const DEFAULT_MAX_UNIQUE_RATIO = .5;
|
|
6
|
+
const DEFAULT_MIN_DIFFERENCE = .1;
|
|
7
|
+
const DEFAULT_LIMIT = 20;
|
|
8
|
+
/**
|
|
9
|
+
* Render a value as a grouping key.
|
|
10
|
+
*
|
|
11
|
+
* Objects and arrays return undefined: a nested structure does not name a
|
|
12
|
+
* cohort, and stringifying it produces noise rather than a testable split.
|
|
13
|
+
*/
|
|
14
|
+
function valueKey(value) {
|
|
15
|
+
if (value === null || value === void 0) return;
|
|
16
|
+
const kind = typeof value;
|
|
17
|
+
if (kind === "string" || kind === "number" || kind === "boolean" || kind === "bigint") return String(value);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Fold one group's events into the shared tally.
|
|
21
|
+
*
|
|
22
|
+
* Both groups accumulate into the same structure, so the caller never builds a
|
|
23
|
+
* combined array or revisits an event once per candidate field.
|
|
24
|
+
*/
|
|
25
|
+
function accumulate(tally, events, group, includes) {
|
|
26
|
+
for (const event of events) for (const [field, raw] of Object.entries(event)) {
|
|
27
|
+
if (!includes(field)) continue;
|
|
28
|
+
const value = valueKey(raw);
|
|
29
|
+
if (value === void 0) continue;
|
|
30
|
+
let values = tally.get(field);
|
|
31
|
+
if (values === void 0) {
|
|
32
|
+
values = /* @__PURE__ */ new Map();
|
|
33
|
+
tally.set(field, values);
|
|
34
|
+
}
|
|
35
|
+
const counts = values.get(value) ?? {
|
|
36
|
+
outlier: 0,
|
|
37
|
+
baseline: 0
|
|
38
|
+
};
|
|
39
|
+
counts[group]++;
|
|
40
|
+
values.set(value, counts);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Rank the field/value pairs that separate an outlier group from a baseline.
|
|
45
|
+
*
|
|
46
|
+
* Returns an empty array when either group is empty, because a fraction over
|
|
47
|
+
* zero events carries no information.
|
|
48
|
+
*
|
|
49
|
+
* @param options - The two populations and the scan limits
|
|
50
|
+
* @returns Differences sorted by absolute strength, strongest first
|
|
51
|
+
*/
|
|
52
|
+
function compareCohorts(options) {
|
|
53
|
+
const { outlier, baseline, fields, ignoreFields, maxValuesPerField = DEFAULT_MAX_VALUES_PER_FIELD, maxUniqueRatio = DEFAULT_MAX_UNIQUE_RATIO, minDifference = DEFAULT_MIN_DIFFERENCE, limit = DEFAULT_LIMIT } = options;
|
|
54
|
+
if (outlier.length === 0 || baseline.length === 0) return [];
|
|
55
|
+
const ignored = new Set(ignoreFields);
|
|
56
|
+
const selected = fields === void 0 ? void 0 : new Set(fields);
|
|
57
|
+
const includes = (field) => !ignored.has(field) && (selected === void 0 || selected.has(field));
|
|
58
|
+
const tally = /* @__PURE__ */ new Map();
|
|
59
|
+
accumulate(tally, outlier, "outlier", includes);
|
|
60
|
+
accumulate(tally, baseline, "baseline", includes);
|
|
61
|
+
const results = [];
|
|
62
|
+
const total = outlier.length + baseline.length;
|
|
63
|
+
for (const [field, values] of tally) {
|
|
64
|
+
if (values.size > maxValuesPerField || values.size > total * maxUniqueRatio) continue;
|
|
65
|
+
for (const [value, counts] of values) {
|
|
66
|
+
const outlierFraction = counts.outlier / outlier.length;
|
|
67
|
+
const baselineFraction = counts.baseline / baseline.length;
|
|
68
|
+
const difference = outlierFraction - baselineFraction;
|
|
69
|
+
if (Math.abs(difference) < minDifference) continue;
|
|
70
|
+
results.push({
|
|
71
|
+
field,
|
|
72
|
+
value,
|
|
73
|
+
outlierFraction,
|
|
74
|
+
baselineFraction,
|
|
75
|
+
difference,
|
|
76
|
+
outlierCount: counts.outlier,
|
|
77
|
+
baselineCount: counts.baseline
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
results.sort((a, b) => Math.abs(b.difference) - Math.abs(a.difference) || b.difference - a.difference || a.field.localeCompare(b.field) || a.value.localeCompare(b.value));
|
|
82
|
+
return results.slice(0, limit);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
exports.compareCohorts = compareCohorts;
|
|
87
|
+
//# sourceMappingURL=analysis.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analysis.cjs","names":[],"sources":["../src/analysis.ts"],"sourcesContent":["/**\n * Core Analysis Loop\n *\n * Debugging from first principles: take the events you care about, take a\n * comparable normal population, and ask which recorded field separates them.\n * The loop is mechanical, so run it in code instead of clicking through a\n * dashboard.\n *\n * `compareCohorts()` scores every field/value pair by how much more often it\n * appears in the outlier group than in the baseline. The top result names the\n * cohort behind a regression, which is the hypothesis you then verify against\n * individual traces.\n *\n * The input is any array of flat records: wide events from\n * `getRequestLogger()`, `TestSpan.attributes` from `autotel/testing`, or rows\n * returned by a backend query.\n *\n * @example Find the cohort behind a latency regression\n * ```typescript\n * import { compareCohorts } from 'autotel/analysis'\n *\n * const slow = events.filter((event) => event['duration_ms'] >= 800)\n * const normal = events.filter((event) => event['duration_ms'] < 800)\n *\n * const [top] = compareCohorts({ outlier: slow, baseline: normal })\n * // { field: 'payment.provider', value: 'bank-beta', difference: 0.94, ... }\n * ```\n */\n\n/** A flat telemetry record. Span attributes and wide events both satisfy it. */\nexport type AnalysisEvent = Record<string, unknown>;\n\n/** How strongly one field/value pair separates the outlier group from the baseline. */\nexport interface CohortDifference {\n /** Attribute name, such as `payment.provider`. */\n field: string;\n /** The value, rendered as a string for display and grouping. */\n value: string;\n /** Share of outlier events carrying this value, 0-1. */\n outlierFraction: number;\n /** Share of baseline events carrying this value, 0-1. */\n baselineFraction: number;\n /** `outlierFraction - baselineFraction`. Positive means over-represented in the outliers. */\n difference: number;\n outlierCount: number;\n baselineCount: number;\n}\n\nexport interface CompareCohortsOptions {\n /** The events you are investigating: the errors, the slow requests, the failed checkouts. */\n outlier: readonly AnalysisEvent[];\n /** A comparable normal population from the same time range. */\n baseline: readonly AnalysisEvent[];\n /** Restrict the scan to these fields. Defaults to every field seen in either group. */\n fields?: readonly string[];\n /** Fields to skip, such as identifiers you already know are unique. */\n ignoreFields?: readonly string[];\n /**\n * Skip a field once it holds more distinct values than this across both\n * groups. Default 50.\n */\n maxValuesPerField?: number;\n /**\n * Skip a field whose distinct values outnumber this share of the combined\n * events. A request id or a raw duration takes a near-unique value per\n * event, so its values never repeat and it cannot describe a cohort. The\n * ratio catches those fields in small populations, where an absolute cap\n * does not. Bucket numeric fields at instrumentation time if you want them\n * ranked. Default 0.5.\n */\n maxUniqueRatio?: number;\n /** Drop pairs whose absolute difference falls below this. Default 0.1. */\n minDifference?: number;\n /** Maximum results to return, strongest first. Default 20. */\n limit?: number;\n}\n\nconst DEFAULT_MAX_VALUES_PER_FIELD = 50;\nconst DEFAULT_MAX_UNIQUE_RATIO = 0.5;\nconst DEFAULT_MIN_DIFFERENCE = 0.1;\nconst DEFAULT_LIMIT = 20;\n\n/**\n * Render a value as a grouping key.\n *\n * Objects and arrays return undefined: a nested structure does not name a\n * cohort, and stringifying it produces noise rather than a testable split.\n */\nfunction valueKey(value: unknown): string | undefined {\n if (value === null || value === undefined) {\n return undefined;\n }\n const kind = typeof value;\n if (\n kind === 'string' ||\n kind === 'number' ||\n kind === 'boolean' ||\n kind === 'bigint'\n ) {\n return String(value);\n }\n return undefined;\n}\n\n/** Occurrences of one value, split by the group it appeared in. */\ninterface ValueCounts {\n outlier: number;\n baseline: number;\n}\n\n/** field -> value -> counts */\ntype FieldTally = Map<string, Map<string, ValueCounts>>;\n\n/**\n * Fold one group's events into the shared tally.\n *\n * Both groups accumulate into the same structure, so the caller never builds a\n * combined array or revisits an event once per candidate field.\n */\nfunction accumulate(\n tally: FieldTally,\n events: readonly AnalysisEvent[],\n group: keyof ValueCounts,\n includes: (field: string) => boolean,\n): void {\n for (const event of events) {\n for (const [field, raw] of Object.entries(event)) {\n if (!includes(field)) {\n continue;\n }\n const value = valueKey(raw);\n if (value === undefined) {\n continue;\n }\n let values = tally.get(field);\n if (values === undefined) {\n values = new Map<string, ValueCounts>();\n tally.set(field, values);\n }\n const counts = values.get(value) ?? { outlier: 0, baseline: 0 };\n counts[group]++;\n values.set(value, counts);\n }\n }\n}\n\n/**\n * Rank the field/value pairs that separate an outlier group from a baseline.\n *\n * Returns an empty array when either group is empty, because a fraction over\n * zero events carries no information.\n *\n * @param options - The two populations and the scan limits\n * @returns Differences sorted by absolute strength, strongest first\n */\nexport function compareCohorts(\n options: CompareCohortsOptions,\n): CohortDifference[] {\n const {\n outlier,\n baseline,\n fields,\n ignoreFields,\n maxValuesPerField = DEFAULT_MAX_VALUES_PER_FIELD,\n maxUniqueRatio = DEFAULT_MAX_UNIQUE_RATIO,\n minDifference = DEFAULT_MIN_DIFFERENCE,\n limit = DEFAULT_LIMIT,\n } = options;\n\n if (outlier.length === 0 || baseline.length === 0) {\n return [];\n }\n\n const ignored = new Set(ignoreFields);\n const selected = fields === undefined ? undefined : new Set(fields);\n const includes = (field: string) =>\n !ignored.has(field) && (selected === undefined || selected.has(field));\n\n const tally: FieldTally = new Map();\n accumulate(tally, outlier, 'outlier', includes);\n accumulate(tally, baseline, 'baseline', includes);\n\n const results: CohortDifference[] = [];\n const total = outlier.length + baseline.length;\n\n for (const [field, values] of tally) {\n if (\n values.size > maxValuesPerField ||\n values.size > total * maxUniqueRatio\n ) {\n continue;\n }\n\n for (const [value, counts] of values) {\n const outlierFraction = counts.outlier / outlier.length;\n const baselineFraction = counts.baseline / baseline.length;\n const difference = outlierFraction - baselineFraction;\n\n if (Math.abs(difference) < minDifference) {\n continue;\n }\n\n results.push({\n field,\n value,\n outlierFraction,\n baselineFraction,\n difference,\n outlierCount: counts.outlier,\n baselineCount: counts.baseline,\n });\n }\n }\n\n // Strongest first. On a tie prefer the over-represented value, because a\n // cohort you can open traces from beats one defined by its absence. Fall\n // back to field and value so repeated runs return the same order.\n results.sort(\n (a, b) =>\n Math.abs(b.difference) - Math.abs(a.difference) ||\n b.difference - a.difference ||\n a.field.localeCompare(b.field) ||\n a.value.localeCompare(b.value),\n );\n\n return results.slice(0, limit);\n}\n"],"mappings":";;;AA6EA,MAAM,+BAA+B;AACrC,MAAM,2BAA2B;AACjC,MAAM,yBAAyB;AAC/B,MAAM,gBAAgB;;;;;;;AAQtB,SAAS,SAAS,OAAoC;CACpD,IAAI,UAAU,QAAQ,UAAU,QAC9B;CAEF,MAAM,OAAO,OAAO;CACpB,IACE,SAAS,YACT,SAAS,YACT,SAAS,aACT,SAAS,UAET,OAAO,OAAO,KAAK;AAGvB;;;;;;;AAiBA,SAAS,WACP,OACA,QACA,OACA,UACM;CACN,KAAK,MAAM,SAAS,QAClB,KAAK,MAAM,CAAC,OAAO,QAAQ,OAAO,QAAQ,KAAK,GAAG;EAChD,IAAI,CAAC,SAAS,KAAK,GACjB;EAEF,MAAM,QAAQ,SAAS,GAAG;EAC1B,IAAI,UAAU,QACZ;EAEF,IAAI,SAAS,MAAM,IAAI,KAAK;EAC5B,IAAI,WAAW,QAAW;GACxB,yBAAS,IAAI,IAAyB;GACtC,MAAM,IAAI,OAAO,MAAM;EACzB;EACA,MAAM,SAAS,OAAO,IAAI,KAAK,KAAK;GAAE,SAAS;GAAG,UAAU;EAAE;EAC9D,OAAO,MAAM;EACb,OAAO,IAAI,OAAO,MAAM;CAC1B;AAEJ;;;;;;;;;;AAWA,SAAgB,eACd,SACoB;CACpB,MAAM,EACJ,SACA,UACA,QACA,cACA,oBAAoB,8BACpB,iBAAiB,0BACjB,gBAAgB,wBAChB,QAAQ,kBACN;CAEJ,IAAI,QAAQ,WAAW,KAAK,SAAS,WAAW,GAC9C,OAAO,CAAC;CAGV,MAAM,UAAU,IAAI,IAAI,YAAY;CACpC,MAAM,WAAW,WAAW,SAAY,SAAY,IAAI,IAAI,MAAM;CAClE,MAAM,YAAY,UAChB,CAAC,QAAQ,IAAI,KAAK,MAAM,aAAa,UAAa,SAAS,IAAI,KAAK;CAEtE,MAAM,wBAAoB,IAAI,IAAI;CAClC,WAAW,OAAO,SAAS,WAAW,QAAQ;CAC9C,WAAW,OAAO,UAAU,YAAY,QAAQ;CAEhD,MAAM,UAA8B,CAAC;CACrC,MAAM,QAAQ,QAAQ,SAAS,SAAS;CAExC,KAAK,MAAM,CAAC,OAAO,WAAW,OAAO;EACnC,IACE,OAAO,OAAO,qBACd,OAAO,OAAO,QAAQ,gBAEtB;EAGF,KAAK,MAAM,CAAC,OAAO,WAAW,QAAQ;GACpC,MAAM,kBAAkB,OAAO,UAAU,QAAQ;GACjD,MAAM,mBAAmB,OAAO,WAAW,SAAS;GACpD,MAAM,aAAa,kBAAkB;GAErC,IAAI,KAAK,IAAI,UAAU,IAAI,eACzB;GAGF,QAAQ,KAAK;IACX;IACA;IACA;IACA;IACA;IACA,cAAc,OAAO;IACrB,eAAe,OAAO;GACxB,CAAC;EACH;CACF;CAKA,QAAQ,MACL,GAAG,MACF,KAAK,IAAI,EAAE,UAAU,IAAI,KAAK,IAAI,EAAE,UAAU,KAC9C,EAAE,aAAa,EAAE,cACjB,EAAE,MAAM,cAAc,EAAE,KAAK,KAC7B,EAAE,MAAM,cAAc,EAAE,KAAK,CACjC;CAEA,OAAO,QAAQ,MAAM,GAAG,KAAK;AAC/B"}
|