@equipe-tech/observability 0.2.0 → 0.3.5
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 +11 -9
- package/dist/BrowserEvents.d.ts +89 -12
- package/dist/BrowserEvents.js +67 -13
- package/dist/Correlation.d.ts +51 -0
- package/dist/Correlation.js +95 -0
- package/dist/Metrics.d.ts +19 -3
- package/dist/Metrics.js +16 -0
- package/dist/MetricsRuntime.d.ts +45 -3
- package/dist/MetricsRuntime.js +478 -120
- package/dist/PolicyOtlpLogger.d.ts +18 -0
- package/dist/PolicyOtlpLogger.js +142 -0
- package/dist/RedactionPolicy.d.ts +2 -9
- package/dist/RedactionPolicy.js +2 -246
- package/dist/ResourceIdentity.d.ts +47 -0
- package/dist/ResourceIdentity.js +82 -0
- package/dist/Telemetry.d.ts +18 -3
- package/dist/Telemetry.js +43 -25
- package/dist/TelemetryConfig.d.ts +11 -4
- package/dist/TelemetryConfig.js +38 -10
- package/dist/audit/AuditCommitDocument.d.ts +41 -0
- package/dist/audit/AuditCommitDocument.js +58 -0
- package/dist/audit/AuditDigest.d.ts +11 -0
- package/dist/audit/AuditDigest.js +25 -0
- package/dist/audit/AuditOutbox.d.ts +75 -0
- package/dist/audit/AuditOutbox.js +104 -0
- package/dist/audit/AuditPublisher.d.ts +49 -0
- package/dist/audit/AuditPublisher.js +60 -0
- package/dist/audit/AuditRecord.d.ts +128 -0
- package/dist/audit/AuditRecord.js +172 -0
- package/dist/audit/CommittedAuditRecordInternal.d.ts +11 -0
- package/dist/audit/CommittedAuditRecordInternal.js +13 -0
- package/dist/audit/InvalidAuditRecord.d.ts +12 -0
- package/dist/audit/InvalidAuditRecord.js +16 -0
- package/dist/audit/index.d.ts +7 -0
- package/dist/audit/index.js +7 -0
- package/dist/browser/BrowserClient.d.ts +82 -3
- package/dist/browser/BrowserClient.js +322 -28
- package/dist/browser/BrowserEventLimits.d.ts +8 -0
- package/dist/browser/BrowserEventLimits.js +8 -0
- package/dist/browser/BrowserMetricRecorder.d.ts +17 -0
- package/dist/browser/BrowserMetricRecorder.js +35 -0
- package/dist/browser/BrowserTelemetry.d.ts +40 -0
- package/dist/browser/BrowserTelemetry.js +105 -0
- package/dist/browser/ClientPolicy.d.ts +3 -0
- package/dist/browser/ClientPolicy.js +52 -0
- package/dist/browser/client.d.ts +3 -2
- package/dist/browser/client.js +2 -1
- package/dist/browser/index.d.ts +4 -37
- package/dist/browser/index.js +3 -95
- package/dist/contract/ContractCompatibility.d.ts +31 -0
- package/dist/contract/ContractCompatibility.js +274 -0
- package/dist/contract/ContractIndex.d.ts +54 -0
- package/dist/contract/ContractIndex.js +178 -0
- package/dist/contract/ContractSurface.d.ts +111 -0
- package/dist/contract/ContractSurface.js +116 -0
- package/dist/contract/EventName.d.ts +6 -0
- package/dist/contract/EventName.js +55 -0
- package/dist/contract/EventProducer.d.ts +123 -0
- package/dist/contract/EventProducer.js +209 -0
- package/dist/contract/MetricContractError.d.ts +19 -0
- package/dist/contract/MetricContractError.js +19 -0
- package/dist/contract/MetricDefinition.d.ts +61 -0
- package/dist/contract/MetricDefinition.js +91 -0
- package/dist/contract/MetricProducer.d.ts +42 -0
- package/dist/contract/MetricProducer.js +123 -0
- package/dist/contract/OrganizationEvents.d.ts +165 -0
- package/dist/contract/OrganizationEvents.js +97 -0
- package/dist/contract/TelemetryContract.d.ts +95 -0
- package/dist/contract/TelemetryContract.js +451 -0
- package/dist/contract/TelemetryContractError.d.ts +44 -0
- package/dist/contract/TelemetryContractError.js +64 -0
- package/dist/contract/TelemetryEvent.d.ts +59 -0
- package/dist/contract/TelemetryEvent.js +54 -0
- package/dist/contract/index.d.ts +11 -0
- package/dist/contract/index.js +11 -0
- package/dist/effect/WideEvent.d.ts +3 -0
- package/dist/effect/WideEvent.js +20 -0
- package/dist/effect/WideEventSink.d.ts +3 -0
- package/dist/effect/WideEventSink.js +79 -0
- package/dist/effect/index.d.ts +2 -0
- package/dist/effect/index.js +2 -0
- package/dist/index.d.ts +17 -2
- package/dist/index.js +11 -2
- package/dist/metrics/InstrumentGrammar.d.ts +5 -0
- package/dist/metrics/InstrumentGrammar.js +12 -0
- package/dist/metrics/MetricScalar.d.ts +3 -0
- package/dist/metrics/MetricScalar.js +5 -0
- package/dist/node/AuditDigest.d.ts +3 -0
- package/dist/node/AuditDigest.js +6 -0
- package/dist/node/BrowserEventIngest.d.ts +7 -2
- package/dist/node/BrowserEventIngest.js +111 -19
- package/dist/node/LocalCollector.d.ts +20 -0
- package/dist/node/LocalCollector.js +188 -0
- package/dist/node/Observability.d.ts +49 -0
- package/dist/node/Observability.js +190 -0
- package/dist/node/Runtime.d.ts +4 -1
- package/dist/node/index.d.ts +4 -0
- package/dist/node/index.js +3 -0
- package/dist/policy/BrowserFieldPolicy.d.ts +7 -0
- package/dist/policy/BrowserFieldPolicy.js +298 -0
- package/dist/policy/DataPolicy.d.ts +19 -0
- package/dist/policy/DataPolicy.js +254 -0
- package/dist/policy/DataPolicyError.d.ts +22 -0
- package/dist/policy/DataPolicyError.js +25 -0
- package/dist/policy/Deduplication.d.ts +13 -0
- package/dist/policy/Deduplication.js +44 -0
- package/dist/policy/DefectEnvelope.d.ts +25 -0
- package/dist/policy/DefectEnvelope.js +52 -0
- package/dist/policy/MetricLabelPolicy.d.ts +5 -0
- package/dist/policy/MetricLabelPolicy.js +65 -0
- package/dist/policy/PolicyTransform.d.ts +16 -0
- package/dist/policy/PolicyTransform.js +136 -0
- package/dist/policy/PolicyVocabulary.d.ts +10 -0
- package/dist/policy/PolicyVocabulary.js +84 -0
- package/dist/policy/ResourceAttributePolicy.d.ts +9 -0
- package/dist/policy/ResourceAttributePolicy.js +33 -0
- package/dist/policy/entrypoint.d.ts +2 -0
- package/dist/policy/entrypoint.js +2 -0
- package/dist/policy/index.d.ts +17 -0
- package/dist/policy/index.js +9 -0
- package/dist/profile/DataPolicy.d.ts +2 -0
- package/dist/profile/DataPolicy.js +1 -0
- package/dist/profile/EnvironmentPolicy.d.ts +22 -0
- package/dist/profile/EnvironmentPolicy.js +41 -0
- package/dist/profile/LifecycleRegistry.d.ts +24 -0
- package/dist/profile/LifecycleRegistry.js +240 -0
- package/dist/profile/ObservabilityAdapter.d.ts +115 -0
- package/dist/profile/ObservabilityAdapter.js +50 -0
- package/dist/profile/ObservabilityConfig.d.ts +68 -0
- package/dist/profile/ObservabilityConfig.js +125 -0
- package/dist/profile/ObservabilityConfigError.d.ts +23 -0
- package/dist/profile/ObservabilityConfigError.js +39 -0
- package/dist/profile/ObservabilityProfile.d.ts +49 -0
- package/dist/profile/ObservabilityProfile.js +121 -0
- package/dist/profile/ReactWebProfile.d.ts +8 -0
- package/dist/profile/ReactWebProfile.js +7 -0
- package/dist/profile/index.d.ts +5 -0
- package/dist/profile/index.js +5 -0
- package/dist/testing/conformance/ConformanceAssertions.d.ts +5 -0
- package/dist/testing/conformance/ConformanceAssertions.js +31 -0
- package/dist/testing/conformance/ConformanceFailure.d.ts +35 -0
- package/dist/testing/conformance/ConformanceFailure.js +56 -0
- package/dist/testing/conformance/ConformanceModel.d.ts +97 -0
- package/dist/testing/conformance/ConformanceModel.js +8 -0
- package/dist/testing/conformance/ConformanceRegistry.d.ts +13 -0
- package/dist/testing/conformance/ConformanceRegistry.js +190 -0
- package/dist/testing/conformance/ConformanceRunner.d.ts +5 -0
- package/dist/testing/conformance/ConformanceRunner.js +198 -0
- package/dist/testing/conformance/TelemetryEvidence.d.ts +91 -0
- package/dist/testing/conformance/TelemetryEvidence.js +370 -0
- package/dist/testing/conformance/index.d.ts +10 -0
- package/dist/testing/conformance/index.js +6 -0
- package/dist/testing/contract.d.ts +81 -0
- package/dist/testing/contract.js +93 -0
- package/dist/testing/deployedCanary.d.ts +1 -0
- package/dist/testing/deployedCanary.js +1 -0
- package/dist/testing/index.d.ts +40 -3
- package/dist/testing/index.js +122 -5
- package/dist/trace/HttpServerOtlpTracer.d.ts +42 -0
- package/dist/trace/HttpServerOtlpTracer.js +301 -0
- package/package.json +16 -29
- package/dist/WideEvent.d.ts +0 -5
- package/dist/WideEvent.js +0 -6
- package/dist/nestjs/BrowserEventsController.d.ts +0 -21
- package/dist/nestjs/BrowserEventsController.js +0 -52
- package/dist/nestjs/HttpRoutePolicy.d.ts +0 -23
- package/dist/nestjs/HttpRoutePolicy.js +0 -179
- package/dist/nestjs/HttpServerOtlpTracer.d.ts +0 -15
- package/dist/nestjs/HttpServerOtlpTracer.js +0 -154
- package/dist/nestjs/RequestWideEventTraceCorrelation.d.ts +0 -15
- package/dist/nestjs/RequestWideEventTraceCorrelation.js +0 -13
- package/dist/nestjs/TelemetryInterceptor.d.ts +0 -31
- package/dist/nestjs/TelemetryInterceptor.js +0 -268
- package/dist/nestjs/TelemetryModule.d.ts +0 -53
- package/dist/nestjs/TelemetryModule.js +0 -428
- package/dist/nestjs/index.d.ts +0 -5
- package/dist/nestjs/index.js +0 -4
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { conformanceChecks } from "./ConformanceRegistry.js";
|
|
2
|
+
export { ConformanceAssertionError, ConformanceFailure, InvalidConformanceSuite, conformanceFailureCodes, } from "./ConformanceFailure.js";
|
|
3
|
+
export { assertConformanceFailure, assertConforms } from "./ConformanceAssertions.js";
|
|
4
|
+
export { runConformance, runConformanceSuite } from "./ConformanceRunner.js";
|
|
5
|
+
export { ConformanceViolation, defineConformanceEvidenceProvider } from "./ConformanceModel.js";
|
|
6
|
+
export { applicationDeployedTelemetryDestinationReceipt, auditCanaryConformance, auditConformance, contractConformance, conformanceTargetBinding, correlationConformance, identityConformance, libraryLifecycleConformance, lifecycleConformance, policyConformance, producersConformance, profileConformance, telemetryCanaryConformance, telemetryDestinationMatches, telemetryDestinationTelemetry, } from "./TelemetryEvidence.js";
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Effect, Layer } from "effect";
|
|
2
|
+
import { TelemetryEventSink, type BrowserTelemetryEvent, type EventPayloadOf, type EventProducer, type TelemetryContract, type TelemetryContractInput } from "../contract/index.js";
|
|
3
|
+
import { ContractIssueCode } from "../contract/TelemetryContractError.js";
|
|
4
|
+
import type { TelemetryEvent } from "../contract/TelemetryEvent.js";
|
|
5
|
+
export type OrganizationEventFixture = {
|
|
6
|
+
readonly alias: string;
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly kind: string;
|
|
9
|
+
};
|
|
10
|
+
export declare const organizationEventFixtures: ReadonlyArray<OrganizationEventFixture>;
|
|
11
|
+
export declare const contractIssueFixtures: readonly ["OBS_CONTRACT_INVALID_DOCUMENT", "OBS_CONTRACT_INVALID_VERSION", "OBS_CONTRACT_INVALID_EVENT_NAME", "OBS_CONTRACT_DUPLICATE_EVENT_NAME", "OBS_CONTRACT_INVALID_EVENT_KIND", "OBS_CONTRACT_INVALID_DEFAULT_SEVERITY", "OBS_CONTRACT_INVALID_ATTRIBUTE_NAME", "OBS_CONTRACT_RESERVED_ATTRIBUTE_NAME", "OBS_CONTRACT_INVALID_ATTRIBUTE_DEFINITION", "OBS_CONTRACT_INVALID_SAMPLING_RATE", "OBS_CONTRACT_INVALID_AUDIT_ACTION", "OBS_CONTRACT_DUPLICATE_AUDIT_ACTION", "OBS_CONTRACT_INVALID_AUDIT_REASON_CODE", "OBS_CONTRACT_INVALID_METRIC_NAME", "OBS_CONTRACT_DUPLICATE_METRIC_NAME", "OBS_CONTRACT_INVALID_METRIC_KIND", "OBS_CONTRACT_INVALID_METRIC_UNIT", "OBS_CONTRACT_INVALID_METRIC_DESCRIPTION", "OBS_CONTRACT_INVALID_METRIC_BOUNDARIES", "OBS_CONTRACT_INVALID_METRIC_ATTRIBUTE_NAME", "OBS_CONTRACT_INVALID_METRIC_ATTRIBUTE_DEFINITION", "OBS_CONTRACT_INVALID_METRIC_ALLOWED_VALUES", "OBS_CONTRACT_INVALID_METRIC_CARDINALITY"];
|
|
12
|
+
export declare const telemetryEventErrorFixtures: readonly ["OBS_EVENT_UNKNOWN_NAME", "OBS_EVENT_UNDECLARED_ATTRIBUTE", "OBS_EVENT_MISSING_ATTRIBUTE", "OBS_EVENT_INVALID_FIELD", "OBS_EVENT_INVALID_OUTCOME", "OBS_EVENT_RESTRICTED_ATTRIBUTE", "OBS_EVENT_SENSITIVE_METRIC_LABEL", "OBS_EVENT_UNKNOWN_AUDIT_ACTION", "OBS_EVENT_INVALID_AUDIT_RESOURCE", "OBS_EVENT_INVALID_AUDIT_OUTCOME", "OBS_EVENT_INVALID_AUDIT_REASON"];
|
|
13
|
+
export declare const auditRecordErrorFixtures: readonly ["OBS_AUDIT_UNKNOWN_ACTION", "OBS_AUDIT_INVALID_ACTOR", "OBS_AUDIT_INVALID_RESOURCE", "OBS_AUDIT_INVALID_OUTCOME", "OBS_AUDIT_UNKNOWN_REASON_CODE", "OBS_AUDIT_INVALID_FIELD"];
|
|
14
|
+
export declare const metricDefinitionFixtures: {
|
|
15
|
+
Counter: {
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
unit: string;
|
|
19
|
+
kind: "counter";
|
|
20
|
+
attributes: {};
|
|
21
|
+
};
|
|
22
|
+
Histogram: {
|
|
23
|
+
name: string;
|
|
24
|
+
description: string;
|
|
25
|
+
unit: string;
|
|
26
|
+
kind: "histogram";
|
|
27
|
+
boundaries: number[];
|
|
28
|
+
attributes: {};
|
|
29
|
+
};
|
|
30
|
+
ObservableGauge: {
|
|
31
|
+
name: string;
|
|
32
|
+
description: string;
|
|
33
|
+
unit: string;
|
|
34
|
+
kind: "observable_gauge";
|
|
35
|
+
attributes: {};
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
type MetricDefinitionIssueCode = Extract<ContractIssueCode, `OBS_CONTRACT_${string}METRIC${string}`>;
|
|
39
|
+
export type InvalidMetricDefinitionFixture = {
|
|
40
|
+
readonly issue: MetricDefinitionIssueCode;
|
|
41
|
+
readonly metricsDocument: string;
|
|
42
|
+
};
|
|
43
|
+
export declare const invalidMetricDefinitionFixtures: ({
|
|
44
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_NAME";
|
|
45
|
+
metricsDocument: string;
|
|
46
|
+
} | {
|
|
47
|
+
issue: "OBS_CONTRACT_DUPLICATE_METRIC_NAME";
|
|
48
|
+
metricsDocument: string;
|
|
49
|
+
} | {
|
|
50
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_KIND";
|
|
51
|
+
metricsDocument: string;
|
|
52
|
+
} | {
|
|
53
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_DESCRIPTION";
|
|
54
|
+
metricsDocument: string;
|
|
55
|
+
} | {
|
|
56
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_UNIT";
|
|
57
|
+
metricsDocument: string;
|
|
58
|
+
} | {
|
|
59
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_BOUNDARIES";
|
|
60
|
+
metricsDocument: string;
|
|
61
|
+
} | {
|
|
62
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_ATTRIBUTE_NAME";
|
|
63
|
+
metricsDocument: string;
|
|
64
|
+
} | {
|
|
65
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_ATTRIBUTE_DEFINITION";
|
|
66
|
+
metricsDocument: string;
|
|
67
|
+
} | {
|
|
68
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_CARDINALITY";
|
|
69
|
+
metricsDocument: string;
|
|
70
|
+
} | {
|
|
71
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_ALLOWED_VALUES";
|
|
72
|
+
metricsDocument: string;
|
|
73
|
+
})[];
|
|
74
|
+
export type CollectingTelemetryEventSink = {
|
|
75
|
+
readonly layer: Layer.Layer<TelemetryEventSink>;
|
|
76
|
+
readonly events: Effect.Effect<ReadonlyArray<TelemetryEvent>>;
|
|
77
|
+
readonly browserEvents: Effect.Effect<ReadonlyArray<BrowserTelemetryEvent>>;
|
|
78
|
+
};
|
|
79
|
+
export declare const makeCollectingTelemetryEventSink: () => Effect.Effect<CollectingTelemetryEventSink, never, never>;
|
|
80
|
+
export declare const withFixedSampling: <A, E, R>(program: Effect.Effect<A, E, R>, draw: number) => Effect.Effect<A, E, R>;
|
|
81
|
+
export type { EventPayloadOf, EventProducer, TelemetryContract, TelemetryContractInput };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { Effect, Layer, Random, Ref } from "effect";
|
|
2
|
+
import { AuditRecordErrorCode } from "../audit/InvalidAuditRecord.js";
|
|
3
|
+
import { TelemetryEventSink, } from "../contract/index.js";
|
|
4
|
+
import { ContractIssueCode, TelemetryEventErrorCode } from "../contract/TelemetryContractError.js";
|
|
5
|
+
import { organizationEvents } from "../contract/OrganizationEvents.js";
|
|
6
|
+
export const organizationEventFixtures = Object.entries(organizationEvents).map(([alias, definition]) => ({ alias, name: definition.name, kind: definition.kind }));
|
|
7
|
+
export const contractIssueFixtures = ContractIssueCode.literals;
|
|
8
|
+
export const telemetryEventErrorFixtures = TelemetryEventErrorCode.literals;
|
|
9
|
+
export const auditRecordErrorFixtures = AuditRecordErrorCode.literals;
|
|
10
|
+
export const metricDefinitionFixtures = {
|
|
11
|
+
Counter: {
|
|
12
|
+
name: "fixture.counter",
|
|
13
|
+
description: "Counter fixture",
|
|
14
|
+
unit: "1",
|
|
15
|
+
kind: "counter",
|
|
16
|
+
attributes: {},
|
|
17
|
+
},
|
|
18
|
+
Histogram: {
|
|
19
|
+
name: "fixture.histogram",
|
|
20
|
+
description: "Histogram fixture",
|
|
21
|
+
unit: "ms",
|
|
22
|
+
kind: "histogram",
|
|
23
|
+
boundaries: [1, 10],
|
|
24
|
+
attributes: {},
|
|
25
|
+
},
|
|
26
|
+
ObservableGauge: {
|
|
27
|
+
name: "fixture.gauge",
|
|
28
|
+
description: "Observable gauge fixture",
|
|
29
|
+
unit: "1",
|
|
30
|
+
kind: "observable_gauge",
|
|
31
|
+
attributes: {},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
const exhaustiveMetricDefinitionFixtures = (fixtures) => fixtures;
|
|
35
|
+
export const invalidMetricDefinitionFixtures = exhaustiveMetricDefinitionFixtures([
|
|
36
|
+
{
|
|
37
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_NAME",
|
|
38
|
+
metricsDocument: `{"Metric":{"name":"invalid","description":"Fixture","unit":"1","kind":"counter","attributes":{}}}`,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
issue: "OBS_CONTRACT_DUPLICATE_METRIC_NAME",
|
|
42
|
+
metricsDocument: `{"First":{"name":"fixture.duplicate","description":"Fixture","unit":"1","kind":"counter","attributes":{}},"Second":{"name":"fixture.duplicate","description":"Fixture","unit":"1","kind":"counter","attributes":{}}}`,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_KIND",
|
|
46
|
+
metricsDocument: `{"Metric":{"name":"fixture.metric","description":"Fixture","unit":"1","kind":"summary","attributes":{}}}`,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_DESCRIPTION",
|
|
50
|
+
metricsDocument: `{"Metric":{"name":"fixture.metric","description":"","unit":"1","kind":"counter","attributes":{}}}`,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_UNIT",
|
|
54
|
+
metricsDocument: `{"Metric":{"name":"fixture.metric","description":"Fixture","unit":"bad unit","kind":"counter","attributes":{}}}`,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_BOUNDARIES",
|
|
58
|
+
metricsDocument: `{"Metric":{"name":"fixture.metric","description":"Fixture","unit":"ms","kind":"histogram","boundaries":[],"attributes":{}}}`,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_ATTRIBUTE_NAME",
|
|
62
|
+
metricsDocument: `{"Metric":{"name":"fixture.metric","description":"Fixture","unit":"1","kind":"counter","attributes":{"Invalid":{"classification":"public","maximumCardinality":1}}}}`,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_ATTRIBUTE_DEFINITION",
|
|
66
|
+
metricsDocument: `{"Metric":{"name":"fixture.metric","description":"Fixture","unit":"1","kind":"counter","attributes":{"fixture.label":{"classification":"sensitive","maximumCardinality":1}}}}`,
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_CARDINALITY",
|
|
70
|
+
metricsDocument: `{"Metric":{"name":"fixture.metric","description":"Fixture","unit":"1","kind":"counter","attributes":{"fixture.label":{"classification":"public","maximumCardinality":0}}}}`,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
issue: "OBS_CONTRACT_INVALID_METRIC_ALLOWED_VALUES",
|
|
74
|
+
metricsDocument: `{"Metric":{"name":"fixture.metric","description":"Fixture","unit":"1","kind":"counter","attributes":{"fixture.label":{"classification":"public","maximumCardinality":1,"allowedValues":[]}}}}`,
|
|
75
|
+
},
|
|
76
|
+
]);
|
|
77
|
+
export const makeCollectingTelemetryEventSink = Effect.fn("makeCollectingTelemetryEventSink")(function* () {
|
|
78
|
+
const store = yield* Ref.make([]);
|
|
79
|
+
const browserStore = yield* Ref.make([]);
|
|
80
|
+
const record = (event) => Ref.update(store, (events) => [...events, event]);
|
|
81
|
+
const admitBrowserBatch = (events) => Effect.succeed({
|
|
82
|
+
commit: Ref.update(browserStore, (captured) => [...captured, ...events]),
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
layer: Layer.succeed(TelemetryEventSink, TelemetryEventSink.of({ record, admitBrowserBatch })),
|
|
86
|
+
events: Ref.get(store),
|
|
87
|
+
browserEvents: Ref.get(browserStore),
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
export const withFixedSampling = (program, draw) => Effect.provideService(program, Random.Random, {
|
|
91
|
+
nextIntUnsafe: () => 0,
|
|
92
|
+
nextDoubleUnsafe: () => draw,
|
|
93
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const deployedCanarySuiteTimeoutMilliseconds = 480000;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const deployedCanarySuiteTimeoutMilliseconds = 480_000;
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
import { Effect, Layer, Option, type Exit } from "effect";
|
|
2
2
|
import { OtlpExporter } from "effect/unstable/observability";
|
|
3
3
|
import { TelemetryConfig } from "../TelemetryConfig.js";
|
|
4
|
+
import type { DataPolicy } from "../policy/DataPolicy.js";
|
|
5
|
+
import type { InvalidDataPolicy } from "../policy/DataPolicyError.js";
|
|
6
|
+
import type { ResourceAttribute } from "../policy/ResourceAttributePolicy.js";
|
|
7
|
+
import type { ContractRegistry } from "../profile/ObservabilityAdapter.js";
|
|
8
|
+
export * from "./contract.js";
|
|
9
|
+
export * from "./conformance/index.js";
|
|
10
|
+
export * from "./deployedCanary.js";
|
|
11
|
+
export * from "../node/LocalCollector.js";
|
|
12
|
+
export { registerTestingAdapter, type TestingAdapterRegistration, } from "../profile/ObservabilityAdapter.js";
|
|
13
|
+
export { createTestingNodeObservabilityFromConfig } from "../node/Observability.js";
|
|
4
14
|
export type CapturedAttributeValue = string | number | boolean;
|
|
5
15
|
export type CapturedAttributes = ReadonlyMap<string, CapturedAttributeValue>;
|
|
16
|
+
export type CapturedSpanEvent = {
|
|
17
|
+
readonly name: string;
|
|
18
|
+
readonly attributes: CapturedAttributes;
|
|
19
|
+
readonly droppedAttributesCount: number;
|
|
20
|
+
};
|
|
21
|
+
export type CapturedSpanLink = {
|
|
22
|
+
readonly spanId: string;
|
|
23
|
+
readonly attributes: CapturedAttributes;
|
|
24
|
+
readonly droppedAttributesCount: number;
|
|
25
|
+
};
|
|
6
26
|
export type CapturedSpan = {
|
|
7
27
|
readonly traceId: string;
|
|
8
28
|
readonly spanId: string;
|
|
@@ -12,6 +32,11 @@ export type CapturedSpan = {
|
|
|
12
32
|
readonly statusCode: number;
|
|
13
33
|
readonly statusMessage: Option.Option<string>;
|
|
14
34
|
readonly attributes: CapturedAttributes;
|
|
35
|
+
readonly droppedAttributesCount: number;
|
|
36
|
+
readonly events: ReadonlyArray<CapturedSpanEvent>;
|
|
37
|
+
readonly droppedEventsCount: number;
|
|
38
|
+
readonly links: ReadonlyArray<CapturedSpanLink>;
|
|
39
|
+
readonly droppedLinksCount: number;
|
|
15
40
|
readonly eventNames: ReadonlyArray<string>;
|
|
16
41
|
readonly linkedSpanIds: ReadonlyArray<string>;
|
|
17
42
|
readonly resourceAttributes: CapturedAttributes;
|
|
@@ -20,6 +45,7 @@ export type CapturedLog = {
|
|
|
20
45
|
readonly traceId: Option.Option<string>;
|
|
21
46
|
readonly spanId: Option.Option<string>;
|
|
22
47
|
readonly severityText: Option.Option<string>;
|
|
48
|
+
readonly droppedAttributesCount: number;
|
|
23
49
|
readonly body: Option.Option<string>;
|
|
24
50
|
readonly attributes: CapturedAttributes;
|
|
25
51
|
readonly resourceAttributes: CapturedAttributes;
|
|
@@ -74,13 +100,24 @@ export type CapturedRequest = {
|
|
|
74
100
|
readonly path: string;
|
|
75
101
|
readonly payload: unknown;
|
|
76
102
|
};
|
|
103
|
+
export declare const decodeCapturedTelemetry: (requests: readonly CapturedRequest[]) => Effect.Effect<CapturedTelemetry, never, never>;
|
|
77
104
|
export type RunOptions = {
|
|
78
105
|
readonly config?: TelemetryConfig;
|
|
106
|
+
readonly policy?: DataPolicy;
|
|
107
|
+
readonly resourceAttributes?: ReadonlyArray<ResourceAttribute>;
|
|
108
|
+
readonly contract?: ContractRegistry;
|
|
79
109
|
};
|
|
80
110
|
export type TelemetryCapture = {
|
|
81
|
-
readonly layer: Layer.Layer<OtlpExporter.Flusher>;
|
|
111
|
+
readonly layer: Layer.Layer<OtlpExporter.Flusher, InvalidDataPolicy>;
|
|
82
112
|
readonly telemetry: Effect.Effect<CapturedTelemetry>;
|
|
83
113
|
};
|
|
114
|
+
export type OtlpCaptureServer = {
|
|
115
|
+
readonly endpoint: URL;
|
|
116
|
+
readonly telemetry: () => CapturedTelemetry;
|
|
117
|
+
readonly stop: () => Promise<void>;
|
|
118
|
+
};
|
|
119
|
+
export declare const startOtlpCaptureServer: (options?: {
|
|
120
|
+
readonly host?: string;
|
|
121
|
+
}) => Promise<OtlpCaptureServer>;
|
|
84
122
|
export declare const makeCapture: (options?: RunOptions | undefined) => Effect.Effect<TelemetryCapture, never, never>;
|
|
85
|
-
export declare const run: <A, E, R>(program: Effect.Effect<A, E, R>, options?: RunOptions) => Effect.Effect<TelemetryRun<A, E>, never, R>;
|
|
86
|
-
export {};
|
|
123
|
+
export declare const run: <A, E, R>(program: Effect.Effect<A, E, R>, options?: RunOptions) => Effect.Effect<TelemetryRun<A, E | InvalidDataPolicy>, never, R>;
|
package/dist/testing/index.js
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { Effect, Layer, Option, Ref, Schema } from "effect";
|
|
2
2
|
import { HttpClient, HttpClientResponse } from "effect/unstable/http";
|
|
3
|
+
import { parseResourceIdentity } from "../ResourceIdentity.js";
|
|
3
4
|
import { layerOtlp } from "../Telemetry.js";
|
|
4
5
|
import { TelemetryConfig } from "../TelemetryConfig.js";
|
|
6
|
+
import { createServer } from "node:http";
|
|
7
|
+
export * from "./contract.js";
|
|
8
|
+
export * from "./conformance/index.js";
|
|
9
|
+
export * from "./deployedCanary.js";
|
|
10
|
+
export * from "../node/LocalCollector.js";
|
|
11
|
+
export { registerTestingAdapter, } from "../profile/ObservabilityAdapter.js";
|
|
12
|
+
export { createTestingNodeObservabilityFromConfig } from "../node/Observability.js";
|
|
5
13
|
const AttributeValue = Schema.Struct({
|
|
6
14
|
stringValue: Schema.String.pipe(Schema.optionalKey),
|
|
7
15
|
boolValue: Schema.Boolean.pipe(Schema.optionalKey),
|
|
@@ -27,8 +35,19 @@ const ExportedSpan = Schema.Struct({
|
|
|
27
35
|
message: Schema.String.pipe(Schema.optionalKey),
|
|
28
36
|
}).pipe(Schema.withDecodingDefault(Effect.succeed({ code: 0 }))),
|
|
29
37
|
attributes: Attributes,
|
|
30
|
-
|
|
31
|
-
|
|
38
|
+
droppedAttributesCount: Schema.Number.pipe(Schema.withDecodingDefault(Effect.succeed(0))),
|
|
39
|
+
events: Schema.Array(Schema.Struct({
|
|
40
|
+
name: Schema.String,
|
|
41
|
+
attributes: Attributes,
|
|
42
|
+
droppedAttributesCount: Schema.Number.pipe(Schema.withDecodingDefault(Effect.succeed(0))),
|
|
43
|
+
})).pipe(Schema.withDecodingDefault(Effect.succeed([]))),
|
|
44
|
+
droppedEventsCount: Schema.Number.pipe(Schema.withDecodingDefault(Effect.succeed(0))),
|
|
45
|
+
links: Schema.Array(Schema.Struct({
|
|
46
|
+
spanId: Schema.String,
|
|
47
|
+
attributes: Attributes,
|
|
48
|
+
droppedAttributesCount: Schema.Number.pipe(Schema.withDecodingDefault(Effect.succeed(0))),
|
|
49
|
+
})).pipe(Schema.withDecodingDefault(Effect.succeed([]))),
|
|
50
|
+
droppedLinksCount: Schema.Number.pipe(Schema.withDecodingDefault(Effect.succeed(0))),
|
|
32
51
|
});
|
|
33
52
|
const SpanExport = Schema.Struct({
|
|
34
53
|
resourceSpans: Schema.Array(Schema.Struct({
|
|
@@ -40,6 +59,7 @@ const ExportedLogRecord = Schema.Struct({
|
|
|
40
59
|
traceId: Schema.String.pipe(Schema.optionalKey),
|
|
41
60
|
spanId: Schema.String.pipe(Schema.optionalKey),
|
|
42
61
|
severityText: Schema.String.pipe(Schema.optionalKey),
|
|
62
|
+
droppedAttributesCount: Schema.Number.pipe(Schema.withDecodingDefault(Effect.succeed(0))),
|
|
43
63
|
body: Schema.Struct({ stringValue: Schema.String.pipe(Schema.optionalKey) }).pipe(Schema.optionalKey),
|
|
44
64
|
attributes: Attributes,
|
|
45
65
|
});
|
|
@@ -130,7 +150,7 @@ const captureClient = (store) => HttpClient.make((request, url) => Effect.gen(fu
|
|
|
130
150
|
}
|
|
131
151
|
return HttpClientResponse.fromWeb(request, new Response("{}", { status: 200 }));
|
|
132
152
|
}));
|
|
133
|
-
const decodeCapturedTelemetry = Effect.fn("decodeCapturedTelemetry")(function* (requests) {
|
|
153
|
+
export const decodeCapturedTelemetry = Effect.fn("decodeCapturedTelemetry")(function* (requests) {
|
|
134
154
|
const spans = [];
|
|
135
155
|
const logs = [];
|
|
136
156
|
const metrics = [];
|
|
@@ -150,6 +170,19 @@ const decodeCapturedTelemetry = Effect.fn("decodeCapturedTelemetry")(function* (
|
|
|
150
170
|
statusCode: span.status.code,
|
|
151
171
|
statusMessage: Option.fromNullishOr(span.status.message),
|
|
152
172
|
attributes: toAttributes(span.attributes),
|
|
173
|
+
droppedAttributesCount: span.droppedAttributesCount,
|
|
174
|
+
events: span.events.map((event) => ({
|
|
175
|
+
name: event.name,
|
|
176
|
+
attributes: toAttributes(event.attributes),
|
|
177
|
+
droppedAttributesCount: event.droppedAttributesCount,
|
|
178
|
+
})),
|
|
179
|
+
droppedEventsCount: span.droppedEventsCount,
|
|
180
|
+
links: span.links.map((link) => ({
|
|
181
|
+
spanId: link.spanId,
|
|
182
|
+
attributes: toAttributes(link.attributes),
|
|
183
|
+
droppedAttributesCount: link.droppedAttributesCount,
|
|
184
|
+
})),
|
|
185
|
+
droppedLinksCount: span.droppedLinksCount,
|
|
153
186
|
eventNames: span.events.map((event) => event.name),
|
|
154
187
|
linkedSpanIds: span.links.map((link) => link.spanId),
|
|
155
188
|
resourceAttributes,
|
|
@@ -168,6 +201,7 @@ const decodeCapturedTelemetry = Effect.fn("decodeCapturedTelemetry")(function* (
|
|
|
168
201
|
traceId: Option.fromNullishOr(log.traceId),
|
|
169
202
|
spanId: Option.fromNullishOr(log.spanId),
|
|
170
203
|
severityText: Option.fromNullishOr(log.severityText),
|
|
204
|
+
droppedAttributesCount: log.droppedAttributesCount,
|
|
171
205
|
body: Option.fromNullishOr(log.body?.stringValue),
|
|
172
206
|
attributes: toAttributes(log.attributes),
|
|
173
207
|
resourceAttributes,
|
|
@@ -246,15 +280,98 @@ const decodeCapturedTelemetry = Effect.fn("decodeCapturedTelemetry")(function* (
|
|
|
246
280
|
}
|
|
247
281
|
return { spans, logs, metrics };
|
|
248
282
|
});
|
|
249
|
-
const
|
|
283
|
+
const defaultIdentity = Effect.runSync(parseResourceIdentity({
|
|
250
284
|
serviceName: "telemetry-testing",
|
|
251
285
|
serviceVersion: "0.0.0",
|
|
252
286
|
environment: "test",
|
|
287
|
+
}));
|
|
288
|
+
const defaultConfig = new TelemetryConfig({
|
|
289
|
+
identity: defaultIdentity,
|
|
253
290
|
otlpEndpoint: new URL("http://telemetry.invalid"),
|
|
254
291
|
});
|
|
292
|
+
const ServerAddress = Schema.Struct({ address: Schema.String, port: Schema.Number });
|
|
293
|
+
const decodeServerAddress = Schema.decodeUnknownSync(ServerAddress);
|
|
294
|
+
const listenForCapture = (server, host) => new Promise((resolve, reject) => {
|
|
295
|
+
const onError = (cause) => {
|
|
296
|
+
server.off("listening", onListening);
|
|
297
|
+
reject(cause);
|
|
298
|
+
};
|
|
299
|
+
const onListening = () => {
|
|
300
|
+
server.off("error", onError);
|
|
301
|
+
resolve();
|
|
302
|
+
};
|
|
303
|
+
server.once("error", onError);
|
|
304
|
+
server.once("listening", onListening);
|
|
305
|
+
try {
|
|
306
|
+
server.listen(0, host);
|
|
307
|
+
}
|
|
308
|
+
catch (cause) {
|
|
309
|
+
server.off("error", onError);
|
|
310
|
+
server.off("listening", onListening);
|
|
311
|
+
reject(cause);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
const closeCaptureServer = (server) => new Promise((resolve, reject) => {
|
|
315
|
+
server.close((cause) => (cause === undefined ? resolve() : reject(cause)));
|
|
316
|
+
server.closeAllConnections();
|
|
317
|
+
});
|
|
318
|
+
const captureEndpoint = (host, port) => {
|
|
319
|
+
const hostname = host.includes(":") ? `[${host}]` : host;
|
|
320
|
+
return new URL(`http://${hostname}:${port}`);
|
|
321
|
+
};
|
|
322
|
+
const capturePayloadDecoders = new Map([
|
|
323
|
+
["/v1/traces", Schema.decodeUnknownOption(Schema.fromJsonString(SpanExport))],
|
|
324
|
+
["/v1/logs", Schema.decodeUnknownOption(Schema.fromJsonString(LogExport))],
|
|
325
|
+
["/v1/metrics", Schema.decodeUnknownOption(Schema.fromJsonString(MetricExport))],
|
|
326
|
+
]);
|
|
327
|
+
export const startOtlpCaptureServer = async (options) => {
|
|
328
|
+
const requests = [];
|
|
329
|
+
const server = createServer((request, response) => {
|
|
330
|
+
const chunks = [];
|
|
331
|
+
request.on("data", (chunk) => chunks.push(chunk));
|
|
332
|
+
request.on("end", () => {
|
|
333
|
+
const path = request.url ?? "";
|
|
334
|
+
const decodePayload = capturePayloadDecoders.get(path);
|
|
335
|
+
if (decodePayload !== undefined) {
|
|
336
|
+
const payload = decodePayload(Buffer.concat(chunks).toString("utf8"));
|
|
337
|
+
if (Option.isNone(payload)) {
|
|
338
|
+
response.writeHead(400, { "content-type": "application/json" });
|
|
339
|
+
response.end(JSON.stringify({ code: 3, message: "Invalid OTLP JSON payload." }));
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
requests.push({ path, payload: payload.value });
|
|
343
|
+
}
|
|
344
|
+
response.writeHead(200, { "content-type": "application/json" });
|
|
345
|
+
response.end("{}");
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
const host = options?.host ?? "127.0.0.1";
|
|
349
|
+
await listenForCapture(server, host);
|
|
350
|
+
try {
|
|
351
|
+
const address = decodeServerAddress(server.address());
|
|
352
|
+
const endpoint = captureEndpoint(address.address, address.port);
|
|
353
|
+
let stopPromise;
|
|
354
|
+
return {
|
|
355
|
+
endpoint,
|
|
356
|
+
telemetry: () => Effect.runSync(decodeCapturedTelemetry(requests)),
|
|
357
|
+
stop: () => {
|
|
358
|
+
stopPromise ??= closeCaptureServer(server);
|
|
359
|
+
return stopPromise;
|
|
360
|
+
},
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
catch (cause) {
|
|
364
|
+
await closeCaptureServer(server).catch(() => undefined);
|
|
365
|
+
throw cause;
|
|
366
|
+
}
|
|
367
|
+
};
|
|
255
368
|
export const makeCapture = Effect.fn("makeCapture")(function* (options) {
|
|
256
369
|
const store = yield* Ref.make([]);
|
|
257
|
-
const layer = layerOtlp(options?.config ?? defaultConfig
|
|
370
|
+
const layer = layerOtlp(options?.config ?? defaultConfig, {
|
|
371
|
+
policy: options?.policy,
|
|
372
|
+
resourceAttributes: options?.resourceAttributes,
|
|
373
|
+
contract: options?.contract,
|
|
374
|
+
}).pipe(Layer.provide(Layer.succeed(HttpClient.HttpClient, captureClient(store))));
|
|
258
375
|
const telemetry = Ref.get(store).pipe(Effect.flatMap(decodeCapturedTelemetry));
|
|
259
376
|
return { layer, telemetry };
|
|
260
377
|
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Context, Duration, Effect, Layer } from "effect";
|
|
2
|
+
import type { HttpClient } from "effect/unstable/http";
|
|
3
|
+
import { OtlpExporter, OtlpSerialization } from "effect/unstable/observability";
|
|
4
|
+
import type { BrowserTraceSpan } from "../BrowserEvents.js";
|
|
5
|
+
import type { ResourceAttributes } from "../ResourceIdentity.js";
|
|
6
|
+
import type { DataPolicy } from "../policy/DataPolicy.js";
|
|
7
|
+
export type HttpServerOtlpTracerOptions = {
|
|
8
|
+
readonly url: string;
|
|
9
|
+
readonly policy: DataPolicy;
|
|
10
|
+
readonly resource: {
|
|
11
|
+
readonly serviceName: string;
|
|
12
|
+
readonly serviceVersion: string;
|
|
13
|
+
readonly attributes: ResourceAttributes;
|
|
14
|
+
};
|
|
15
|
+
readonly shutdownTimeout?: Duration.Input | undefined;
|
|
16
|
+
};
|
|
17
|
+
export declare const layerHttpServerOtlpTracer: (options: HttpServerOtlpTracerOptions) => Layer.Layer<OtlpExporter.Flusher, never, HttpClient.HttpClient | OtlpSerialization.OtlpSerialization>;
|
|
18
|
+
export type BrowserSignals = {
|
|
19
|
+
readonly resource?: {
|
|
20
|
+
readonly serviceName: string;
|
|
21
|
+
readonly serviceVersion: string;
|
|
22
|
+
readonly environment: string;
|
|
23
|
+
};
|
|
24
|
+
readonly spans: ReadonlyArray<BrowserTraceSpan>;
|
|
25
|
+
};
|
|
26
|
+
declare const BrowserSignalExporter_base: Context.Reference<{
|
|
27
|
+
readonly export: (signals: BrowserSignals) => Effect.Effect<void>;
|
|
28
|
+
}>;
|
|
29
|
+
export declare class BrowserSignalExporter extends BrowserSignalExporter_base {
|
|
30
|
+
}
|
|
31
|
+
export type BrowserSignalExporterOptions = {
|
|
32
|
+
readonly tracesUrl: string;
|
|
33
|
+
readonly policy: DataPolicy;
|
|
34
|
+
readonly resource: {
|
|
35
|
+
readonly serviceName: string;
|
|
36
|
+
readonly serviceVersion: string;
|
|
37
|
+
readonly attributes: ResourceAttributes;
|
|
38
|
+
};
|
|
39
|
+
readonly shutdownTimeout?: Duration.Input | undefined;
|
|
40
|
+
};
|
|
41
|
+
export declare const layerBrowserSignalExporter: (options: BrowserSignalExporterOptions) => Layer.Layer<OtlpExporter.Flusher, never, HttpClient.HttpClient | OtlpSerialization.OtlpSerialization>;
|
|
42
|
+
export {};
|