@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.
Files changed (177) hide show
  1. package/README.md +11 -9
  2. package/dist/BrowserEvents.d.ts +89 -12
  3. package/dist/BrowserEvents.js +67 -13
  4. package/dist/Correlation.d.ts +51 -0
  5. package/dist/Correlation.js +95 -0
  6. package/dist/Metrics.d.ts +19 -3
  7. package/dist/Metrics.js +16 -0
  8. package/dist/MetricsRuntime.d.ts +45 -3
  9. package/dist/MetricsRuntime.js +478 -120
  10. package/dist/PolicyOtlpLogger.d.ts +18 -0
  11. package/dist/PolicyOtlpLogger.js +142 -0
  12. package/dist/RedactionPolicy.d.ts +2 -9
  13. package/dist/RedactionPolicy.js +2 -246
  14. package/dist/ResourceIdentity.d.ts +47 -0
  15. package/dist/ResourceIdentity.js +82 -0
  16. package/dist/Telemetry.d.ts +18 -3
  17. package/dist/Telemetry.js +43 -25
  18. package/dist/TelemetryConfig.d.ts +11 -4
  19. package/dist/TelemetryConfig.js +38 -10
  20. package/dist/audit/AuditCommitDocument.d.ts +41 -0
  21. package/dist/audit/AuditCommitDocument.js +58 -0
  22. package/dist/audit/AuditDigest.d.ts +11 -0
  23. package/dist/audit/AuditDigest.js +25 -0
  24. package/dist/audit/AuditOutbox.d.ts +75 -0
  25. package/dist/audit/AuditOutbox.js +104 -0
  26. package/dist/audit/AuditPublisher.d.ts +49 -0
  27. package/dist/audit/AuditPublisher.js +60 -0
  28. package/dist/audit/AuditRecord.d.ts +128 -0
  29. package/dist/audit/AuditRecord.js +172 -0
  30. package/dist/audit/CommittedAuditRecordInternal.d.ts +11 -0
  31. package/dist/audit/CommittedAuditRecordInternal.js +13 -0
  32. package/dist/audit/InvalidAuditRecord.d.ts +12 -0
  33. package/dist/audit/InvalidAuditRecord.js +16 -0
  34. package/dist/audit/index.d.ts +7 -0
  35. package/dist/audit/index.js +7 -0
  36. package/dist/browser/BrowserClient.d.ts +82 -3
  37. package/dist/browser/BrowserClient.js +322 -28
  38. package/dist/browser/BrowserEventLimits.d.ts +8 -0
  39. package/dist/browser/BrowserEventLimits.js +8 -0
  40. package/dist/browser/BrowserMetricRecorder.d.ts +17 -0
  41. package/dist/browser/BrowserMetricRecorder.js +35 -0
  42. package/dist/browser/BrowserTelemetry.d.ts +40 -0
  43. package/dist/browser/BrowserTelemetry.js +105 -0
  44. package/dist/browser/ClientPolicy.d.ts +3 -0
  45. package/dist/browser/ClientPolicy.js +52 -0
  46. package/dist/browser/client.d.ts +3 -2
  47. package/dist/browser/client.js +2 -1
  48. package/dist/browser/index.d.ts +4 -37
  49. package/dist/browser/index.js +3 -95
  50. package/dist/contract/ContractCompatibility.d.ts +31 -0
  51. package/dist/contract/ContractCompatibility.js +274 -0
  52. package/dist/contract/ContractIndex.d.ts +54 -0
  53. package/dist/contract/ContractIndex.js +178 -0
  54. package/dist/contract/ContractSurface.d.ts +111 -0
  55. package/dist/contract/ContractSurface.js +116 -0
  56. package/dist/contract/EventName.d.ts +6 -0
  57. package/dist/contract/EventName.js +55 -0
  58. package/dist/contract/EventProducer.d.ts +123 -0
  59. package/dist/contract/EventProducer.js +209 -0
  60. package/dist/contract/MetricContractError.d.ts +19 -0
  61. package/dist/contract/MetricContractError.js +19 -0
  62. package/dist/contract/MetricDefinition.d.ts +61 -0
  63. package/dist/contract/MetricDefinition.js +91 -0
  64. package/dist/contract/MetricProducer.d.ts +42 -0
  65. package/dist/contract/MetricProducer.js +123 -0
  66. package/dist/contract/OrganizationEvents.d.ts +165 -0
  67. package/dist/contract/OrganizationEvents.js +97 -0
  68. package/dist/contract/TelemetryContract.d.ts +95 -0
  69. package/dist/contract/TelemetryContract.js +451 -0
  70. package/dist/contract/TelemetryContractError.d.ts +44 -0
  71. package/dist/contract/TelemetryContractError.js +64 -0
  72. package/dist/contract/TelemetryEvent.d.ts +59 -0
  73. package/dist/contract/TelemetryEvent.js +54 -0
  74. package/dist/contract/index.d.ts +11 -0
  75. package/dist/contract/index.js +11 -0
  76. package/dist/effect/WideEvent.d.ts +3 -0
  77. package/dist/effect/WideEvent.js +20 -0
  78. package/dist/effect/WideEventSink.d.ts +3 -0
  79. package/dist/effect/WideEventSink.js +79 -0
  80. package/dist/effect/index.d.ts +2 -0
  81. package/dist/effect/index.js +2 -0
  82. package/dist/index.d.ts +17 -2
  83. package/dist/index.js +11 -2
  84. package/dist/metrics/InstrumentGrammar.d.ts +5 -0
  85. package/dist/metrics/InstrumentGrammar.js +12 -0
  86. package/dist/metrics/MetricScalar.d.ts +3 -0
  87. package/dist/metrics/MetricScalar.js +5 -0
  88. package/dist/node/AuditDigest.d.ts +3 -0
  89. package/dist/node/AuditDigest.js +6 -0
  90. package/dist/node/BrowserEventIngest.d.ts +7 -2
  91. package/dist/node/BrowserEventIngest.js +111 -19
  92. package/dist/node/LocalCollector.d.ts +20 -0
  93. package/dist/node/LocalCollector.js +188 -0
  94. package/dist/node/Observability.d.ts +49 -0
  95. package/dist/node/Observability.js +190 -0
  96. package/dist/node/Runtime.d.ts +4 -1
  97. package/dist/node/index.d.ts +4 -0
  98. package/dist/node/index.js +3 -0
  99. package/dist/policy/BrowserFieldPolicy.d.ts +7 -0
  100. package/dist/policy/BrowserFieldPolicy.js +298 -0
  101. package/dist/policy/DataPolicy.d.ts +19 -0
  102. package/dist/policy/DataPolicy.js +254 -0
  103. package/dist/policy/DataPolicyError.d.ts +22 -0
  104. package/dist/policy/DataPolicyError.js +25 -0
  105. package/dist/policy/Deduplication.d.ts +13 -0
  106. package/dist/policy/Deduplication.js +44 -0
  107. package/dist/policy/DefectEnvelope.d.ts +25 -0
  108. package/dist/policy/DefectEnvelope.js +52 -0
  109. package/dist/policy/MetricLabelPolicy.d.ts +5 -0
  110. package/dist/policy/MetricLabelPolicy.js +65 -0
  111. package/dist/policy/PolicyTransform.d.ts +16 -0
  112. package/dist/policy/PolicyTransform.js +136 -0
  113. package/dist/policy/PolicyVocabulary.d.ts +10 -0
  114. package/dist/policy/PolicyVocabulary.js +84 -0
  115. package/dist/policy/ResourceAttributePolicy.d.ts +9 -0
  116. package/dist/policy/ResourceAttributePolicy.js +33 -0
  117. package/dist/policy/entrypoint.d.ts +2 -0
  118. package/dist/policy/entrypoint.js +2 -0
  119. package/dist/policy/index.d.ts +17 -0
  120. package/dist/policy/index.js +9 -0
  121. package/dist/profile/DataPolicy.d.ts +2 -0
  122. package/dist/profile/DataPolicy.js +1 -0
  123. package/dist/profile/EnvironmentPolicy.d.ts +22 -0
  124. package/dist/profile/EnvironmentPolicy.js +41 -0
  125. package/dist/profile/LifecycleRegistry.d.ts +24 -0
  126. package/dist/profile/LifecycleRegistry.js +240 -0
  127. package/dist/profile/ObservabilityAdapter.d.ts +115 -0
  128. package/dist/profile/ObservabilityAdapter.js +50 -0
  129. package/dist/profile/ObservabilityConfig.d.ts +68 -0
  130. package/dist/profile/ObservabilityConfig.js +125 -0
  131. package/dist/profile/ObservabilityConfigError.d.ts +23 -0
  132. package/dist/profile/ObservabilityConfigError.js +39 -0
  133. package/dist/profile/ObservabilityProfile.d.ts +49 -0
  134. package/dist/profile/ObservabilityProfile.js +121 -0
  135. package/dist/profile/ReactWebProfile.d.ts +8 -0
  136. package/dist/profile/ReactWebProfile.js +7 -0
  137. package/dist/profile/index.d.ts +5 -0
  138. package/dist/profile/index.js +5 -0
  139. package/dist/testing/conformance/ConformanceAssertions.d.ts +5 -0
  140. package/dist/testing/conformance/ConformanceAssertions.js +31 -0
  141. package/dist/testing/conformance/ConformanceFailure.d.ts +35 -0
  142. package/dist/testing/conformance/ConformanceFailure.js +56 -0
  143. package/dist/testing/conformance/ConformanceModel.d.ts +97 -0
  144. package/dist/testing/conformance/ConformanceModel.js +8 -0
  145. package/dist/testing/conformance/ConformanceRegistry.d.ts +13 -0
  146. package/dist/testing/conformance/ConformanceRegistry.js +190 -0
  147. package/dist/testing/conformance/ConformanceRunner.d.ts +5 -0
  148. package/dist/testing/conformance/ConformanceRunner.js +198 -0
  149. package/dist/testing/conformance/TelemetryEvidence.d.ts +91 -0
  150. package/dist/testing/conformance/TelemetryEvidence.js +370 -0
  151. package/dist/testing/conformance/index.d.ts +10 -0
  152. package/dist/testing/conformance/index.js +6 -0
  153. package/dist/testing/contract.d.ts +81 -0
  154. package/dist/testing/contract.js +93 -0
  155. package/dist/testing/deployedCanary.d.ts +1 -0
  156. package/dist/testing/deployedCanary.js +1 -0
  157. package/dist/testing/index.d.ts +40 -3
  158. package/dist/testing/index.js +122 -5
  159. package/dist/trace/HttpServerOtlpTracer.d.ts +42 -0
  160. package/dist/trace/HttpServerOtlpTracer.js +301 -0
  161. package/package.json +16 -29
  162. package/dist/WideEvent.d.ts +0 -5
  163. package/dist/WideEvent.js +0 -6
  164. package/dist/nestjs/BrowserEventsController.d.ts +0 -21
  165. package/dist/nestjs/BrowserEventsController.js +0 -52
  166. package/dist/nestjs/HttpRoutePolicy.d.ts +0 -23
  167. package/dist/nestjs/HttpRoutePolicy.js +0 -179
  168. package/dist/nestjs/HttpServerOtlpTracer.d.ts +0 -15
  169. package/dist/nestjs/HttpServerOtlpTracer.js +0 -154
  170. package/dist/nestjs/RequestWideEventTraceCorrelation.d.ts +0 -15
  171. package/dist/nestjs/RequestWideEventTraceCorrelation.js +0 -13
  172. package/dist/nestjs/TelemetryInterceptor.d.ts +0 -31
  173. package/dist/nestjs/TelemetryInterceptor.js +0 -268
  174. package/dist/nestjs/TelemetryModule.d.ts +0 -53
  175. package/dist/nestjs/TelemetryModule.js +0 -428
  176. package/dist/nestjs/index.d.ts +0 -5
  177. 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;
@@ -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>;
@@ -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
- events: Schema.Array(Schema.Struct({ name: Schema.String })).pipe(Schema.withDecodingDefault(Effect.succeed([]))),
31
- links: Schema.Array(Schema.Struct({ spanId: Schema.String })).pipe(Schema.withDecodingDefault(Effect.succeed([]))),
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 defaultConfig = new TelemetryConfig({
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).pipe(Layer.provide(Layer.succeed(HttpClient.HttpClient, captureClient(store))));
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 {};