autotel 4.2.5 → 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 +10 -15
- 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 +11 -16
- 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 +13 -1
- package/dist/test-span-collector.cjs.map +1 -1
- package/dist/test-span-collector.d.cts +8 -1
- package/dist/test-span-collector.d.cts.map +1 -1
- package/dist/test-span-collector.d.ts +8 -1
- package/dist/test-span-collector.d.ts.map +1 -1
- package/dist/test-span-collector.js +13 -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.cjs +27 -0
- package/dist/tracer-provider.cjs.map +1 -1
- package/dist/tracer-provider.d.cts +19 -2
- package/dist/tracer-provider.d.cts.map +1 -1
- package/dist/tracer-provider.d.ts +19 -2
- package/dist/tracer-provider.d.ts.map +1 -1
- package/dist/tracer-provider.js +27 -1
- package/dist/tracer-provider.js.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-BCtxvYir.cjs +0 -1315
- package/dist/functional-BCtxvYir.cjs.map +0 -1
- package/dist/functional-CrAq8Az8.js +0 -1265
- package/dist/functional-CrAq8Az8.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/dist/slo.cjs
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_config = require('./config.cjs');
|
|
3
|
+
let _opentelemetry_api = require("@opentelemetry/api");
|
|
4
|
+
|
|
5
|
+
//#region src/slo.ts
|
|
6
|
+
/**
|
|
7
|
+
* Service level objective tracking and burn-rate evaluation.
|
|
8
|
+
*
|
|
9
|
+
* The tracker keeps a bounded rolling window in memory, records low-cardinality
|
|
10
|
+
* OpenTelemetry metrics, and returns snapshots that callers can feed into alert
|
|
11
|
+
* evaluation. Production systems can persist the emitted metrics in their
|
|
12
|
+
* telemetry backend while tests use the same calculations in process.
|
|
13
|
+
*/
|
|
14
|
+
function validateDefinition(definition) {
|
|
15
|
+
if (!definition.name.trim()) throw new Error("SLO name must not be empty");
|
|
16
|
+
if (!Number.isFinite(definition.target) || definition.target <= 0 || definition.target >= 1) throw new Error("SLO target must be greater than 0 and less than 1");
|
|
17
|
+
if (!Number.isFinite(definition.windowMs) || definition.windowMs <= 0) throw new Error("SLO windowMs must be greater than 0");
|
|
18
|
+
}
|
|
19
|
+
function validateThreshold(name, threshold) {
|
|
20
|
+
if (!Number.isFinite(threshold) || threshold <= 0) throw new Error(`${name} must be greater than 0`);
|
|
21
|
+
}
|
|
22
|
+
function validateForecastOptions(options) {
|
|
23
|
+
if (!Number.isFinite(options.baselineMs) || options.baselineMs <= 0) throw new Error("baselineMs must be greater than 0");
|
|
24
|
+
if (!Number.isFinite(options.lookaheadMs) || options.lookaheadMs <= 0) throw new Error("lookaheadMs must be greater than 0");
|
|
25
|
+
if (options.lookaheadMs > options.baselineMs * 4) throw new Error("lookaheadMs must not exceed 4 times baselineMs");
|
|
26
|
+
if (options.expectedEventsInLookahead !== void 0 && (!Number.isFinite(options.expectedEventsInLookahead) || options.expectedEventsInLookahead < 0)) throw new Error("expectedEventsInLookahead must not be negative");
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Track good and bad events for one rolling-window service level objective.
|
|
30
|
+
*/
|
|
31
|
+
function createSloTracker(definition, options = {}) {
|
|
32
|
+
validateDefinition(definition);
|
|
33
|
+
const stableDefinition = Object.freeze({ ...definition });
|
|
34
|
+
const now = options.now ?? Date.now;
|
|
35
|
+
const observations = [];
|
|
36
|
+
let firstLiveIndex = 0;
|
|
37
|
+
let outcomeCounter;
|
|
38
|
+
let burnRateHistogram;
|
|
39
|
+
if (options.recordMetrics !== false) {
|
|
40
|
+
const meter = require_config.getConfig().meter;
|
|
41
|
+
outcomeCounter = meter.createCounter("autotel.slo.outcomes", {
|
|
42
|
+
description: "Good and bad events recorded against a service level objective",
|
|
43
|
+
unit: "1"
|
|
44
|
+
});
|
|
45
|
+
burnRateHistogram = meter.createHistogram("autotel.slo.burn_rate", {
|
|
46
|
+
description: "Error-budget burn rate for a service level objective",
|
|
47
|
+
unit: "1"
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const prune = (at) => {
|
|
51
|
+
const cutoff = at - stableDefinition.windowMs;
|
|
52
|
+
while (firstLiveIndex < observations.length && observations[firstLiveIndex].timestamp < cutoff) firstLiveIndex += 1;
|
|
53
|
+
if (firstLiveIndex > 1024 && firstLiveIndex * 2 >= observations.length) {
|
|
54
|
+
observations.splice(0, firstLiveIndex);
|
|
55
|
+
firstLiveIndex = 0;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const calculate = (at) => {
|
|
59
|
+
prune(at);
|
|
60
|
+
let good = 0;
|
|
61
|
+
for (let index = firstLiveIndex; index < observations.length; index += 1) if (observations[index].outcome === "good") good += 1;
|
|
62
|
+
const total = observations.length - firstLiveIndex;
|
|
63
|
+
const bad = total - good;
|
|
64
|
+
const sli = total === 0 ? void 0 : good / total;
|
|
65
|
+
const errorBudgetFraction = 1 - stableDefinition.target;
|
|
66
|
+
const burnRate = (total === 0 ? 0 : bad / total) / errorBudgetFraction;
|
|
67
|
+
const budgetConsumed = burnRate;
|
|
68
|
+
return {
|
|
69
|
+
...stableDefinition,
|
|
70
|
+
observedAt: at,
|
|
71
|
+
total,
|
|
72
|
+
good,
|
|
73
|
+
bad,
|
|
74
|
+
sli,
|
|
75
|
+
errorBudgetFraction,
|
|
76
|
+
budgetConsumed,
|
|
77
|
+
budgetRemaining: 1 - budgetConsumed,
|
|
78
|
+
burnRate,
|
|
79
|
+
meetsTarget: sli === void 0 || sli >= stableDefinition.target
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
return {
|
|
83
|
+
definition: stableDefinition,
|
|
84
|
+
record(outcome, attributes = {}) {
|
|
85
|
+
if (outcome !== "good" && outcome !== "bad") throw new Error("SLO outcome must be \"good\" or \"bad\"");
|
|
86
|
+
const timestamp = now();
|
|
87
|
+
observations.push({
|
|
88
|
+
outcome,
|
|
89
|
+
timestamp
|
|
90
|
+
});
|
|
91
|
+
const current = calculate(timestamp);
|
|
92
|
+
const metricAttributes = {
|
|
93
|
+
...attributes,
|
|
94
|
+
"slo.name": stableDefinition.name,
|
|
95
|
+
"slo.outcome": outcome
|
|
96
|
+
};
|
|
97
|
+
outcomeCounter?.add(1, metricAttributes);
|
|
98
|
+
burnRateHistogram?.record(current.burnRate, { "slo.name": stableDefinition.name });
|
|
99
|
+
_opentelemetry_api.trace.getActiveSpan()?.setAttributes({
|
|
100
|
+
"slo.name": stableDefinition.name,
|
|
101
|
+
"slo.target": stableDefinition.target,
|
|
102
|
+
"slo.outcome": outcome,
|
|
103
|
+
"slo.burn_rate": current.burnRate
|
|
104
|
+
});
|
|
105
|
+
return current;
|
|
106
|
+
},
|
|
107
|
+
snapshot(at = now()) {
|
|
108
|
+
return calculate(at);
|
|
109
|
+
},
|
|
110
|
+
forecast(forecastOptions) {
|
|
111
|
+
validateForecastOptions(forecastOptions);
|
|
112
|
+
if (forecastOptions.baselineMs > stableDefinition.windowMs) throw new Error("baselineMs must not exceed the SLO windowMs");
|
|
113
|
+
const observedAt = now();
|
|
114
|
+
prune(observedAt);
|
|
115
|
+
const baselineCutoff = observedAt - forecastOptions.baselineMs;
|
|
116
|
+
const retainedCutoff = observedAt + forecastOptions.lookaheadMs - stableDefinition.windowMs;
|
|
117
|
+
let baselineTotal = 0;
|
|
118
|
+
let baselineBad = 0;
|
|
119
|
+
let retainedTotal = 0;
|
|
120
|
+
let retainedBad = 0;
|
|
121
|
+
for (let index = firstLiveIndex; index < observations.length; index += 1) {
|
|
122
|
+
const observation = observations[index];
|
|
123
|
+
if (observation.timestamp >= baselineCutoff) {
|
|
124
|
+
baselineTotal += 1;
|
|
125
|
+
if (observation.outcome === "bad") baselineBad += 1;
|
|
126
|
+
}
|
|
127
|
+
if (observation.timestamp >= retainedCutoff) {
|
|
128
|
+
retainedTotal += 1;
|
|
129
|
+
if (observation.outcome === "bad") retainedBad += 1;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (baselineTotal === 0) return {
|
|
133
|
+
name: stableDefinition.name,
|
|
134
|
+
target: stableDefinition.target,
|
|
135
|
+
observedAt,
|
|
136
|
+
baselineMs: forecastOptions.baselineMs,
|
|
137
|
+
lookaheadMs: forecastOptions.lookaheadMs,
|
|
138
|
+
baselineTotal: 0,
|
|
139
|
+
baselineBad: 0,
|
|
140
|
+
baselineFailureRate: 0,
|
|
141
|
+
retainedTotal,
|
|
142
|
+
retainedBad,
|
|
143
|
+
projectedTotal: retainedTotal,
|
|
144
|
+
projectedBad: retainedBad,
|
|
145
|
+
projectedSli: retainedTotal === 0 ? void 0 : (retainedTotal - retainedBad) / retainedTotal,
|
|
146
|
+
alerting: false,
|
|
147
|
+
reason: "no-baseline-traffic"
|
|
148
|
+
};
|
|
149
|
+
const baselineFailureRate = baselineBad / baselineTotal;
|
|
150
|
+
const expectedEventsInLookahead = forecastOptions.expectedEventsInLookahead ?? baselineTotal * forecastOptions.lookaheadMs / forecastOptions.baselineMs;
|
|
151
|
+
const projectedFailures = baselineFailureRate * expectedEventsInLookahead;
|
|
152
|
+
const projectedTotal = retainedTotal + expectedEventsInLookahead;
|
|
153
|
+
const projectedBad = retainedBad + projectedFailures;
|
|
154
|
+
const projectedSli = projectedTotal === 0 ? void 0 : (projectedTotal - projectedBad) / projectedTotal;
|
|
155
|
+
const allowedFailureRate = 1 - stableDefinition.target;
|
|
156
|
+
const remainingFailures = allowedFailureRate * retainedTotal - retainedBad;
|
|
157
|
+
const netFailureRate = baselineFailureRate - allowedFailureRate;
|
|
158
|
+
const eventRate = expectedEventsInLookahead / forecastOptions.lookaheadMs;
|
|
159
|
+
const timeToExhaustionMs = remainingFailures <= 0 ? 0 : netFailureRate > 0 && eventRate > 0 ? remainingFailures / (netFailureRate * eventRate) : void 0;
|
|
160
|
+
const alerting = projectedSli !== void 0 && projectedSli < stableDefinition.target;
|
|
161
|
+
return {
|
|
162
|
+
name: stableDefinition.name,
|
|
163
|
+
target: stableDefinition.target,
|
|
164
|
+
observedAt,
|
|
165
|
+
baselineMs: forecastOptions.baselineMs,
|
|
166
|
+
lookaheadMs: forecastOptions.lookaheadMs,
|
|
167
|
+
baselineTotal,
|
|
168
|
+
baselineBad,
|
|
169
|
+
baselineFailureRate,
|
|
170
|
+
retainedTotal,
|
|
171
|
+
retainedBad,
|
|
172
|
+
projectedTotal,
|
|
173
|
+
projectedBad,
|
|
174
|
+
projectedSli,
|
|
175
|
+
timeToExhaustionMs,
|
|
176
|
+
alerting,
|
|
177
|
+
reason: alerting ? "projected-budget-exhaustion" : "within-budget"
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
reset() {
|
|
181
|
+
observations.length = 0;
|
|
182
|
+
firstLiveIndex = 0;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Evaluate a dual-window burn-rate alert.
|
|
188
|
+
*
|
|
189
|
+
* Both windows must exceed their threshold. The short window catches a sharp
|
|
190
|
+
* regression while the long window rejects brief spikes.
|
|
191
|
+
*/
|
|
192
|
+
function evaluateBurnRateAlert(options) {
|
|
193
|
+
validateThreshold("shortThreshold", options.shortThreshold);
|
|
194
|
+
validateThreshold("longThreshold", options.longThreshold);
|
|
195
|
+
if (options.shortWindow.name !== options.longWindow.name || options.shortWindow.target !== options.longWindow.target) throw new Error("Burn-rate windows must describe the same SLO name and target");
|
|
196
|
+
if (options.shortWindow.total === 0 || options.longWindow.total === 0) return {
|
|
197
|
+
alerting: false,
|
|
198
|
+
reason: "no-traffic",
|
|
199
|
+
shortBurnRate: options.shortWindow.burnRate,
|
|
200
|
+
longBurnRate: options.longWindow.burnRate
|
|
201
|
+
};
|
|
202
|
+
if (options.shortWindow.burnRate < options.shortThreshold) return {
|
|
203
|
+
alerting: false,
|
|
204
|
+
reason: "short-window-below-threshold",
|
|
205
|
+
shortBurnRate: options.shortWindow.burnRate,
|
|
206
|
+
longBurnRate: options.longWindow.burnRate
|
|
207
|
+
};
|
|
208
|
+
if (options.longWindow.burnRate < options.longThreshold) return {
|
|
209
|
+
alerting: false,
|
|
210
|
+
reason: "long-window-below-threshold",
|
|
211
|
+
shortBurnRate: options.shortWindow.burnRate,
|
|
212
|
+
longBurnRate: options.longWindow.burnRate
|
|
213
|
+
};
|
|
214
|
+
return {
|
|
215
|
+
alerting: true,
|
|
216
|
+
reason: "burn-rate-thresholds-exceeded",
|
|
217
|
+
shortBurnRate: options.shortWindow.burnRate,
|
|
218
|
+
longBurnRate: options.longWindow.burnRate
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
//#endregion
|
|
223
|
+
exports.createSloTracker = createSloTracker;
|
|
224
|
+
exports.evaluateBurnRateAlert = evaluateBurnRateAlert;
|
|
225
|
+
//# sourceMappingURL=slo.cjs.map
|
package/dist/slo.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slo.cjs","names":["getConfig","otelTrace"],"sources":["../src/slo.ts"],"sourcesContent":["/**\n * Service level objective tracking and burn-rate evaluation.\n *\n * The tracker keeps a bounded rolling window in memory, records low-cardinality\n * OpenTelemetry metrics, and returns snapshots that callers can feed into alert\n * evaluation. Production systems can persist the emitted metrics in their\n * telemetry backend while tests use the same calculations in process.\n */\n\nimport {\n trace as otelTrace,\n type Attributes,\n type Counter,\n type Histogram,\n} from '@opentelemetry/api';\nimport { getConfig } from './config';\n\nexport type SloOutcome = 'good' | 'bad';\n\nexport interface SloDefinition {\n /** Stable identifier used in metric attributes and alerts. */\n name: string;\n /** Required success ratio, expressed as a value between 0 and 1. */\n target: number;\n /** Rolling observation window in milliseconds. */\n windowMs: number;\n}\n\nexport interface SloTrackerOptions {\n /** Clock override for deterministic tests. */\n now?: () => number;\n /** Disable metric recording when calculations run outside an initialized SDK. */\n recordMetrics?: boolean;\n}\n\nexport interface SloSnapshot extends SloDefinition {\n observedAt: number;\n total: number;\n good: number;\n bad: number;\n /** Observed good-event ratio. Undefined until the tracker sees an event. */\n sli?: number;\n /** Fraction of events the objective permits to fail. */\n errorBudgetFraction: number;\n /** Fraction of the available error budget consumed in this window. */\n budgetConsumed: number;\n /** Remaining budget fraction. Negative values show overspend. */\n budgetRemaining: number;\n /** Observed failure ratio divided by the permitted failure ratio. */\n burnRate: number;\n meetsTarget: boolean;\n}\n\nexport interface SloTracker {\n readonly definition: Readonly<SloDefinition>;\n record(outcome: SloOutcome, attributes?: Attributes): SloSnapshot;\n snapshot(at?: number): SloSnapshot;\n forecast(options: SloForecastOptions): SloForecast;\n reset(): void;\n}\n\nexport interface SloForecastOptions {\n /** Recent observation period used to estimate the future failure rate. */\n baselineMs: number;\n /** Future period covered by the forecast. Must not exceed 4x the baseline. */\n lookaheadMs: number;\n /**\n * Expected eligible events during the lookahead. Defaults to the event rate\n * observed during the baseline.\n */\n expectedEventsInLookahead?: number;\n}\n\nexport interface SloForecast {\n name: string;\n target: number;\n observedAt: number;\n baselineMs: number;\n lookaheadMs: number;\n baselineTotal: number;\n baselineBad: number;\n baselineFailureRate: number;\n retainedTotal: number;\n retainedBad: number;\n projectedTotal: number;\n projectedBad: number;\n projectedSli?: number;\n /** Milliseconds until the retained and projected error budget is exhausted. */\n timeToExhaustionMs?: number;\n alerting: boolean;\n reason:\n 'no-baseline-traffic' | 'within-budget' | 'projected-budget-exhaustion';\n}\n\nexport interface BurnRateAlertOptions {\n shortWindow: SloSnapshot;\n longWindow: SloSnapshot;\n shortThreshold: number;\n longThreshold: number;\n}\n\nexport interface BurnRateAlertDecision {\n alerting: boolean;\n reason:\n | 'burn-rate-thresholds-exceeded'\n | 'short-window-below-threshold'\n | 'long-window-below-threshold'\n | 'no-traffic';\n shortBurnRate: number;\n longBurnRate: number;\n}\n\ninterface Observation {\n outcome: SloOutcome;\n timestamp: number;\n}\n\nfunction validateDefinition(definition: SloDefinition): void {\n if (!definition.name.trim()) {\n throw new Error('SLO name must not be empty');\n }\n if (\n !Number.isFinite(definition.target) ||\n definition.target <= 0 ||\n definition.target >= 1\n ) {\n throw new Error('SLO target must be greater than 0 and less than 1');\n }\n if (!Number.isFinite(definition.windowMs) || definition.windowMs <= 0) {\n throw new Error('SLO windowMs must be greater than 0');\n }\n}\n\nfunction validateThreshold(name: string, threshold: number): void {\n if (!Number.isFinite(threshold) || threshold <= 0) {\n throw new Error(`${name} must be greater than 0`);\n }\n}\n\nfunction validateForecastOptions(options: SloForecastOptions): void {\n if (!Number.isFinite(options.baselineMs) || options.baselineMs <= 0) {\n throw new Error('baselineMs must be greater than 0');\n }\n if (!Number.isFinite(options.lookaheadMs) || options.lookaheadMs <= 0) {\n throw new Error('lookaheadMs must be greater than 0');\n }\n if (options.lookaheadMs > options.baselineMs * 4) {\n throw new Error('lookaheadMs must not exceed 4 times baselineMs');\n }\n if (\n options.expectedEventsInLookahead !== undefined &&\n (!Number.isFinite(options.expectedEventsInLookahead) ||\n options.expectedEventsInLookahead < 0)\n ) {\n throw new Error('expectedEventsInLookahead must not be negative');\n }\n}\n\n/**\n * Track good and bad events for one rolling-window service level objective.\n */\nexport function createSloTracker(\n definition: SloDefinition,\n options: SloTrackerOptions = {},\n): SloTracker {\n validateDefinition(definition);\n\n const stableDefinition = Object.freeze({ ...definition });\n const now = options.now ?? Date.now;\n const observations: Observation[] = [];\n let firstLiveIndex = 0;\n\n let outcomeCounter: Counter | undefined;\n let burnRateHistogram: Histogram | undefined;\n\n if (options.recordMetrics !== false) {\n const meter = getConfig().meter;\n outcomeCounter = meter.createCounter('autotel.slo.outcomes', {\n description:\n 'Good and bad events recorded against a service level objective',\n unit: '1',\n });\n burnRateHistogram = meter.createHistogram('autotel.slo.burn_rate', {\n description: 'Error-budget burn rate for a service level objective',\n unit: '1',\n });\n }\n\n const prune = (at: number): void => {\n const cutoff = at - stableDefinition.windowMs;\n while (\n firstLiveIndex < observations.length &&\n observations[firstLiveIndex]!.timestamp < cutoff\n ) {\n firstLiveIndex += 1;\n }\n\n if (firstLiveIndex > 1024 && firstLiveIndex * 2 >= observations.length) {\n observations.splice(0, firstLiveIndex);\n firstLiveIndex = 0;\n }\n };\n\n const calculate = (at: number): SloSnapshot => {\n prune(at);\n\n let good = 0;\n for (let index = firstLiveIndex; index < observations.length; index += 1) {\n if (observations[index]!.outcome === 'good') good += 1;\n }\n\n const total = observations.length - firstLiveIndex;\n const bad = total - good;\n const sli = total === 0 ? undefined : good / total;\n const errorBudgetFraction = 1 - stableDefinition.target;\n const observedBadFraction = total === 0 ? 0 : bad / total;\n const burnRate = observedBadFraction / errorBudgetFraction;\n const budgetConsumed = burnRate;\n\n return {\n ...stableDefinition,\n observedAt: at,\n total,\n good,\n bad,\n sli,\n errorBudgetFraction,\n budgetConsumed,\n budgetRemaining: 1 - budgetConsumed,\n burnRate,\n meetsTarget: sli === undefined || sli >= stableDefinition.target,\n };\n };\n\n return {\n definition: stableDefinition,\n\n record(outcome: SloOutcome, attributes: Attributes = {}): SloSnapshot {\n if (outcome !== 'good' && outcome !== 'bad') {\n throw new Error('SLO outcome must be \"good\" or \"bad\"');\n }\n\n const timestamp = now();\n observations.push({ outcome, timestamp });\n const current = calculate(timestamp);\n const metricAttributes: Attributes = {\n ...attributes,\n 'slo.name': stableDefinition.name,\n 'slo.outcome': outcome,\n };\n\n outcomeCounter?.add(1, metricAttributes);\n burnRateHistogram?.record(current.burnRate, {\n 'slo.name': stableDefinition.name,\n });\n\n const activeSpan = otelTrace.getActiveSpan();\n activeSpan?.setAttributes({\n 'slo.name': stableDefinition.name,\n 'slo.target': stableDefinition.target,\n 'slo.outcome': outcome,\n 'slo.burn_rate': current.burnRate,\n });\n\n return current;\n },\n\n snapshot(at = now()): SloSnapshot {\n return calculate(at);\n },\n\n forecast(forecastOptions: SloForecastOptions): SloForecast {\n validateForecastOptions(forecastOptions);\n if (forecastOptions.baselineMs > stableDefinition.windowMs) {\n throw new Error('baselineMs must not exceed the SLO windowMs');\n }\n const observedAt = now();\n prune(observedAt);\n\n const baselineCutoff = observedAt - forecastOptions.baselineMs;\n const retainedCutoff =\n observedAt + forecastOptions.lookaheadMs - stableDefinition.windowMs;\n let baselineTotal = 0;\n let baselineBad = 0;\n let retainedTotal = 0;\n let retainedBad = 0;\n\n for (\n let index = firstLiveIndex;\n index < observations.length;\n index += 1\n ) {\n const observation = observations[index]!;\n if (observation.timestamp >= baselineCutoff) {\n baselineTotal += 1;\n if (observation.outcome === 'bad') baselineBad += 1;\n }\n if (observation.timestamp >= retainedCutoff) {\n retainedTotal += 1;\n if (observation.outcome === 'bad') retainedBad += 1;\n }\n }\n\n if (baselineTotal === 0) {\n return {\n name: stableDefinition.name,\n target: stableDefinition.target,\n observedAt,\n baselineMs: forecastOptions.baselineMs,\n lookaheadMs: forecastOptions.lookaheadMs,\n baselineTotal: 0,\n baselineBad: 0,\n baselineFailureRate: 0,\n retainedTotal,\n retainedBad,\n projectedTotal: retainedTotal,\n projectedBad: retainedBad,\n projectedSli:\n retainedTotal === 0\n ? undefined\n : (retainedTotal - retainedBad) / retainedTotal,\n alerting: false,\n reason: 'no-baseline-traffic',\n };\n }\n\n const baselineFailureRate = baselineBad / baselineTotal;\n const expectedEventsInLookahead =\n forecastOptions.expectedEventsInLookahead ??\n (baselineTotal * forecastOptions.lookaheadMs) /\n forecastOptions.baselineMs;\n const projectedFailures = baselineFailureRate * expectedEventsInLookahead;\n const projectedTotal = retainedTotal + expectedEventsInLookahead;\n const projectedBad = retainedBad + projectedFailures;\n const projectedSli =\n projectedTotal === 0\n ? undefined\n : (projectedTotal - projectedBad) / projectedTotal;\n const allowedFailureRate = 1 - stableDefinition.target;\n const remainingFailures =\n allowedFailureRate * retainedTotal - retainedBad;\n const netFailureRate = baselineFailureRate - allowedFailureRate;\n const eventRate = expectedEventsInLookahead / forecastOptions.lookaheadMs;\n const timeToExhaustionMs =\n remainingFailures <= 0\n ? 0\n : netFailureRate > 0 && eventRate > 0\n ? remainingFailures / (netFailureRate * eventRate)\n : undefined;\n const alerting =\n projectedSli !== undefined && projectedSli < stableDefinition.target;\n\n return {\n name: stableDefinition.name,\n target: stableDefinition.target,\n observedAt,\n baselineMs: forecastOptions.baselineMs,\n lookaheadMs: forecastOptions.lookaheadMs,\n baselineTotal,\n baselineBad,\n baselineFailureRate,\n retainedTotal,\n retainedBad,\n projectedTotal,\n projectedBad,\n projectedSli,\n timeToExhaustionMs,\n alerting,\n reason: alerting ? 'projected-budget-exhaustion' : 'within-budget',\n };\n },\n\n reset(): void {\n observations.length = 0;\n firstLiveIndex = 0;\n },\n };\n}\n\n/**\n * Evaluate a dual-window burn-rate alert.\n *\n * Both windows must exceed their threshold. The short window catches a sharp\n * regression while the long window rejects brief spikes.\n */\nexport function evaluateBurnRateAlert(\n options: BurnRateAlertOptions,\n): BurnRateAlertDecision {\n validateThreshold('shortThreshold', options.shortThreshold);\n validateThreshold('longThreshold', options.longThreshold);\n\n if (\n options.shortWindow.name !== options.longWindow.name ||\n options.shortWindow.target !== options.longWindow.target\n ) {\n throw new Error(\n 'Burn-rate windows must describe the same SLO name and target',\n );\n }\n\n if (options.shortWindow.total === 0 || options.longWindow.total === 0) {\n return {\n alerting: false,\n reason: 'no-traffic',\n shortBurnRate: options.shortWindow.burnRate,\n longBurnRate: options.longWindow.burnRate,\n };\n }\n\n if (options.shortWindow.burnRate < options.shortThreshold) {\n return {\n alerting: false,\n reason: 'short-window-below-threshold',\n shortBurnRate: options.shortWindow.burnRate,\n longBurnRate: options.longWindow.burnRate,\n };\n }\n\n if (options.longWindow.burnRate < options.longThreshold) {\n return {\n alerting: false,\n reason: 'long-window-below-threshold',\n shortBurnRate: options.shortWindow.burnRate,\n longBurnRate: options.longWindow.burnRate,\n };\n }\n\n return {\n alerting: true,\n reason: 'burn-rate-thresholds-exceeded',\n shortBurnRate: options.shortWindow.burnRate,\n longBurnRate: options.longWindow.burnRate,\n };\n}\n"],"mappings":"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"}
|
package/dist/slo.d.cts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Attributes } from "@opentelemetry/api";
|
|
2
|
+
//#region src/slo.d.ts
|
|
3
|
+
type SloOutcome = 'good' | 'bad';
|
|
4
|
+
interface SloDefinition {
|
|
5
|
+
/** Stable identifier used in metric attributes and alerts. */
|
|
6
|
+
name: string;
|
|
7
|
+
/** Required success ratio, expressed as a value between 0 and 1. */
|
|
8
|
+
target: number;
|
|
9
|
+
/** Rolling observation window in milliseconds. */
|
|
10
|
+
windowMs: number;
|
|
11
|
+
}
|
|
12
|
+
interface SloTrackerOptions {
|
|
13
|
+
/** Clock override for deterministic tests. */
|
|
14
|
+
now?: () => number;
|
|
15
|
+
/** Disable metric recording when calculations run outside an initialized SDK. */
|
|
16
|
+
recordMetrics?: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface SloSnapshot extends SloDefinition {
|
|
19
|
+
observedAt: number;
|
|
20
|
+
total: number;
|
|
21
|
+
good: number;
|
|
22
|
+
bad: number;
|
|
23
|
+
/** Observed good-event ratio. Undefined until the tracker sees an event. */
|
|
24
|
+
sli?: number;
|
|
25
|
+
/** Fraction of events the objective permits to fail. */
|
|
26
|
+
errorBudgetFraction: number;
|
|
27
|
+
/** Fraction of the available error budget consumed in this window. */
|
|
28
|
+
budgetConsumed: number;
|
|
29
|
+
/** Remaining budget fraction. Negative values show overspend. */
|
|
30
|
+
budgetRemaining: number;
|
|
31
|
+
/** Observed failure ratio divided by the permitted failure ratio. */
|
|
32
|
+
burnRate: number;
|
|
33
|
+
meetsTarget: boolean;
|
|
34
|
+
}
|
|
35
|
+
interface SloTracker {
|
|
36
|
+
readonly definition: Readonly<SloDefinition>;
|
|
37
|
+
record(outcome: SloOutcome, attributes?: Attributes): SloSnapshot;
|
|
38
|
+
snapshot(at?: number): SloSnapshot;
|
|
39
|
+
forecast(options: SloForecastOptions): SloForecast;
|
|
40
|
+
reset(): void;
|
|
41
|
+
}
|
|
42
|
+
interface SloForecastOptions {
|
|
43
|
+
/** Recent observation period used to estimate the future failure rate. */
|
|
44
|
+
baselineMs: number;
|
|
45
|
+
/** Future period covered by the forecast. Must not exceed 4x the baseline. */
|
|
46
|
+
lookaheadMs: number;
|
|
47
|
+
/**
|
|
48
|
+
* Expected eligible events during the lookahead. Defaults to the event rate
|
|
49
|
+
* observed during the baseline.
|
|
50
|
+
*/
|
|
51
|
+
expectedEventsInLookahead?: number;
|
|
52
|
+
}
|
|
53
|
+
interface SloForecast {
|
|
54
|
+
name: string;
|
|
55
|
+
target: number;
|
|
56
|
+
observedAt: number;
|
|
57
|
+
baselineMs: number;
|
|
58
|
+
lookaheadMs: number;
|
|
59
|
+
baselineTotal: number;
|
|
60
|
+
baselineBad: number;
|
|
61
|
+
baselineFailureRate: number;
|
|
62
|
+
retainedTotal: number;
|
|
63
|
+
retainedBad: number;
|
|
64
|
+
projectedTotal: number;
|
|
65
|
+
projectedBad: number;
|
|
66
|
+
projectedSli?: number;
|
|
67
|
+
/** Milliseconds until the retained and projected error budget is exhausted. */
|
|
68
|
+
timeToExhaustionMs?: number;
|
|
69
|
+
alerting: boolean;
|
|
70
|
+
reason: 'no-baseline-traffic' | 'within-budget' | 'projected-budget-exhaustion';
|
|
71
|
+
}
|
|
72
|
+
interface BurnRateAlertOptions {
|
|
73
|
+
shortWindow: SloSnapshot;
|
|
74
|
+
longWindow: SloSnapshot;
|
|
75
|
+
shortThreshold: number;
|
|
76
|
+
longThreshold: number;
|
|
77
|
+
}
|
|
78
|
+
interface BurnRateAlertDecision {
|
|
79
|
+
alerting: boolean;
|
|
80
|
+
reason: 'burn-rate-thresholds-exceeded' | 'short-window-below-threshold' | 'long-window-below-threshold' | 'no-traffic';
|
|
81
|
+
shortBurnRate: number;
|
|
82
|
+
longBurnRate: number;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Track good and bad events for one rolling-window service level objective.
|
|
86
|
+
*/
|
|
87
|
+
declare function createSloTracker(definition: SloDefinition, options?: SloTrackerOptions): SloTracker;
|
|
88
|
+
/**
|
|
89
|
+
* Evaluate a dual-window burn-rate alert.
|
|
90
|
+
*
|
|
91
|
+
* Both windows must exceed their threshold. The short window catches a sharp
|
|
92
|
+
* regression while the long window rejects brief spikes.
|
|
93
|
+
*/
|
|
94
|
+
declare function evaluateBurnRateAlert(options: BurnRateAlertOptions): BurnRateAlertDecision;
|
|
95
|
+
//#endregion
|
|
96
|
+
export { BurnRateAlertDecision, BurnRateAlertOptions, SloDefinition, SloForecast, SloForecastOptions, SloOutcome, SloSnapshot, SloTracker, SloTrackerOptions, createSloTracker, evaluateBurnRateAlert };
|
|
97
|
+
//# sourceMappingURL=slo.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slo.d.cts","names":[],"sources":["../src/slo.ts"],"mappings":";;KAiBY;UAEK;;EAEf;;EAEA;;EAEA;;UAGe;;EAEf;;EAEA;;UAGe,oBAAoB;EACnC;EACA;EACA;EACA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;EACA;;UAGe;WACN,YAAY,SAAS;EAC9B,OAAO,SAAS,YAAY,aAAa,aAAa;EACtD,SAAS,cAAc;EACvB,SAAS,SAAS,qBAAqB;EACvC;;UAGe;;EAEf;;EAEA;;;;;EAKA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAEA;EACA;EACA;;UAIe;EACf,aAAa;EACb,YAAY;EACZ;EACA;;UAGe;EACf;EACA;EAKA;EACA;;;;;iBAoDc,iBACd,YAAY,eACZ,UAAS,oBACR;;;;;;;iBA6Na,sBACd,SAAS,uBACR"}
|
package/dist/slo.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Attributes } from "@opentelemetry/api";
|
|
2
|
+
//#region src/slo.d.ts
|
|
3
|
+
type SloOutcome = 'good' | 'bad';
|
|
4
|
+
interface SloDefinition {
|
|
5
|
+
/** Stable identifier used in metric attributes and alerts. */
|
|
6
|
+
name: string;
|
|
7
|
+
/** Required success ratio, expressed as a value between 0 and 1. */
|
|
8
|
+
target: number;
|
|
9
|
+
/** Rolling observation window in milliseconds. */
|
|
10
|
+
windowMs: number;
|
|
11
|
+
}
|
|
12
|
+
interface SloTrackerOptions {
|
|
13
|
+
/** Clock override for deterministic tests. */
|
|
14
|
+
now?: () => number;
|
|
15
|
+
/** Disable metric recording when calculations run outside an initialized SDK. */
|
|
16
|
+
recordMetrics?: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface SloSnapshot extends SloDefinition {
|
|
19
|
+
observedAt: number;
|
|
20
|
+
total: number;
|
|
21
|
+
good: number;
|
|
22
|
+
bad: number;
|
|
23
|
+
/** Observed good-event ratio. Undefined until the tracker sees an event. */
|
|
24
|
+
sli?: number;
|
|
25
|
+
/** Fraction of events the objective permits to fail. */
|
|
26
|
+
errorBudgetFraction: number;
|
|
27
|
+
/** Fraction of the available error budget consumed in this window. */
|
|
28
|
+
budgetConsumed: number;
|
|
29
|
+
/** Remaining budget fraction. Negative values show overspend. */
|
|
30
|
+
budgetRemaining: number;
|
|
31
|
+
/** Observed failure ratio divided by the permitted failure ratio. */
|
|
32
|
+
burnRate: number;
|
|
33
|
+
meetsTarget: boolean;
|
|
34
|
+
}
|
|
35
|
+
interface SloTracker {
|
|
36
|
+
readonly definition: Readonly<SloDefinition>;
|
|
37
|
+
record(outcome: SloOutcome, attributes?: Attributes): SloSnapshot;
|
|
38
|
+
snapshot(at?: number): SloSnapshot;
|
|
39
|
+
forecast(options: SloForecastOptions): SloForecast;
|
|
40
|
+
reset(): void;
|
|
41
|
+
}
|
|
42
|
+
interface SloForecastOptions {
|
|
43
|
+
/** Recent observation period used to estimate the future failure rate. */
|
|
44
|
+
baselineMs: number;
|
|
45
|
+
/** Future period covered by the forecast. Must not exceed 4x the baseline. */
|
|
46
|
+
lookaheadMs: number;
|
|
47
|
+
/**
|
|
48
|
+
* Expected eligible events during the lookahead. Defaults to the event rate
|
|
49
|
+
* observed during the baseline.
|
|
50
|
+
*/
|
|
51
|
+
expectedEventsInLookahead?: number;
|
|
52
|
+
}
|
|
53
|
+
interface SloForecast {
|
|
54
|
+
name: string;
|
|
55
|
+
target: number;
|
|
56
|
+
observedAt: number;
|
|
57
|
+
baselineMs: number;
|
|
58
|
+
lookaheadMs: number;
|
|
59
|
+
baselineTotal: number;
|
|
60
|
+
baselineBad: number;
|
|
61
|
+
baselineFailureRate: number;
|
|
62
|
+
retainedTotal: number;
|
|
63
|
+
retainedBad: number;
|
|
64
|
+
projectedTotal: number;
|
|
65
|
+
projectedBad: number;
|
|
66
|
+
projectedSli?: number;
|
|
67
|
+
/** Milliseconds until the retained and projected error budget is exhausted. */
|
|
68
|
+
timeToExhaustionMs?: number;
|
|
69
|
+
alerting: boolean;
|
|
70
|
+
reason: 'no-baseline-traffic' | 'within-budget' | 'projected-budget-exhaustion';
|
|
71
|
+
}
|
|
72
|
+
interface BurnRateAlertOptions {
|
|
73
|
+
shortWindow: SloSnapshot;
|
|
74
|
+
longWindow: SloSnapshot;
|
|
75
|
+
shortThreshold: number;
|
|
76
|
+
longThreshold: number;
|
|
77
|
+
}
|
|
78
|
+
interface BurnRateAlertDecision {
|
|
79
|
+
alerting: boolean;
|
|
80
|
+
reason: 'burn-rate-thresholds-exceeded' | 'short-window-below-threshold' | 'long-window-below-threshold' | 'no-traffic';
|
|
81
|
+
shortBurnRate: number;
|
|
82
|
+
longBurnRate: number;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Track good and bad events for one rolling-window service level objective.
|
|
86
|
+
*/
|
|
87
|
+
declare function createSloTracker(definition: SloDefinition, options?: SloTrackerOptions): SloTracker;
|
|
88
|
+
/**
|
|
89
|
+
* Evaluate a dual-window burn-rate alert.
|
|
90
|
+
*
|
|
91
|
+
* Both windows must exceed their threshold. The short window catches a sharp
|
|
92
|
+
* regression while the long window rejects brief spikes.
|
|
93
|
+
*/
|
|
94
|
+
declare function evaluateBurnRateAlert(options: BurnRateAlertOptions): BurnRateAlertDecision;
|
|
95
|
+
//#endregion
|
|
96
|
+
export { BurnRateAlertDecision, BurnRateAlertOptions, SloDefinition, SloForecast, SloForecastOptions, SloOutcome, SloSnapshot, SloTracker, SloTrackerOptions, createSloTracker, evaluateBurnRateAlert };
|
|
97
|
+
//# sourceMappingURL=slo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slo.d.ts","names":[],"sources":["../src/slo.ts"],"mappings":";;KAiBY;UAEK;;EAEf;;EAEA;;EAEA;;UAGe;;EAEf;;EAEA;;UAGe,oBAAoB;EACnC;EACA;EACA;EACA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;EACA;;UAGe;WACN,YAAY,SAAS;EAC9B,OAAO,SAAS,YAAY,aAAa,aAAa;EACtD,SAAS,cAAc;EACvB,SAAS,SAAS,qBAAqB;EACvC;;UAGe;;EAEf;;EAEA;;;;;EAKA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAEA;EACA;EACA;;UAIe;EACf,aAAa;EACb,YAAY;EACZ;EACA;;UAGe;EACf;EACA;EAKA;EACA;;;;;iBAoDc,iBACd,YAAY,eACZ,UAAS,oBACR;;;;;;;iBA6Na,sBACd,SAAS,uBACR"}
|