@smthrs/observability 1.0.0-rc.5 → 1.0.0-rc.7
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 +9 -8
- package/dist/cjs/Otel.d.ts +3 -2
- package/dist/cjs/Otel.d.ts.map +1 -1
- package/dist/cjs/Otel.js.map +2 -2
- package/dist/cjs/Otlp.d.ts +9 -6
- package/dist/cjs/Otlp.d.ts.map +1 -1
- package/dist/cjs/Otlp.js +23 -7
- package/dist/cjs/Otlp.js.map +2 -2
- package/dist/cjs/Resource.d.ts +6 -5
- package/dist/cjs/Resource.d.ts.map +1 -1
- package/dist/cjs/Resource.js +1 -1
- package/dist/cjs/Resource.js.map +2 -2
- package/dist/esm/Otel.d.ts +3 -2
- package/dist/esm/Otel.d.ts.map +1 -1
- package/dist/esm/Otel.js +2 -1
- package/dist/esm/Otel.js.map +1 -1
- package/dist/esm/Otlp.d.ts +9 -6
- package/dist/esm/Otlp.d.ts.map +1 -1
- package/dist/esm/Otlp.js +47 -13
- package/dist/esm/Otlp.js.map +1 -1
- package/dist/esm/Resource.d.ts +6 -5
- package/dist/esm/Resource.d.ts.map +1 -1
- package/dist/esm/Resource.js +7 -6
- package/dist/esm/Resource.js.map +1 -1
- package/docs/api.md +24 -12
- package/docs/concepts/instrumentation-and-export.md +31 -1
- package/docs/concepts/layer-map.md +5 -4
- package/docs/concepts/validated-acquisition.md +4 -3
- package/docs/guides/export-to-a-collector.md +27 -4
- package/docs/guides/testing.md +1 -1
- package/docs/guides/wire-an-opentelemetry-sdk.md +10 -4
- package/docs/installation.md +8 -8
- package/docs/troubleshooting.md +2 -2
- package/package.json +7 -7
- package/src/Otel.ts +3 -2
- package/src/Otlp.ts +52 -15
- package/src/Resource.ts +7 -6
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Release candidate scope, host requirements and compatibility review are defined in the [library support policy](https://github.com/smithersai/smithers/blob/main/RELEASE_SUPPORT.md).
|
|
4
4
|
|
|
5
|
-
This package declares `effect` as
|
|
6
|
-
`
|
|
7
|
-
|
|
5
|
+
This package declares `effect` as a `^4.0.4` peer dependency. Install one
|
|
6
|
+
`effect` release in that range so all Smithers packages share one Effect
|
|
7
|
+
runtime.
|
|
8
8
|
|
|
9
9
|
**Documentation:** https://observability.smithers.sh
|
|
10
10
|
|
|
@@ -20,11 +20,11 @@ Send an Effect program's logs, metrics, and traces to an OpenTelemetry collector
|
|
|
20
20
|
|
|
21
21
|
Not on npm yet; see [Installation](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/flow/docs/installation.md#use-the-libraries).
|
|
22
22
|
|
|
23
|
-
Node.js 26.4.0 or later. Effect services are identified by module identity, so install
|
|
23
|
+
Node.js 26.4.0 or later. Effect services are identified by module identity, so install one `effect` release, in the range `^4.0.4`.
|
|
24
24
|
|
|
25
|
-
The default install supports the root, `Otlp`, `Otel`, and `Resource
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
The default install supports the root, `Otlp`, `Otel`, and `Resource`. It
|
|
26
|
+
installs `@effect/opentelemetry@4.0.4` and requires the
|
|
27
|
+
`@opentelemetry/api@1.9.1` peer. It includes no HTTP exporters or trace SDK. Select the optional peers
|
|
28
28
|
for the host subpath you import:
|
|
29
29
|
|
|
30
30
|
```sh
|
|
@@ -52,7 +52,8 @@ units, strings to 65,536 code units, and attributes to 256 entries.
|
|
|
52
52
|
Resources are refused during layer acquisition with `InvalidResourceConfiguration`
|
|
53
53
|
if arrays exceed 256 elements or the whole OTLP JSON resource exceeds 128 KiB.
|
|
54
54
|
The byte budget counts keys, values, wrappers, JSON escaping, and UTF-8, including
|
|
55
|
-
service identity and SDK-added `telemetry.sdk.name
|
|
55
|
+
service identity and SDK-added `telemetry.sdk.name`, `telemetry.sdk.language`
|
|
56
|
+
and `telemetry.sdk.version`.
|
|
56
57
|
These SDK fields are reserved even for the default Effect exporter. Resource
|
|
57
58
|
metadata is explicit; both default OTLP and Node SDK layers isolate ambient
|
|
58
59
|
resource configuration so it cannot enlarge a resource after validation.
|
package/dist/cjs/Otel.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { type Configuration as ResourceConfiguration, type InvalidResourceConfig
|
|
|
16
16
|
* @since 0.1.0
|
|
17
17
|
*/
|
|
18
18
|
export interface Options {
|
|
19
|
-
/** Validated resource for metrics
|
|
19
|
+
/** Validated resource for metrics and provider factories. */
|
|
20
20
|
readonly resource: ResourceConfiguration;
|
|
21
21
|
/**
|
|
22
22
|
* Borrowed: the layer bridges onto this provider and never flushes or shuts
|
|
@@ -43,7 +43,8 @@ export interface Options {
|
|
|
43
43
|
* layer acquires. Factories run during layer acquisition after resource
|
|
44
44
|
* validation, and the provider factories receive the metric resource.
|
|
45
45
|
* Already-created providers keep the resource captured at construction; the
|
|
46
|
-
* resource option only sets
|
|
46
|
+
* resource option only sets the metric resource for them. Spans and log
|
|
47
|
+
* records carry the instrumentation scope `effect` with the Effect version.
|
|
47
48
|
* Ownership splits: callers own provider flushing and shutdown, including
|
|
48
49
|
* factory-built providers, while the layer scope shuts down every reader the
|
|
49
50
|
* `metricReader` factory returned. No exporter is allocated by this module.
|
package/dist/cjs/Otel.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Otel.d.ts","sourceRoot":"","sources":["../../src/Otel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,WAAW,MAAM,mCAAmC,CAAA;AAEhE,OAAO,KAAK,KAAK,GAAG,MAAM,oBAAoB,CAAA;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAE9D,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,EACL,KAAK,aAAa,IAAI,qBAAqB,EAC3C,KAAK,4BAA4B,EAEjC,QAAQ,EACT,MAAM,eAAe,CAAA;AAEtB;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,
|
|
1
|
+
{"version":3,"file":"Otel.d.ts","sourceRoot":"","sources":["../../src/Otel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,WAAW,MAAM,mCAAmC,CAAA;AAEhE,OAAO,KAAK,KAAK,GAAG,MAAM,oBAAoB,CAAA;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAE9D,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,EACL,KAAK,aAAa,IAAI,qBAAqB,EAC3C,KAAK,4BAA4B,EAEjC,QAAQ,EACT,MAAM,eAAe,CAAA;AAEtB;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAA;IACxC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EACpB,GAAG,CAAC,cAAc,GAClB,CAAC,CAAC,QAAQ,EAAE,OAAO,QAAQ,CAAC,OAAO,KAAK,GAAG,CAAC,cAAc,CAAC,GAC3D,SAAS,CAAA;IACb,sDAAsD;IACtD,QAAQ,CAAC,cAAc,CAAC,EACpB,cAAc,GACd,CAAC,CAAC,QAAQ,EAAE,OAAO,QAAQ,CAAC,OAAO,KAAK,cAAc,CAAC,GACvD,SAAS,CAAA;IACb;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC,GAAG,SAAS,CAAA;IACtF,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IACtD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,WAAW,CAAC,qBAAqB,GAAG,SAAS,CAAA;CAC3E;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS,GAAI,SAAS,OAAO,KAAG,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,4BAA4B,CAsC3F,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAe,CAAA"}
|
package/dist/cjs/Otel.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Otel.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Provider-neutral composition for injected OpenTelemetry providers.\n *\n * @since 0.1.0\n */\n\nimport * as OtelLogger from \"@effect/opentelemetry/OtelLogger\"\nimport * as OtelMetrics from \"@effect/opentelemetry/OtelMetrics\"\nimport * as OtelTracer from \"@effect/opentelemetry/OtelTracer\"\nimport type * as Api from \"@opentelemetry/api\"\nimport type { LoggerProvider } from \"@opentelemetry/sdk-logs\"\nimport type { MetricReader } from \"@opentelemetry/sdk-metrics\"\nimport * as Effect from \"effect/Effect\"\nimport * as Layer from \"effect/Layer\"\nimport {\n type Configuration as ResourceConfiguration,\n type InvalidResourceConfiguration,\n layer as resourceLayer,\n Resource\n} from \"./Resource.ts\"\n\n/**\n * Injected providers used by the provider-neutral OTEL layer.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface Options {\n /** Validated resource for metrics
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,iBAA4B;AAC5B,kBAA6B;AAC7B,iBAA4B;AAI5B,aAAwB;AACxB,YAAuB;AACvB,sBAKO;
|
|
4
|
+
"sourcesContent": ["/**\n * Provider-neutral composition for injected OpenTelemetry providers.\n *\n * @since 0.1.0\n */\n\nimport * as OtelLogger from \"@effect/opentelemetry/OtelLogger\"\nimport * as OtelMetrics from \"@effect/opentelemetry/OtelMetrics\"\nimport * as OtelTracer from \"@effect/opentelemetry/OtelTracer\"\nimport type * as Api from \"@opentelemetry/api\"\nimport type { LoggerProvider } from \"@opentelemetry/sdk-logs\"\nimport type { MetricReader } from \"@opentelemetry/sdk-metrics\"\nimport * as Effect from \"effect/Effect\"\nimport * as Layer from \"effect/Layer\"\nimport {\n type Configuration as ResourceConfiguration,\n type InvalidResourceConfiguration,\n layer as resourceLayer,\n Resource\n} from \"./Resource.ts\"\n\n/**\n * Injected providers used by the provider-neutral OTEL layer.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface Options {\n /** Validated resource for metrics and provider factories. */\n readonly resource: ResourceConfiguration\n /**\n * Borrowed: the layer bridges onto this provider and never flushes or shuts\n * it down, including a provider a factory returns. Existing providers retain\n * their resource. Factories must pass the supplied resource to the SDK.\n */\n readonly tracerProvider?:\n | Api.TracerProvider\n | ((resource: typeof Resource.Service) => Api.TracerProvider)\n | undefined\n /** Borrowed on the same terms as `tracerProvider`. */\n readonly loggerProvider?:\n | LoggerProvider\n | ((resource: typeof Resource.Service) => LoggerProvider)\n | undefined\n /**\n * Owned: the factory runs once during layer acquisition, after resource\n * validation, and every reader it returns is shut down when the scope\n * closes. Build the readers inside the factory rather than returning one a\n * longer-lived composition still exports through, which that shutdown would\n * disable. An empty array registers no reader at all.\n */\n readonly metricReader?: (() => MetricReader | ReadonlyArray<MetricReader>) | undefined\n readonly loggerMergeWithExisting?: boolean | undefined\n readonly metricTemporality?: OtelMetrics.TemporalityPreference | undefined\n}\n\n/**\n * Composes Effect tracer, logger, and metric bridges from already-created\n * OpenTelemetry providers or provider factories, and from metric readers this\n * layer acquires. Factories run during layer acquisition after resource\n * validation, and the provider factories receive the metric resource.\n * Already-created providers keep the resource captured at construction; the\n * resource option only sets the metric resource for them. Spans and log\n * records carry the instrumentation scope `effect` with the Effect version.\n * Ownership splits: callers own provider flushing and shutdown, including\n * factory-built providers, while the layer scope shuts down every reader the\n * `metricReader` factory returned. No exporter is allocated by this module.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layerOtel = (options: Options): Layer.Layer<never, InvalidResourceConfiguration> => {\n const resource = resourceLayer(options.resource)\n const tracerProvider = options.tracerProvider\n const loggerProvider = options.loggerProvider\n const tracer = tracerProvider === undefined\n ? Layer.empty\n : Layer.provide(\n OtelTracer.layer,\n Layer.effect(\n OtelTracer.OtelTracerProvider,\n Effect.map(\n Resource,\n (resource) => typeof tracerProvider === \"function\" ? tracerProvider(resource) : tracerProvider\n )\n )\n )\n const logger = loggerProvider === undefined\n ? Layer.empty\n : Layer.provide(\n OtelLogger.layer({ mergeWithExisting: options.loggerMergeWithExisting }),\n Layer.effect(\n OtelLogger.OtelLoggerProvider,\n Effect.map(\n Resource,\n (resource) => typeof loggerProvider === \"function\" ? loggerProvider(resource) : loggerProvider\n )\n )\n )\n const acquireMetricReader = options.metricReader\n const metrics = acquireMetricReader === undefined\n ? Layer.empty\n : OtelMetrics.layer(\n () => acquireMetricReader() as unknown as MetricReader | readonly [MetricReader, ...Array<MetricReader>],\n {\n temporality: options.metricTemporality\n }\n )\n return Layer.mergeAll(tracer, logger, metrics).pipe(Layer.provideMerge(resource))\n}\n\n/**\n * A no-op OTEL layer for callers that want an explicit optional slot.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layerNoop: Layer.Layer<never> = Layer.empty\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,iBAA4B;AAC5B,kBAA6B;AAC7B,iBAA4B;AAI5B,aAAwB;AACxB,YAAuB;AACvB,sBAKO;AAoDA,MAAM,YAAY,CAAC,YAAuE;AAC/F,QAAM,eAAW,gBAAAA,OAAc,QAAQ,QAAQ;AAC/C,QAAM,iBAAiB,QAAQ;AAC/B,QAAM,iBAAiB,QAAQ;AAC/B,QAAM,SAAS,mBAAmB,SAC9B,MAAM,QACN,MAAM;AAAA,IACN,WAAW;AAAA,IACX,MAAM;AAAA,MACJ,WAAW;AAAA,MACX,OAAO;AAAA,QACL;AAAA,QACA,CAACC,cAAa,OAAO,mBAAmB,aAAa,eAAeA,SAAQ,IAAI;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AACF,QAAM,SAAS,mBAAmB,SAC9B,MAAM,QACN,MAAM;AAAA,IACN,WAAW,MAAM,EAAE,mBAAmB,QAAQ,wBAAwB,CAAC;AAAA,IACvE,MAAM;AAAA,MACJ,WAAW;AAAA,MACX,OAAO;AAAA,QACL;AAAA,QACA,CAACA,cAAa,OAAO,mBAAmB,aAAa,eAAeA,SAAQ,IAAI;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AACF,QAAM,sBAAsB,QAAQ;AACpC,QAAM,UAAU,wBAAwB,SACpC,MAAM,QACN,YAAY;AAAA,IACZ,MAAM,oBAAoB;AAAA,IAC1B;AAAA,MACE,aAAa,QAAQ;AAAA,IACvB;AAAA,EACF;AACF,SAAO,MAAM,SAAS,QAAQ,QAAQ,OAAO,EAAE,KAAK,MAAM,aAAa,QAAQ,CAAC;AAClF;AAQO,MAAM,YAAgC,MAAM;",
|
|
6
6
|
"names": ["resourceLayer", "resource"]
|
|
7
7
|
}
|
package/dist/cjs/Otlp.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `Metric` counters on their hot paths; what they deliberately do not do is
|
|
6
6
|
* ship an exporter. This module is that exporter: one layer that installs
|
|
7
7
|
* Effect's own OTLP logger, metrics exporter, and tracer
|
|
8
|
-
* (`effect/
|
|
8
|
+
* (`effect/observability/Otlp`) against a collector endpoint, with
|
|
9
9
|
* the flows service identity filled in. Nothing beyond `effect` is involved;
|
|
10
10
|
* no OpenTelemetry SDK dependency.
|
|
11
11
|
*
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
* @since 0.1.0
|
|
19
19
|
*/
|
|
20
20
|
import type * as Duration from "effect/Duration";
|
|
21
|
+
import * as Headers from "effect/http/Headers";
|
|
22
|
+
import * as HttpClient from "effect/http/HttpClient";
|
|
21
23
|
import * as Layer from "effect/Layer";
|
|
22
|
-
import * as Headers from "effect/unstable/http/Headers";
|
|
23
|
-
import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
24
24
|
import * as Endpoint from "./Endpoint.ts";
|
|
25
25
|
import * as Resource from "./Resource.ts";
|
|
26
26
|
/**
|
|
@@ -45,7 +45,7 @@ export declare const defaultServiceName = "flows";
|
|
|
45
45
|
* @category resource
|
|
46
46
|
* @since 0.1.0
|
|
47
47
|
*/
|
|
48
|
-
export declare const defaultServiceVersion = "1.0.0-rc.
|
|
48
|
+
export declare const defaultServiceVersion = "1.0.0-rc.7";
|
|
49
49
|
/**
|
|
50
50
|
* Maximum encoded export request size, in bytes.
|
|
51
51
|
* @category transport
|
|
@@ -63,8 +63,9 @@ export declare const maximumEnvelopeBytes: number;
|
|
|
63
63
|
*
|
|
64
64
|
* The transport discards a request over 1 MiB, and the resource rides in every
|
|
65
65
|
* request, so the largest resource `Resource.decode` admits
|
|
66
|
-
* (`Resource.maximumResourceBytes`, 128 KiB) and the envelope
|
|
67
|
-
* service name (under 8 KiB) come off the top.
|
|
66
|
+
* (`Resource.maximumResourceBytes`, 128 KiB) and the envelope, which in a
|
|
67
|
+
* metrics request repeats the service name (under 8 KiB), come off the top.
|
|
68
|
+
* The 888 KiB left gives each
|
|
68
69
|
* record of a full 1,000-record logger or tracer batch about 900 bytes, three
|
|
69
70
|
* to four times a bare log record or span, and gives the metrics snapshot room
|
|
70
71
|
* for several thousand series. Every resource the decoder accepts therefore
|
|
@@ -126,6 +127,8 @@ export interface Options {
|
|
|
126
127
|
* once a minute a `Warn` record with code `otlp_export_discarded` names the
|
|
127
128
|
* reason, the request size, and the running total through the loggers that
|
|
128
129
|
* were installed when the layer was acquired, never through this exporter.
|
|
130
|
+
* A collector's response body is never read: the exporter acts on the status
|
|
131
|
+
* and the `retry-after` header, and the exchange ends when they arrive.
|
|
129
132
|
*
|
|
130
133
|
* **Details**
|
|
131
134
|
*
|
package/dist/cjs/Otlp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Otlp.d.ts","sourceRoot":"","sources":["../../src/Otlp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"Otlp.d.ts","sourceRoot":"","sources":["../../src/Otlp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAIhD,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAA;AAE9C,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAA;AAGpD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AASrC,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AACzC,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AAEzC;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,UAAU,CAAA;AAEzC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,eAAe,CAAA;AAMjD;;;;GAIG;AACH,eAAO,MAAM,eAAe,QAAc,CAAA;AAQ1C;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,QAAW,CAAA;AAE5C;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,QAAyE,CAAA;AA2MxG;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzC,kFAAkF;IAClF,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5C;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;IACzD;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,KAAK,GAAG,SAAS,CAAA;IAC5C,+FAA+F;IAC/F,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,KAAK,GAAG,SAAS,CAAA;IACpD,uEAAuE;IACvE,QAAQ,CAAC,eAAe,CAAC,EAAE,QAAQ,CAAC,KAAK,GAAG,SAAS,CAAA;CACtD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,KAAK,GAChB,SAAS,OAAO,KACf,KAAK,CAAC,KAAK,CACZ,KAAK,EACL,QAAQ,CAAC,4BAA4B,GAAG,QAAQ,CAAC,uBAAuB,EACxE,UAAU,CAAC,UAAU,CAyCpB,CAAA;AAEH;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,UAAU,GACrB,SAAS,OAAO,KACf,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,4BAA4B,GAAG,QAAQ,CAAC,uBAAuB,CACnC,CAAA;AAE3D;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,4BAA4B,GAAG,QAAQ,CAAC,uBAAuB,CAAA;AAEjG;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,GAAG,SAAS,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAc7E,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,GAC3B,aAAa,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EACzD,UAAS,IAAI,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,CAAM,KACjD,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,CAI/B,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAe,CAAA"}
|
package/dist/cjs/Otlp.js
CHANGED
|
@@ -46,23 +46,23 @@ var import_Clock = require("effect/Clock");
|
|
|
46
46
|
var ConfigProvider = __toESM(require("effect/ConfigProvider"), 1);
|
|
47
47
|
var Effect = __toESM(require("effect/Effect"), 1);
|
|
48
48
|
var Exit = __toESM(require("effect/Exit"), 1);
|
|
49
|
+
var FetchHttpClient = __toESM(require("effect/http/FetchHttpClient"), 1);
|
|
50
|
+
var Headers = __toESM(require("effect/http/Headers"), 1);
|
|
51
|
+
var HttpClient = __toESM(require("effect/http/HttpClient"), 1);
|
|
52
|
+
var HttpClientResponse = __toESM(require("effect/http/HttpClientResponse"), 1);
|
|
49
53
|
var Layer = __toESM(require("effect/Layer"), 1);
|
|
50
54
|
var Logger = __toESM(require("effect/Logger"), 1);
|
|
51
55
|
var Metric = __toESM(require("effect/Metric"), 1);
|
|
56
|
+
var Otlp = __toESM(require("effect/observability/Otlp"), 1);
|
|
52
57
|
var Option = __toESM(require("effect/Option"), 1);
|
|
53
58
|
var References = __toESM(require("effect/References"), 1);
|
|
54
59
|
var Schema = __toESM(require("effect/Schema"), 1);
|
|
55
60
|
var Semaphore = __toESM(require("effect/Semaphore"), 1);
|
|
56
61
|
var Tracer = __toESM(require("effect/Tracer"), 1);
|
|
57
|
-
var FetchHttpClient = __toESM(require("effect/unstable/http/FetchHttpClient"), 1);
|
|
58
|
-
var Headers = __toESM(require("effect/unstable/http/Headers"), 1);
|
|
59
|
-
var HttpClient = __toESM(require("effect/unstable/http/HttpClient"), 1);
|
|
60
|
-
var HttpClientResponse = __toESM(require("effect/unstable/http/HttpClientResponse"), 1);
|
|
61
|
-
var Otlp = __toESM(require("effect/unstable/observability/Otlp"), 1);
|
|
62
62
|
var Endpoint = __toESM(require("./Endpoint.js"), 1);
|
|
63
63
|
var Resource = __toESM(require("./Resource.js"), 1);
|
|
64
64
|
const defaultServiceName = "flows";
|
|
65
|
-
const defaultServiceVersion = "1.0.0-rc.
|
|
65
|
+
const defaultServiceVersion = "1.0.0-rc.7";
|
|
66
66
|
const maxBatchSize = 1e3;
|
|
67
67
|
const maxInFlight = 4;
|
|
68
68
|
const maxRequestBytes = 1024 * 1024;
|
|
@@ -70,10 +70,26 @@ const requestTimeout = "10 seconds";
|
|
|
70
70
|
const diagnosticIntervalMillis = 6e4;
|
|
71
71
|
const maximumEnvelopeBytes = 8 * 1024;
|
|
72
72
|
const reservedBatchBytes = maxRequestBytes - Resource.maximumResourceBytes - maximumEnvelopeBytes;
|
|
73
|
+
const withoutBody = (response) => {
|
|
74
|
+
const retryAfter = response.headers["retry-after"];
|
|
75
|
+
let answer;
|
|
76
|
+
try {
|
|
77
|
+
answer = new Response(null, {
|
|
78
|
+
status: response.status,
|
|
79
|
+
headers: retryAfter === void 0 ? {} : { "retry-after": retryAfter }
|
|
80
|
+
});
|
|
81
|
+
} catch {
|
|
82
|
+
answer = Response.error();
|
|
83
|
+
}
|
|
84
|
+
return HttpClientResponse.fromWeb(response.request, answer);
|
|
85
|
+
};
|
|
73
86
|
const boundedClient = Layer.effect(
|
|
74
87
|
HttpClient.HttpClient,
|
|
75
88
|
Effect.gen(function* () {
|
|
76
|
-
const client =
|
|
89
|
+
const client = HttpClient.transformResponse(
|
|
90
|
+
HttpClient.withScope(yield* HttpClient.HttpClient),
|
|
91
|
+
(exchange) => exchange.pipe(Effect.map(withoutBody), Effect.scoped)
|
|
92
|
+
);
|
|
77
93
|
const clock = yield* import_Clock.Clock;
|
|
78
94
|
const ambientLoggers = yield* Effect.withFiber((fiber) => Effect.succeed(fiber.getRef(Logger.CurrentLoggers)));
|
|
79
95
|
const permits = Semaphore.makeUnsafe(maxInFlight);
|
package/dist/cjs/Otlp.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Otlp.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Default OTLP export wiring for flows telemetry.\n *\n * The store packages already open spans through Effect's tracer and update\n * `Metric` counters on their hot paths; what they deliberately do not do is\n * ship an exporter. This module is that exporter: one layer that installs\n * Effect's own OTLP logger, metrics exporter, and tracer\n * (`effect/unstable/observability/Otlp`) against a collector endpoint, with\n * the flows service identity filled in. Nothing beyond `effect` is involved;\n * no OpenTelemetry SDK dependency.\n *\n * Browser support is met by construction rather than by a no-op variant:\n * export happens over Effect's `HttpClient`, and {@link layerFetch} binds the\n * `fetch` implementation the host already has, so no entry point here ever\n * resolves a `node:` built-in. See the\n * {@link https://smithers.sh/docs/reference/api/observability | observability API contract}.\n *\n * @since 0.1.0\n */\n\nimport * as Redaction from \"@smthrs/journal/Redaction\"\nimport * as Cause from \"effect/Cause\"\nimport { Clock } from \"effect/Clock\"\nimport * as ConfigProvider from \"effect/ConfigProvider\"\nimport type * as Duration from \"effect/Duration\"\nimport * as Effect from \"effect/Effect\"\nimport * as Exit from \"effect/Exit\"\nimport * as Layer from \"effect/Layer\"\nimport * as Logger from \"effect/Logger\"\nimport * as Metric from \"effect/Metric\"\nimport * as Option from \"effect/Option\"\nimport * as References from \"effect/References\"\nimport * as Schema from \"effect/Schema\"\nimport * as Semaphore from \"effect/Semaphore\"\nimport * as Tracer from \"effect/Tracer\"\nimport * as FetchHttpClient from \"effect/unstable/http/FetchHttpClient\"\nimport * as Headers from \"effect/unstable/http/Headers\"\nimport type * as HttpBody from \"effect/unstable/http/HttpBody\"\nimport * as HttpClient from \"effect/unstable/http/HttpClient\"\nimport type * as HttpClientRequest from \"effect/unstable/http/HttpClientRequest\"\nimport * as HttpClientResponse from \"effect/unstable/http/HttpClientResponse\"\nimport * as Otlp from \"effect/unstable/observability/Otlp\"\nimport * as Endpoint from \"./Endpoint.ts\"\nimport * as Resource from \"./Resource.ts\"\n\n/**\n * The `service.name` resource attribute installed when the caller supplies\n * none: the flows distribution itself. Override it per application with\n * {@link Options.serviceName}.\n *\n * @category resource\n * @since 0.1.0\n */\nexport const defaultServiceName = \"flows\"\n\n/**\n * The `service.version` resource attribute installed when the caller supplies\n * none. Mirrors the release version in this package's `package.json`.\n *\n * A published package cannot read its own manifest on every runtime it\n * supports, so the version lives here as a literal.\n * `scripts/set-release-version.mjs` rewrites this declaration with the\n * manifests, and its `--check` mode reports drift, so a release bump cannot\n * leave it behind.\n *\n * @category resource\n * @since 0.1.0\n */\nexport const defaultServiceVersion = \"1.0.0-rc.5\"\n\n// The upstream logger and tracer each buffer at most one 1,000-record batch.\n// Do not queue at the transport: upstream forks every full batch independently.\nconst maxBatchSize = 1000\nconst maxInFlight = 4\n/**\n * Maximum encoded export request size, in bytes.\n * @category transport\n * @since 1.0.0-rc.0\n */\nexport const maxRequestBytes = 1024 * 1024\nconst requestTimeout = \"10 seconds\"\nconst diagnosticIntervalMillis = 60_000\n// The envelope around the resource in every request repeats `service.name` as\n// the instrumentation scope name: at most 1,024 code units, at most six bytes\n// each once JSON-escaped, so under 8 KiB together with the envelope's own keys.\n/**\n * Reserved bytes for request wrappers and the escaped instrumentation scope.\n * @category transport\n * @since 1.0.0-rc.0\n */\nexport const maximumEnvelopeBytes = 8 * 1024\n\n/**\n * Bytes of every export request kept free for the signal batch itself.\n *\n * The transport discards a request over 1 MiB, and the resource rides in every\n * request, so the largest resource `Resource.decode` admits\n * (`Resource.maximumResourceBytes`, 128 KiB) and the envelope that repeats the\n * service name (under 8 KiB) come off the top. The 888 KiB left gives each\n * record of a full 1,000-record logger or tracer batch about 900 bytes, three\n * to four times a bare log record or span, and gives the metrics snapshot room\n * for several thousand series. Every resource the decoder accepts therefore\n * leaves an ordinary batch of any signal exportable; what this reserve does\n * not bound is a single application record or a registry large enough to\n * exceed it on its own.\n *\n * @category transport\n * @since 1.0.0-rc.0\n */\nexport const reservedBatchBytes = maxRequestBytes - Resource.maximumResourceBytes - maximumEnvelopeBytes\n\ntype DiscardReason = \"oversized\" | \"stalled\" | \"saturated\"\n\nconst boundedClient = Layer.effect(\n HttpClient.HttpClient,\n Effect.gen(function*() {\n const client = yield* HttpClient.HttpClient\n const clock = yield* Clock\n // The loggers installed when this transport is acquired. The OTLP logger\n // the same acquisition installs does not exist yet, so a diagnostic pinned\n // to this set cannot enter the exporter it describes, whichever fiber runs\n // the export: the interval and shutdown fibers inherit this set anyway,\n // but a flush requested from application code runs with the application's\n // loggers, which by then include this exporter.\n const ambientLoggers = yield* Effect.withFiber((fiber) => Effect.succeed(fiber.getRef(Logger.CurrentLoggers)))\n const permits = Semaphore.makeUnsafe(maxInFlight)\n // The counter lives with the transport it describes.\n const droppedExports = Metric.counter(\"flows_observability_otlp_dropped\")\n let nextDiagnosticAt = -Infinity\n // A local discard is terminal, so the upstream retry loop must not retain\n // or retry its payload, and the counter records batches, not records. The\n // warning is the diagnostic the counter cannot be: the counter is exported\n // through this same transport and shares every outage with it. One\n // warning per minute keeps a sustained outage from flooding the ambient\n // loggers; the running total in its annotations carries the volume.\n // Replace ambient annotations and log spans to bound the diagnostic itself.\n const discard = (reason: DiscardReason, request: HttpClientRequest.HttpClientRequest, bytes: number) =>\n Metric.update(droppedExports, 1).pipe(\n Effect.andThen(Effect.suspend(() => {\n const now = clock.currentTimeMillisUnsafe()\n if (now < nextDiagnosticAt) return Effect.void\n nextDiagnosticAt = now + diagnosticIntervalMillis\n return Metric.value(droppedExports).pipe(\n Effect.flatMap((dropped) =>\n Effect.logWarning(\"An OTLP export batch was discarded\").pipe(\n Effect.provideService(References.CurrentLogSpans, []),\n Effect.provideService(References.CurrentLogAnnotations, {\n code: \"otlp_export_discarded\",\n reason,\n bytes,\n limit: maxRequestBytes,\n dropped: dropped.count\n })\n )\n ),\n Effect.provideService(Logger.CurrentLoggers, ambientLoggers)\n )\n })),\n Effect.as(HttpClientResponse.fromWeb(request, new Response(null, { status: 204 })))\n )\n return HttpClient.transform(client, (requestEffect, request) =>\n Effect.suspend(() => {\n // layerJson always supplies a Uint8Array body with a byte length.\n const bytes = (request.body as HttpBody.Uint8Array).contentLength\n if (bytes > maxRequestBytes) return discard(\"oversized\", request, bytes)\n // Fetch must expose redirects before any credential or signal body\n // leaves the configured endpoint, even when the caller enables follow.\n const confinedRequest = Effect.flatMap(Effect.serviceOption(FetchHttpClient.RequestInit), (init) =>\n requestEffect.pipe(\n Effect.provideService(FetchHttpClient.RequestInit, {\n ...Option.getOrUndefined(init),\n redirect: \"manual\"\n })\n ))\n return confinedRequest.pipe(\n Effect.timeoutOrElse({\n duration: requestTimeout,\n orElse: () =>\n discard(\"stalled\", request, bytes)\n }),\n permits.withPermitsIfAvailable(1),\n Effect.flatMap(Option.match({\n onNone: () =>\n discard(\"saturated\", request, bytes),\n onSome: Effect.succeed\n }))\n )\n }))\n })\n)\n\nconst loopbackIpv4 = /^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/\n\n/** Whether a decoded endpoint's host never leaves this machine. */\nconst isLoopback = (endpoint: string): boolean => {\n const hostname = new URL(endpoint).hostname\n return hostname === \"localhost\" || hostname === \"[::1]\" || loopbackIpv4.test(hostname)\n}\n\n/**\n * Refuses a credential header bound for a plaintext collector off this\n * machine. Anyone on the network path could read the token from every export\n * request, and the exporter would never report it. Loopback `http://` stays\n * allowed for a local collector or sidecar; non-credential headers such as a\n * tenant id stay allowed on any endpoint.\n */\n/**\n * Vendor credential headers whose names `Redaction.isSensitiveKey` does not\n * recognize. Honeycomb sends its ingest key as `x-honeycomb-team`.\n */\nconst vendorCredentialHeaders: ReadonlySet<string> = new Set([\"x-honeycomb-team\"])\n\nconst isCredentialHeader = (name: string): boolean =>\n Redaction.isSensitiveKey(name) || vendorCredentialHeaders.has(name.toLowerCase())\n\nconst refusePlaintextCredentials = (\n baseUrl: string,\n headers: Headers.Input | undefined\n): Effect.Effect<void, Endpoint.InvalidExporterEndpoint> => {\n if (!baseUrl.toLowerCase().startsWith(\"http:\") || isLoopback(baseUrl)) return Effect.void\n const credential = Object.keys(Headers.fromInput(headers)).some(isCredentialHeader)\n return credential\n ? Effect.fail(\n new Endpoint.InvalidExporterEndpoint({\n code: \"invalid_exporter_endpoint\",\n path: \"baseUrl\",\n message:\n \"OTLP collector baseUrl must use https:// when headers carry credentials, unless it is a loopback address\"\n })\n )\n : Effect.void\n}\n\nconst redactText = (text: string): string => String(Redaction.redact(text))\n\n/**\n * A failed span's error rebuilt with its text redacted. It keeps the original\n * error's `name` and `stack` (redacted) so the collector's exception type and\n * trace stay readable; it is exported to the collector and never thrown.\n */\nclass RedactedSpanError extends Schema.TaggedError<RedactedSpanError>()(\"@smthrs/observability/RedactedSpanError\", {\n message: Schema.String\n}) {}\n\n/**\n * A span failure rendered with credentials removed. The exporter serializes a\n * failed span's cause into its status message and `exception` events, which\n * would otherwise carry any token an error message quoted to the collector.\n */\nconst redactedExit = (exit: Exit.Exit<unknown, unknown>): Exit.Exit<unknown, unknown> => {\n if (exit._tag === \"Success\" || Cause.hasInterruptsOnly(exit.cause)) return exit\n const errors = Cause.prettyErrors(exit.cause, { includeCauseInStack: true }).map((error) => {\n const redacted = new RedactedSpanError({ message: redactText(error.message) })\n Object.defineProperty(redacted, \"name\", { value: redactText(error.name), configurable: true, writable: true })\n // `prettyErrors` always renders a stack.\n redacted.stack = redactText(String(error.stack))\n return redacted\n })\n return Exit.failCause(errors.map(Cause.fail).reduce(Cause.combine, Cause.empty as Cause.Cause<unknown>))\n}\n\n/**\n * Wraps the installed tracer so every exported span's failure and string\n * attributes pass through the journal redaction rules first.\n */\nconst redactedSpans = Layer.effect(Tracer.Tracer)(\n Effect.map(Effect.tracer, (tracer) =>\n Tracer.make({\n ...tracer,\n span(options) {\n const span = tracer.span(options)\n const end = span.end.bind(span)\n const attribute = span.attribute.bind(span)\n span.end = (endTime, exit) => end(endTime, redactedExit(exit))\n span.attribute = (key, value) => attribute(key, typeof value === \"string\" ? redactText(value) : value)\n return span\n }\n }))\n)\n\n/**\n * Configuration for the default OTLP wiring.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface Options {\n /**\n * The collector base URL, for example `http://localhost:4318`. Signals are\n * posted below it at `/v1/logs`, `/v1/metrics`, and `/v1/traces`. It must be\n * an absolute `http://` or `https://` URL without credentials, a query,\n * fragment, backslashes, spaces, or controls. A base path is allowed. Invalid\n * values fail acquisition with {@link Endpoint.InvalidExporterEndpoint}.\n * Use {@link Options.headers} for authentication.\n */\n readonly baseUrl: string\n /** Overrides {@link defaultServiceName} as the `service.name` attribute. */\n readonly serviceName?: string | undefined\n /** Overrides {@link defaultServiceVersion} as the `service.version` attribute. */\n readonly serviceVersion?: string | undefined\n /**\n * Additional resource attributes attached to every exported signal, decoded\n * by `Resource.Attributes`. The whole resource must encode to at most\n * `Resource.maximumResourceBytes`; a larger one fails acquisition with\n * {@link Resource.InvalidResourceConfiguration} rather than making every\n * request oversized.\n */\n readonly attributes?: Record<string, unknown> | undefined\n /**\n * Headers sent with every export request, for example vendor auth. A header\n * whose name names a credential (`authorization`, `x-api-key`, anything\n * `Redaction.isSensitiveKey` recognizes, plus `x-honeycomb-team`) requires\n * an `https://` baseUrl unless the host is loopback; otherwise acquisition\n * fails with\n * {@link Endpoint.InvalidExporterEndpoint}.\n */\n readonly headers?: Headers.Input | undefined\n /** Export cadence for all three signals; each signal's Effect default applies when omitted. */\n readonly exportInterval?: Duration.Input | undefined\n /** Upper bound on the shutdown flush when the layer's scope closes. */\n readonly shutdownTimeout?: Duration.Input | undefined\n}\n\n/**\n * Creates the OTLP logs, metrics, and traces layer with flows resource\n * defaults, JSON-serialized. Exports share a four-request limit with no waiting\n * queue. Requests larger than 1 MiB or stalled for ten seconds are discarded;\n * `flows_observability_otlp_dropped` counts discarded batches, and at most\n * once a minute a `Warn` record with code `otlp_export_discarded` names the\n * reason, the request size, and the running total through the loggers that\n * were installed when the layer was acquired, never through this exporter.\n *\n * **Details**\n *\n * The layer still requires an `HttpClient`, which is how it stays\n * platform-neutral: a Node host may hand it `@effect/platform-node`'s Undici\n * client (re-exported by `@smthrs/platform-node`), a browser or test\n * hands it something else. Use {@link layerFetch} when the host's global\n * `fetch` is good enough. On Node 26 and every browser it is.\n * Fetch redirects are refused. Supply `FetchHttpClient.RequestInit` around\n * the whole exporting effect to retain other fetch options; options scoped\n * only to the supplied client's layer are replaced by the redirect policy.\n * Other HTTP transports must independently refuse automatic redirects.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layer = (\n options: Options\n): Layer.Layer<\n never,\n Resource.InvalidResourceConfiguration | Endpoint.InvalidExporterEndpoint,\n HttpClient.HttpClient\n> =>\n Layer.unwrap(\n Effect.map(\n Effect.all([\n Resource.decode({\n serviceName: options.serviceName ?? defaultServiceName,\n serviceVersion: options.serviceVersion ?? defaultServiceVersion,\n ...(options.attributes === undefined ? {} : { attributes: options.attributes })\n }),\n Endpoint.decode(options.baseUrl, \"baseUrl\").pipe(\n Effect.tap((baseUrl) => refusePlaintextCredentials(baseUrl, options.headers))\n )\n ]),\n ([decoded, baseUrl]) => {\n const resource = Resource.toOpenTelemetryConfiguration(decoded)\n return (\n Otlp.layerJson({\n baseUrl,\n resource: {\n serviceName: resource.serviceName,\n // `serviceVersion` is supplied above before Resource decoding.\n serviceVersion: resource.serviceVersion!,\n ...(resource.attributes === undefined ? {} : { attributes: resource.attributes })\n },\n headers: options.headers,\n maxBatchSize,\n loggerExportInterval: options.exportInterval,\n metricsExportInterval: options.exportInterval,\n tracerExportInterval: options.exportInterval,\n shutdownTimeout: options.shutdownTimeout\n }).pipe(\n Layer.provide(boundedClient),\n // Upstream merges OTEL_RESOURCE_ATTRIBUTES even with explicit\n // options. Keep unvalidated ambient metadata out of every request.\n Layer.provide(ConfigProvider.layer(ConfigProvider.fromUnknown({}))),\n (exporter) => Layer.provideMerge(redactedSpans, exporter)\n )\n )\n }\n )\n )\n\n/**\n * Provides {@link layer} over the host's global `fetch`, the default wiring\n * for a Node host, and browser-safe by construction because it never touches\n * a `node:` built-in.\n *\n * **Example**\n *\n * ```ts\n * import * as Otlp from \"@smthrs/observability/Otlp\"\n *\n * const Telemetry = Otlp.layerFetch({ baseUrl: \"http://localhost:4318\" })\n * ```\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layerFetch = (\n options: Options\n): Layer.Layer<never, Resource.InvalidResourceConfiguration | Endpoint.InvalidExporterEndpoint> =>\n layer(options).pipe(Layer.provide(FetchHttpClient.layer))\n\n/**\n * Why an OTLP layer refused to start.\n *\n * @category errors\n * @since 1.0.0\n */\nexport type LayerError = Resource.InvalidResourceConfiguration | Endpoint.InvalidExporterEndpoint\n\n/**\n * Parses `OTEL_EXPORTER_OTLP_HEADERS`: comma-separated `key=value` pairs whose\n * values are percent-decoded, as the OpenTelemetry exporter specification\n * defines. A pair without `=` or with an empty key is skipped.\n *\n * @category environment\n * @since 1.0.0\n */\nexport const parseHeaders = (value: string | undefined): Record<string, string> => {\n const headers: Record<string, string> = {}\n for (const pair of (value ?? \"\").split(\",\")) {\n const separator = pair.indexOf(\"=\")\n const key = pair.slice(0, separator).trim()\n if (separator < 0 || key === \"\") continue\n const raw = pair.slice(separator + 1).trim()\n let decoded = raw\n try {\n decoded = decodeURIComponent(raw)\n } catch { /* A malformed escape is kept verbatim. */ }\n headers[key] = decoded\n }\n return headers\n}\n\n/**\n * {@link layerFetch} when the environment names a collector, otherwise\n * {@link layerNoop}.\n *\n * `OTEL_EXPORTER_OTLP_ENDPOINT` is the collector base URL and\n * `OTEL_EXPORTER_OTLP_HEADERS` the headers sent with every export. An unset or\n * empty endpoint installs no exporter at all.\n *\n * @category layers\n * @since 1.0.0\n */\nexport const layerEnvironment = (\n environment: Readonly<Record<string, string | undefined>>,\n options: Omit<Options, \"baseUrl\" | \"headers\"> = {}\n): Layer.Layer<never, LayerError> => {\n const endpoint = environment[\"OTEL_EXPORTER_OTLP_ENDPOINT\"]?.trim()\n if (endpoint === undefined || endpoint === \"\") return layerNoop\n return layerFetch({ ...options, baseUrl: endpoint, headers: parseHeaders(environment[\"OTEL_EXPORTER_OTLP_HEADERS\"]) })\n}\n\n/**\n * Exports nothing. The explicit stand-in for hosts with no collector, such as\n * a development shell, a test, or a browser deployment that has not opted in, so\n * wiring code can switch layers rather than branch.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layerNoop: Layer.Layer<never> = Layer.empty\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBA,gBAA2B;AAC3B,YAAuB;AACvB,mBAAsB;AACtB,qBAAgC;AAEhC,aAAwB;AACxB,WAAsB;AACtB,YAAuB;AACvB,aAAwB;AACxB,aAAwB;AACxB,aAAwB;AACxB,iBAA4B;AAC5B,aAAwB;AACxB,gBAA2B;AAC3B,aAAwB;AACxB,
|
|
4
|
+
"sourcesContent": ["/**\n * Default OTLP export wiring for flows telemetry.\n *\n * The store packages already open spans through Effect's tracer and update\n * `Metric` counters on their hot paths; what they deliberately do not do is\n * ship an exporter. This module is that exporter: one layer that installs\n * Effect's own OTLP logger, metrics exporter, and tracer\n * (`effect/observability/Otlp`) against a collector endpoint, with\n * the flows service identity filled in. Nothing beyond `effect` is involved;\n * no OpenTelemetry SDK dependency.\n *\n * Browser support is met by construction rather than by a no-op variant:\n * export happens over Effect's `HttpClient`, and {@link layerFetch} binds the\n * `fetch` implementation the host already has, so no entry point here ever\n * resolves a `node:` built-in. See the\n * {@link https://smithers.sh/docs/reference/api/observability | observability API contract}.\n *\n * @since 0.1.0\n */\n\nimport * as Redaction from \"@smthrs/journal/Redaction\"\nimport * as Cause from \"effect/Cause\"\nimport { Clock } from \"effect/Clock\"\nimport * as ConfigProvider from \"effect/ConfigProvider\"\nimport type * as Duration from \"effect/Duration\"\nimport * as Effect from \"effect/Effect\"\nimport * as Exit from \"effect/Exit\"\nimport * as FetchHttpClient from \"effect/http/FetchHttpClient\"\nimport * as Headers from \"effect/http/Headers\"\nimport type * as HttpBody from \"effect/http/HttpBody\"\nimport * as HttpClient from \"effect/http/HttpClient\"\nimport type * as HttpClientRequest from \"effect/http/HttpClientRequest\"\nimport * as HttpClientResponse from \"effect/http/HttpClientResponse\"\nimport * as Layer from \"effect/Layer\"\nimport * as Logger from \"effect/Logger\"\nimport * as Metric from \"effect/Metric\"\nimport * as Otlp from \"effect/observability/Otlp\"\nimport * as Option from \"effect/Option\"\nimport * as References from \"effect/References\"\nimport * as Schema from \"effect/Schema\"\nimport * as Semaphore from \"effect/Semaphore\"\nimport * as Tracer from \"effect/Tracer\"\nimport * as Endpoint from \"./Endpoint.ts\"\nimport * as Resource from \"./Resource.ts\"\n\n/**\n * The `service.name` resource attribute installed when the caller supplies\n * none: the flows distribution itself. Override it per application with\n * {@link Options.serviceName}.\n *\n * @category resource\n * @since 0.1.0\n */\nexport const defaultServiceName = \"flows\"\n\n/**\n * The `service.version` resource attribute installed when the caller supplies\n * none. Mirrors the release version in this package's `package.json`.\n *\n * A published package cannot read its own manifest on every runtime it\n * supports, so the version lives here as a literal.\n * `scripts/set-release-version.mjs` rewrites this declaration with the\n * manifests, and its `--check` mode reports drift, so a release bump cannot\n * leave it behind.\n *\n * @category resource\n * @since 0.1.0\n */\nexport const defaultServiceVersion = \"1.0.0-rc.7\"\n\n// The upstream logger and tracer each buffer at most one 1,000-record batch.\n// Do not queue at the transport: upstream forks every full batch independently.\nconst maxBatchSize = 1000\nconst maxInFlight = 4\n/**\n * Maximum encoded export request size, in bytes.\n * @category transport\n * @since 1.0.0-rc.0\n */\nexport const maxRequestBytes = 1024 * 1024\nconst requestTimeout = \"10 seconds\"\nconst diagnosticIntervalMillis = 60_000\n// The envelope around the resource in a metrics request repeats `service.name`\n// as the instrumentation scope name: at most 1,024 code units, at most six\n// bytes each once JSON-escaped, so under 8 KiB together with the envelope's own\n// keys. Log and trace requests name their scope `effect` with the Effect\n// version instead, which is smaller.\n/**\n * Reserved bytes for request wrappers and the escaped instrumentation scope.\n * @category transport\n * @since 1.0.0-rc.0\n */\nexport const maximumEnvelopeBytes = 8 * 1024\n\n/**\n * Bytes of every export request kept free for the signal batch itself.\n *\n * The transport discards a request over 1 MiB, and the resource rides in every\n * request, so the largest resource `Resource.decode` admits\n * (`Resource.maximumResourceBytes`, 128 KiB) and the envelope, which in a\n * metrics request repeats the service name (under 8 KiB), come off the top.\n * The 888 KiB left gives each\n * record of a full 1,000-record logger or tracer batch about 900 bytes, three\n * to four times a bare log record or span, and gives the metrics snapshot room\n * for several thousand series. Every resource the decoder accepts therefore\n * leaves an ordinary batch of any signal exportable; what this reserve does\n * not bound is a single application record or a registry large enough to\n * exceed it on its own.\n *\n * @category transport\n * @since 1.0.0-rc.0\n */\nexport const reservedBatchBytes = maxRequestBytes - Resource.maximumResourceBytes - maximumEnvelopeBytes\n\ntype DiscardReason = \"oversized\" | \"stalled\" | \"saturated\"\n\n/**\n * A collector's answer reduced to what the exporter acts on: its status and\n * its `retry-after` delay, with no body.\n *\n * `Response` refuses a status outside 200 to 599 and a malformed header value.\n * Neither is a collector's answer, so `Response.error()` reports it as status\n * 0, which the exporter fails without retrying. A browser already reports a\n * refused redirect that way.\n */\nconst withoutBody = (response: HttpClientResponse.HttpClientResponse): HttpClientResponse.HttpClientResponse => {\n const retryAfter = response.headers[\"retry-after\"]\n let answer: Response\n try {\n answer = new Response(null, {\n status: response.status,\n headers: retryAfter === undefined ? {} : { \"retry-after\": retryAfter }\n })\n } catch {\n answer = Response.error()\n }\n return HttpClientResponse.fromWeb(response.request, answer)\n}\n\nconst boundedClient = Layer.effect(\n HttpClient.HttpClient,\n Effect.gen(function*() {\n // The exporter reads every response body to its end, after the deadline\n // and the in-flight limit below have let the request go. A collector that\n // never ended its answer would stall that signal and grow the buffered\n // body without bound. So the exchange ends here: the exporter receives the\n // status and retry delay, and closing the scope aborts the transport with\n // the body unread.\n const client = HttpClient.transformResponse(\n HttpClient.withScope(yield* HttpClient.HttpClient),\n (exchange) => exchange.pipe(Effect.map(withoutBody), Effect.scoped)\n )\n const clock = yield* Clock\n // The loggers installed when this transport is acquired. The OTLP logger\n // the same acquisition installs does not exist yet, so a diagnostic pinned\n // to this set cannot enter the exporter it describes, whichever fiber runs\n // the export: the interval and shutdown fibers inherit this set anyway,\n // but a flush requested from application code runs with the application's\n // loggers, which by then include this exporter.\n const ambientLoggers = yield* Effect.withFiber((fiber) => Effect.succeed(fiber.getRef(Logger.CurrentLoggers)))\n const permits = Semaphore.makeUnsafe(maxInFlight)\n // The counter lives with the transport it describes.\n const droppedExports = Metric.counter(\"flows_observability_otlp_dropped\")\n let nextDiagnosticAt = -Infinity\n // A local discard is terminal, so the upstream retry loop must not retain\n // or retry its payload, and the counter records batches, not records. The\n // warning is the diagnostic the counter cannot be: the counter is exported\n // through this same transport and shares every outage with it. One\n // warning per minute keeps a sustained outage from flooding the ambient\n // loggers; the running total in its annotations carries the volume.\n // Replace ambient annotations and log spans to bound the diagnostic itself.\n const discard = (reason: DiscardReason, request: HttpClientRequest.HttpClientRequest, bytes: number) =>\n Metric.update(droppedExports, 1).pipe(\n Effect.andThen(Effect.suspend(() => {\n const now = clock.currentTimeMillisUnsafe()\n if (now < nextDiagnosticAt) return Effect.void\n nextDiagnosticAt = now + diagnosticIntervalMillis\n return Metric.value(droppedExports).pipe(\n Effect.flatMap((dropped) =>\n Effect.logWarning(\"An OTLP export batch was discarded\").pipe(\n Effect.provideService(References.CurrentLogSpans, []),\n Effect.provideService(References.CurrentLogAnnotations, {\n code: \"otlp_export_discarded\",\n reason,\n bytes,\n limit: maxRequestBytes,\n dropped: dropped.count\n })\n )\n ),\n Effect.provideService(Logger.CurrentLoggers, ambientLoggers)\n )\n })),\n Effect.as(HttpClientResponse.fromWeb(request, new Response(null, { status: 204 })))\n )\n return HttpClient.transform(client, (requestEffect, request) =>\n Effect.suspend(() => {\n // layerJson always supplies a Uint8Array body with a byte length.\n const bytes = (request.body as HttpBody.Uint8Array).contentLength\n if (bytes > maxRequestBytes) return discard(\"oversized\", request, bytes)\n // Fetch must expose redirects before any credential or signal body\n // leaves the configured endpoint, even when the caller enables follow.\n const confinedRequest = Effect.flatMap(Effect.serviceOption(FetchHttpClient.RequestInit), (init) =>\n requestEffect.pipe(\n Effect.provideService(FetchHttpClient.RequestInit, {\n ...Option.getOrUndefined(init),\n redirect: \"manual\"\n })\n ))\n return confinedRequest.pipe(\n Effect.timeoutOrElse({\n duration: requestTimeout,\n orElse: () =>\n discard(\"stalled\", request, bytes)\n }),\n permits.withPermitsIfAvailable(1),\n Effect.flatMap(Option.match({\n onNone: () =>\n discard(\"saturated\", request, bytes),\n onSome: Effect.succeed\n }))\n )\n }))\n })\n)\n\nconst loopbackIpv4 = /^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/\n\n/** Whether a decoded endpoint's host never leaves this machine. */\nconst isLoopback = (endpoint: string): boolean => {\n const hostname = new URL(endpoint).hostname\n return hostname === \"localhost\" || hostname === \"[::1]\" || loopbackIpv4.test(hostname)\n}\n\n/**\n * Refuses a credential header bound for a plaintext collector off this\n * machine. Anyone on the network path could read the token from every export\n * request, and the exporter would never report it. Loopback `http://` stays\n * allowed for a local collector or sidecar; non-credential headers such as a\n * tenant id stay allowed on any endpoint.\n */\n/**\n * Vendor credential headers whose names `Redaction.isSensitiveKey` does not\n * recognize. Honeycomb sends its ingest key as `x-honeycomb-team`.\n */\nconst vendorCredentialHeaders: ReadonlySet<string> = new Set([\"x-honeycomb-team\"])\n\nconst isCredentialHeader = (name: string): boolean =>\n Redaction.isSensitiveKey(name) || vendorCredentialHeaders.has(name.toLowerCase())\n\nconst refusePlaintextCredentials = (\n baseUrl: string,\n headers: Headers.Input | undefined\n): Effect.Effect<void, Endpoint.InvalidExporterEndpoint> => {\n if (!baseUrl.toLowerCase().startsWith(\"http:\") || isLoopback(baseUrl)) return Effect.void\n const credential = Object.keys(Headers.fromInput(headers)).some(isCredentialHeader)\n return credential\n ? Effect.fail(\n new Endpoint.InvalidExporterEndpoint({\n code: \"invalid_exporter_endpoint\",\n path: \"baseUrl\",\n message:\n \"OTLP collector baseUrl must use https:// when headers carry credentials, unless it is a loopback address\"\n })\n )\n : Effect.void\n}\n\nconst redactText = (text: string): string => String(Redaction.redact(text))\n\n/**\n * A failed span's error rebuilt with its text redacted. It keeps the original\n * error's `name` and `stack` (redacted) so the collector's exception type and\n * trace stay readable; it is exported to the collector and never thrown.\n */\nclass RedactedSpanError extends Schema.TaggedError<RedactedSpanError>()(\"@smthrs/observability/RedactedSpanError\", {\n message: Schema.String\n}) {}\n\n/**\n * A span failure rendered with credentials removed. The exporter serializes a\n * failed span's cause into its status message and `exception` events, which\n * would otherwise carry any token an error message quoted to the collector.\n */\nconst redactedExit = (exit: Exit.Exit<unknown, unknown>): Exit.Exit<unknown, unknown> => {\n if (exit._tag === \"Success\" || Cause.hasInterruptsOnly(exit.cause)) return exit\n const errors = Cause.prettyErrors(exit.cause, { includeCauseInStack: true }).map((error) => {\n const redacted = new RedactedSpanError({ message: redactText(error.message) })\n Object.defineProperty(redacted, \"name\", { value: redactText(error.name), configurable: true, writable: true })\n // `prettyErrors` always renders a stack.\n redacted.stack = redactText(String(error.stack))\n return redacted\n })\n return Exit.failCause(errors.map(Cause.fail).reduce(Cause.combine, Cause.empty as Cause.Cause<unknown>))\n}\n\n/**\n * Wraps the installed tracer so every exported span's failure and string\n * attributes pass through the journal redaction rules first.\n */\nconst redactedSpans = Layer.effect(Tracer.Tracer)(\n Effect.map(Effect.tracer, (tracer) =>\n Tracer.make({\n ...tracer,\n span(options) {\n const span = tracer.span(options)\n const end = span.end.bind(span)\n const attribute = span.attribute.bind(span)\n span.end = (endTime, exit) => end(endTime, redactedExit(exit))\n span.attribute = (key, value) => attribute(key, typeof value === \"string\" ? redactText(value) : value)\n return span\n }\n }))\n)\n\n/**\n * Configuration for the default OTLP wiring.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface Options {\n /**\n * The collector base URL, for example `http://localhost:4318`. Signals are\n * posted below it at `/v1/logs`, `/v1/metrics`, and `/v1/traces`. It must be\n * an absolute `http://` or `https://` URL without credentials, a query,\n * fragment, backslashes, spaces, or controls. A base path is allowed. Invalid\n * values fail acquisition with {@link Endpoint.InvalidExporterEndpoint}.\n * Use {@link Options.headers} for authentication.\n */\n readonly baseUrl: string\n /** Overrides {@link defaultServiceName} as the `service.name` attribute. */\n readonly serviceName?: string | undefined\n /** Overrides {@link defaultServiceVersion} as the `service.version` attribute. */\n readonly serviceVersion?: string | undefined\n /**\n * Additional resource attributes attached to every exported signal, decoded\n * by `Resource.Attributes`. The whole resource must encode to at most\n * `Resource.maximumResourceBytes`; a larger one fails acquisition with\n * {@link Resource.InvalidResourceConfiguration} rather than making every\n * request oversized.\n */\n readonly attributes?: Record<string, unknown> | undefined\n /**\n * Headers sent with every export request, for example vendor auth. A header\n * whose name names a credential (`authorization`, `x-api-key`, anything\n * `Redaction.isSensitiveKey` recognizes, plus `x-honeycomb-team`) requires\n * an `https://` baseUrl unless the host is loopback; otherwise acquisition\n * fails with\n * {@link Endpoint.InvalidExporterEndpoint}.\n */\n readonly headers?: Headers.Input | undefined\n /** Export cadence for all three signals; each signal's Effect default applies when omitted. */\n readonly exportInterval?: Duration.Input | undefined\n /** Upper bound on the shutdown flush when the layer's scope closes. */\n readonly shutdownTimeout?: Duration.Input | undefined\n}\n\n/**\n * Creates the OTLP logs, metrics, and traces layer with flows resource\n * defaults, JSON-serialized. Exports share a four-request limit with no waiting\n * queue. Requests larger than 1 MiB or stalled for ten seconds are discarded;\n * `flows_observability_otlp_dropped` counts discarded batches, and at most\n * once a minute a `Warn` record with code `otlp_export_discarded` names the\n * reason, the request size, and the running total through the loggers that\n * were installed when the layer was acquired, never through this exporter.\n * A collector's response body is never read: the exporter acts on the status\n * and the `retry-after` header, and the exchange ends when they arrive.\n *\n * **Details**\n *\n * The layer still requires an `HttpClient`, which is how it stays\n * platform-neutral: a Node host may hand it `@effect/platform-node`'s Undici\n * client (re-exported by `@smthrs/platform-node`), a browser or test\n * hands it something else. Use {@link layerFetch} when the host's global\n * `fetch` is good enough. On Node 26 and every browser it is.\n * Fetch redirects are refused. Supply `FetchHttpClient.RequestInit` around\n * the whole exporting effect to retain other fetch options; options scoped\n * only to the supplied client's layer are replaced by the redirect policy.\n * Other HTTP transports must independently refuse automatic redirects.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layer = (\n options: Options\n): Layer.Layer<\n never,\n Resource.InvalidResourceConfiguration | Endpoint.InvalidExporterEndpoint,\n HttpClient.HttpClient\n> =>\n Layer.unwrap(\n Effect.map(\n Effect.all([\n Resource.decode({\n serviceName: options.serviceName ?? defaultServiceName,\n serviceVersion: options.serviceVersion ?? defaultServiceVersion,\n ...(options.attributes === undefined ? {} : { attributes: options.attributes })\n }),\n Endpoint.decode(options.baseUrl, \"baseUrl\").pipe(\n Effect.tap((baseUrl) => refusePlaintextCredentials(baseUrl, options.headers))\n )\n ]),\n ([decoded, baseUrl]) => {\n const resource = Resource.toOpenTelemetryConfiguration(decoded)\n return (\n Otlp.layerJson({\n baseUrl,\n resource: {\n serviceName: resource.serviceName,\n // `serviceVersion` is supplied above before Resource decoding.\n serviceVersion: resource.serviceVersion!,\n ...(resource.attributes === undefined ? {} : { attributes: resource.attributes })\n },\n headers: options.headers,\n maxBatchSize,\n loggerExportInterval: options.exportInterval,\n metricsExportInterval: options.exportInterval,\n tracerExportInterval: options.exportInterval,\n shutdownTimeout: options.shutdownTimeout\n }).pipe(\n Layer.provide(boundedClient),\n // Upstream merges OTEL_RESOURCE_ATTRIBUTES even with explicit\n // options. Keep unvalidated ambient metadata out of every request.\n Layer.provide(ConfigProvider.layer(ConfigProvider.fromUnknown({}))),\n (exporter) => Layer.provideMerge(redactedSpans, exporter)\n )\n )\n }\n )\n )\n\n/**\n * Provides {@link layer} over the host's global `fetch`, the default wiring\n * for a Node host, and browser-safe by construction because it never touches\n * a `node:` built-in.\n *\n * **Example**\n *\n * ```ts\n * import * as Otlp from \"@smthrs/observability/Otlp\"\n *\n * const Telemetry = Otlp.layerFetch({ baseUrl: \"http://localhost:4318\" })\n * ```\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layerFetch = (\n options: Options\n): Layer.Layer<never, Resource.InvalidResourceConfiguration | Endpoint.InvalidExporterEndpoint> =>\n layer(options).pipe(Layer.provide(FetchHttpClient.layer))\n\n/**\n * Why an OTLP layer refused to start.\n *\n * @category errors\n * @since 1.0.0\n */\nexport type LayerError = Resource.InvalidResourceConfiguration | Endpoint.InvalidExporterEndpoint\n\n/**\n * Parses `OTEL_EXPORTER_OTLP_HEADERS`: comma-separated `key=value` pairs whose\n * values are percent-decoded, as the OpenTelemetry exporter specification\n * defines. A pair without `=` or with an empty key is skipped.\n *\n * @category environment\n * @since 1.0.0\n */\nexport const parseHeaders = (value: string | undefined): Record<string, string> => {\n const headers: Record<string, string> = {}\n for (const pair of (value ?? \"\").split(\",\")) {\n const separator = pair.indexOf(\"=\")\n const key = pair.slice(0, separator).trim()\n if (separator < 0 || key === \"\") continue\n const raw = pair.slice(separator + 1).trim()\n let decoded = raw\n try {\n decoded = decodeURIComponent(raw)\n } catch { /* A malformed escape is kept verbatim. */ }\n headers[key] = decoded\n }\n return headers\n}\n\n/**\n * {@link layerFetch} when the environment names a collector, otherwise\n * {@link layerNoop}.\n *\n * `OTEL_EXPORTER_OTLP_ENDPOINT` is the collector base URL and\n * `OTEL_EXPORTER_OTLP_HEADERS` the headers sent with every export. An unset or\n * empty endpoint installs no exporter at all.\n *\n * @category layers\n * @since 1.0.0\n */\nexport const layerEnvironment = (\n environment: Readonly<Record<string, string | undefined>>,\n options: Omit<Options, \"baseUrl\" | \"headers\"> = {}\n): Layer.Layer<never, LayerError> => {\n const endpoint = environment[\"OTEL_EXPORTER_OTLP_ENDPOINT\"]?.trim()\n if (endpoint === undefined || endpoint === \"\") return layerNoop\n return layerFetch({ ...options, baseUrl: endpoint, headers: parseHeaders(environment[\"OTEL_EXPORTER_OTLP_HEADERS\"]) })\n}\n\n/**\n * Exports nothing. The explicit stand-in for hosts with no collector, such as\n * a development shell, a test, or a browser deployment that has not opted in, so\n * wiring code can switch layers rather than branch.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layerNoop: Layer.Layer<never> = Layer.empty\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/cjs/Resource.d.ts
CHANGED
|
@@ -48,11 +48,12 @@ export declare const maximumAttributes = 256;
|
|
|
48
48
|
*
|
|
49
49
|
* The measure is the OTLP `Resource` message the exporters place in every
|
|
50
50
|
* request, `{"attributes":[{"key":…,"value":{…}}],"droppedAttributesCount":0}`
|
|
51
|
-
* with service identity and SDK-added `telemetry.sdk.name
|
|
52
|
-
* `telemetry.sdk.language` included, after JSON
|
|
53
|
-
*
|
|
54
|
-
* exporter
|
|
55
|
-
*
|
|
51
|
+
* with service identity and SDK-added `telemetry.sdk.name`,
|
|
52
|
+
* `telemetry.sdk.language` and `telemetry.sdk.version` included, after JSON
|
|
53
|
+
* escaping and UTF-8 encoding. The SDK's own values are reserved even for the
|
|
54
|
+
* default Effect exporter, whose values are shorter. A caller attribute that
|
|
55
|
+
* replaces an SDK field, or that service identity overwrites, is counted
|
|
56
|
+
* beside it. It is the bound the per-field limits cannot express: 256
|
|
56
57
|
* attributes at the string ceiling would encode to 16 MiB, and the resource
|
|
57
58
|
* rides in every export request, so the default transport, which discards a
|
|
58
59
|
* request over 1 MiB, would deliver nothing at all. 128 KiB admits one
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Resource.d.ts","sourceRoot":"","sources":["../../src/Resource.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,YAAY,MAAM,gCAAgC,CAAA;AAC9D,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACtE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"Resource.d.ts","sourceRoot":"","sources":["../../src/Resource.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,YAAY,MAAM,gCAAgC,CAAA;AAC9D,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACtE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,OAAQ,CAAA;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,OAAQ,CAAA;AAE9C;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,QAAS,CAAA;AAElD;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,MAAM,CAAA;AAE9C;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAA;AAEpC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,oBAAoB,SAAU,CAAA;AAqB3C;;;;;GAKG;AACH,eAAO,MAAM,cAAc,kKAgB1B,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,UAAU,iMAYtB,CAAA;AA0CD;;;;;GAKG;AACH,eAAO,MAAM,aAAa;;;;EAqBzB,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;;;;;;AAErD;;;;;GAKG;AACH,qBAAa,4BAA6B,SAAQ,iCAOjD;CAAG;AAWJ;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GACjB,eAAe,OAAO,KACrB,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,4BAA4B,CAC6B,CAAA;AAEzF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAI,eAAe,OAAO,KAAG,aAMnD,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,GACvC,eAAe,aAAa,KAC3B;IACD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,CAAA;CAcpC,CAAA;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,eAAe,aAAa,KAAG,cACwB,CAAA;AAE1F;;;;;GAKG;AACH,eAAO,MAAM,KAAK,GAChB,eAAe,aAAa,KAC3B,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,4BAA4B,CAG/D,CAAA;AAEH;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,8BAAwB,CAAA"}
|
package/dist/cjs/Resource.js
CHANGED
|
@@ -49,8 +49,8 @@ module.exports = __toCommonJS(Resource_exports);
|
|
|
49
49
|
var OtelResource = __toESM(require("@effect/opentelemetry/Resource"), 1);
|
|
50
50
|
var Effect = __toESM(require("effect/Effect"), 1);
|
|
51
51
|
var Layer = __toESM(require("effect/Layer"), 1);
|
|
52
|
+
var OtlpResource = __toESM(require("effect/observability/OtlpResource"), 1);
|
|
52
53
|
var Schema = __toESM(require("effect/Schema"), 1);
|
|
53
|
-
var OtlpResource = __toESM(require("effect/unstable/observability/OtlpResource"), 1);
|
|
54
54
|
var import_schemaIssuePath = require("./internal/schemaIssuePath.js");
|
|
55
55
|
const maximumIdentityLength = 1024;
|
|
56
56
|
const maximumAttributeKeyLength = 1024;
|
package/dist/cjs/Resource.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Resource.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Explicit, validated OpenTelemetry resource metadata for Smithers.\n *\n * @since 0.1.0\n */\n\nimport * as OtelResource from \"@effect/opentelemetry/Resource\"\nimport type { Attributes as OtelAttributes } from \"@opentelemetry/api\"\nimport * as Effect from \"effect/Effect\"\nimport * as Layer from \"effect/Layer\"\nimport * as Schema from \"effect/Schema\"\nimport * as OtlpResource from \"effect/unstable/observability/OtlpResource\"\nimport { schemaIssueMessage, schemaIssuePath } from \"./internal/schemaIssuePath.ts\"\n\n/**\n * Largest service-name or service-version field accepted by a resource.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const maximumIdentityLength = 1_024\n\n/**\n * Largest attribute key accepted by a resource.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const maximumAttributeKeyLength = 1_024\n\n/**\n * Largest string value accepted by one resource attribute.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const maximumAttributeStringLength = 65_536\n\n/**\n * Largest number of elements accepted in one array attribute value.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const maximumAttributeArrayLength = 256\n\n/**\n * Largest number of attributes accepted by one resource.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const maximumAttributes = 256\n\n/**\n * Largest OTLP/JSON encoding accepted for one whole resource, in UTF-8 bytes.\n *\n * The measure is the OTLP `Resource` message the exporters place in every\n * request, `{\"attributes\":[{\"key\":\u2026,\"value\":{\u2026}}],\"droppedAttributesCount\":0}`\n * with service identity and SDK-added `telemetry.sdk.name` and\n * `telemetry.sdk.language` included, after JSON escaping and UTF-8 encoding.\n * These SDK fields are conservatively reserved even for the default Effect\n * exporter. Caller attributes overwritten by SDK identity or metadata are\n * still counted. It is the bound the per-field limits cannot express: 256\n * attributes at the string ceiling would encode to 16 MiB, and the resource\n * rides in every export request, so the default transport, which discards a\n * request over 1 MiB, would deliver nothing at all. 128 KiB admits one\n * ASCII attribute at the string ceiling and leaves that transport 888 KiB of every\n * request for the signal batch; see `Otlp.reservedBatchBytes`.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const maximumResourceBytes = 131_072\n\nconst loneSurrogate = /[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]/\nconst embeddedNul = new RegExp(String.fromCharCode(0))\n\nconst isWellFormed = (value: string): boolean => !loneSurrogate.test(value) && !embeddedNul.test(value)\n\nconst identity = Schema.NonEmptyString.check(\n Schema.isMaxLength(maximumIdentityLength),\n Schema.makeFilter((value: string) => isWellFormed(value), { title: \"wellFormedResourceIdentity\" })\n)\n\nconst attributeString = Schema.String.check(\n Schema.isMaxLength(maximumAttributeStringLength),\n Schema.makeFilter((value: string) => isWellFormed(value), { title: \"wellFormedAttributeString\" })\n)\n\nconst attributeNumber = Schema.Number.check(\n Schema.makeFilter((value: number) => Number.isFinite(value), { title: \"finiteAttributeNumber\" })\n)\n\n/**\n * Runtime schema for one OpenTelemetry resource attribute value.\n *\n * @category schemas\n * @since 1.0.0-rc.0\n */\nexport const AttributeValue = Schema.Union([\n attributeString,\n attributeNumber,\n Schema.Boolean,\n Schema.Array(attributeString),\n Schema.Array(attributeNumber),\n Schema.Array(Schema.Boolean)\n]).check(\n Schema.makeFilter(\n (value) =>\n !Array.isArray(value) || value.length <= maximumAttributeArrayLength || {\n path: [],\n issue: `holds ${value.length} elements, over the ${maximumAttributeArrayLength} element limit`\n },\n { title: \"boundedResourceAttributeArrays\" }\n )\n)\n\n/**\n * Runtime schema for OpenTelemetry resource attributes.\n *\n * @category schemas\n * @since 1.0.0-rc.0\n */\nexport const Attributes = Schema.Record(Schema.String, AttributeValue).check(\n Schema.makeFilter(\n (attributes: Readonly<Record<string, unknown>>) => Object.keys(attributes).length <= maximumAttributes,\n { title: \"boundedResourceAttributes\" }\n ),\n Schema.makeFilter(\n (attributes: Readonly<Record<string, unknown>>) =>\n Object.keys(attributes).every(\n (key) => key.length > 0 && key.length <= maximumAttributeKeyLength && isWellFormed(key)\n ),\n { title: \"wellFormedResourceAttributeKeys\" }\n )\n)\n\nconst encoder = new TextEncoder()\n\n/**\n * Counts OTLP JSON fragments, including keys, wrappers, escaping and UTF-8.\n * Stops at the first fragment over budget: the refusal reports a lower bound.\n * A configuration may reuse one large string in thousands of array slots, so\n * serializing the whole resource before checking could allocate gigabytes.\n */\nconst encodedResourceBytes = (configuration: {\n readonly serviceName: string\n readonly serviceVersion?: string | undefined\n readonly attributes?: Record<string, unknown> | undefined\n}): number => {\n const bytes = (value: unknown) => encoder.encode(JSON.stringify(value)).byteLength\n const identityAttributes = OtelResource.configToAttributes({\n serviceName: configuration.serviceName,\n ...(configuration.serviceVersion === undefined ? {} : { serviceVersion: configuration.serviceVersion })\n })\n // Use the pinned SDK projection so its added metadata cannot escape the\n // complete-resource ceiling. Both exporters use these OTLP AnyValue shapes.\n let total = bytes({\n attributes: OtlpResource.entriesToAttributes(Object.entries(identityAttributes)),\n droppedAttributesCount: 0\n })\n for (const [key, value] of Object.entries(configuration.attributes ?? {})) {\n // An identity attribute is always present, so every addition needs a comma.\n total += 1 + bytes({ key, value: Array.isArray(value) ? { arrayValue: { values: [] } } : null })\n if (Array.isArray(value)) {\n for (const [index, element] of value.entries()) {\n total += (index === 0 ? 0 : 1) + bytes(OtlpResource.unknownToAttributeValue(element))\n if (total > maximumResourceBytes) return total\n }\n } else {\n total += bytes(OtlpResource.unknownToAttributeValue(value)) - 4 // replace JSON null\n }\n if (total > maximumResourceBytes) return total\n }\n return total\n}\n\n/**\n * Runtime schema for the service identity attached to exported telemetry.\n *\n * @category schemas\n * @since 1.0.0-rc.0\n */\nexport const Configuration = Schema.Struct({\n serviceName: identity,\n serviceVersion: Schema.optional(identity),\n attributes: Schema.optional(Attributes)\n}).check(\n Schema.makeFilter(\n (configuration: {\n readonly serviceName: string\n readonly serviceVersion?: string | undefined\n readonly attributes?: Record<string, unknown> | undefined\n }) => {\n const bytes = encodedResourceBytes(configuration)\n // Only attributes can carry a resource past the budget: the two identity\n // fields encode to at most 6 KiB each, so the refusal points there.\n return bytes <= maximumResourceBytes || {\n path: [\"attributes\"],\n issue: `bring the resource to at least ${bytes} bytes of OTLP JSON, over the ${maximumResourceBytes} byte limit`\n }\n },\n { title: \"boundedResourceBytes\" }\n )\n)\n\n/**\n * Configuration used to identify the service emitting telemetry.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport type Configuration = typeof Configuration.Type\n\n/**\n * Stable resource-configuration refusal shared by every OTEL layer.\n *\n * @category errors\n * @since 1.0.0-rc.0\n */\nexport class InvalidResourceConfiguration extends Schema.TaggedError<InvalidResourceConfiguration>()(\n \"@smthrs/observability/InvalidResourceConfiguration\",\n {\n code: Schema.Literal(\"invalid_resource_configuration\"),\n path: Schema.String,\n message: Schema.String\n }\n) {}\n\nconst invalid = (cause: unknown): InvalidResourceConfiguration => {\n const path = schemaIssuePath(cause, \"resource\")\n return new InvalidResourceConfiguration({\n code: \"invalid_resource_configuration\",\n path,\n message: `OpenTelemetry resource ${path} ${schemaIssueMessage(cause) ?? \"is invalid\"}`\n })\n}\n\n/**\n * Decodes one resource configuration without retaining rejected values.\n *\n * @category decoding\n * @since 1.0.0-rc.0\n */\nexport const decode = (\n configuration: unknown\n): Effect.Effect<Configuration, InvalidResourceConfiguration> =>\n Schema.decodeUnknownEffect(Configuration)(configuration).pipe(Effect.mapError(invalid))\n\n/**\n * Decodes one resource configuration for the package's pure projection API.\n *\n * @category decoding\n * @since 1.0.0-rc.0\n */\nexport const decodeSync = (configuration: unknown): Configuration => {\n try {\n return Schema.decodeUnknownSync(Configuration)(configuration)\n } catch (cause) {\n throw invalid(cause)\n }\n}\n\n/**\n * Projects a decoded resource into the exact optional-property shape expected\n * by the OpenTelemetry SDK.\n *\n * @category conversions\n * @since 1.0.0-rc.0\n */\nexport const toOpenTelemetryConfiguration = (\n configuration: Configuration\n): {\n readonly serviceName: string\n readonly serviceVersion?: string\n readonly attributes?: OtelAttributes\n} => ({\n serviceName: configuration.serviceName,\n ...(configuration.serviceVersion === undefined ? {} : { serviceVersion: configuration.serviceVersion }),\n ...(configuration.attributes === undefined\n ? {}\n : {\n attributes: Object.fromEntries(\n Object.entries(configuration.attributes).map(([key, value]) => [\n key,\n Array.isArray(value) ? [...value] : value\n ])\n ) as OtelAttributes\n })\n})\n\n/**\n * Converts explicit service metadata into OpenTelemetry resource attributes.\n *\n * No environment variables are read. Invalid metadata throws the same typed\n * {@link InvalidResourceConfiguration} every layer returns during acquisition.\n *\n * @category conversions\n * @since 1.0.0-rc.0\n */\nexport const configToAttributes = (configuration: Configuration): OtelAttributes =>\n OtelResource.configToAttributes(toOpenTelemetryConfiguration(decodeSync(configuration)))\n\n/**\n * Provides an explicitly validated OpenTelemetry resource.\n *\n * @category layers\n * @since 1.0.0-rc.0\n */\nexport const layer = (\n configuration: Configuration\n): Layer.Layer<OtelResource.Resource, InvalidResourceConfiguration> =>\n Layer.unwrap(\n Effect.map(decode(configuration), (decoded) => OtelResource.layer(toOpenTelemetryConfiguration(decoded)))\n )\n\n/**\n * The OpenTelemetry resource service.\n *\n * @category services\n * @since 1.0.0-rc.0\n */\nexport const Resource = OtelResource.Resource\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,mBAA8B;AAE9B,aAAwB;AACxB,YAAuB;AACvB,aAAwB;AACxB,
|
|
4
|
+
"sourcesContent": ["/**\n * Explicit, validated OpenTelemetry resource metadata for Smithers.\n *\n * @since 0.1.0\n */\n\nimport * as OtelResource from \"@effect/opentelemetry/Resource\"\nimport type { Attributes as OtelAttributes } from \"@opentelemetry/api\"\nimport * as Effect from \"effect/Effect\"\nimport * as Layer from \"effect/Layer\"\nimport * as OtlpResource from \"effect/observability/OtlpResource\"\nimport * as Schema from \"effect/Schema\"\nimport { schemaIssueMessage, schemaIssuePath } from \"./internal/schemaIssuePath.ts\"\n\n/**\n * Largest service-name or service-version field accepted by a resource.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const maximumIdentityLength = 1_024\n\n/**\n * Largest attribute key accepted by a resource.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const maximumAttributeKeyLength = 1_024\n\n/**\n * Largest string value accepted by one resource attribute.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const maximumAttributeStringLength = 65_536\n\n/**\n * Largest number of elements accepted in one array attribute value.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const maximumAttributeArrayLength = 256\n\n/**\n * Largest number of attributes accepted by one resource.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const maximumAttributes = 256\n\n/**\n * Largest OTLP/JSON encoding accepted for one whole resource, in UTF-8 bytes.\n *\n * The measure is the OTLP `Resource` message the exporters place in every\n * request, `{\"attributes\":[{\"key\":\u2026,\"value\":{\u2026}}],\"droppedAttributesCount\":0}`\n * with service identity and SDK-added `telemetry.sdk.name`,\n * `telemetry.sdk.language` and `telemetry.sdk.version` included, after JSON\n * escaping and UTF-8 encoding. The SDK's own values are reserved even for the\n * default Effect exporter, whose values are shorter. A caller attribute that\n * replaces an SDK field, or that service identity overwrites, is counted\n * beside it. It is the bound the per-field limits cannot express: 256\n * attributes at the string ceiling would encode to 16 MiB, and the resource\n * rides in every export request, so the default transport, which discards a\n * request over 1 MiB, would deliver nothing at all. 128 KiB admits one\n * ASCII attribute at the string ceiling and leaves that transport 888 KiB of every\n * request for the signal batch; see `Otlp.reservedBatchBytes`.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const maximumResourceBytes = 131_072\n\nconst loneSurrogate = /[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]/\nconst embeddedNul = new RegExp(String.fromCharCode(0))\n\nconst isWellFormed = (value: string): boolean => !loneSurrogate.test(value) && !embeddedNul.test(value)\n\nconst identity = Schema.NonEmptyString.check(\n Schema.isMaxLength(maximumIdentityLength),\n Schema.makeFilter((value: string) => isWellFormed(value), { title: \"wellFormedResourceIdentity\" })\n)\n\nconst attributeString = Schema.String.check(\n Schema.isMaxLength(maximumAttributeStringLength),\n Schema.makeFilter((value: string) => isWellFormed(value), { title: \"wellFormedAttributeString\" })\n)\n\nconst attributeNumber = Schema.Number.check(\n Schema.makeFilter((value: number) => Number.isFinite(value), { title: \"finiteAttributeNumber\" })\n)\n\n/**\n * Runtime schema for one OpenTelemetry resource attribute value.\n *\n * @category schemas\n * @since 1.0.0-rc.0\n */\nexport const AttributeValue = Schema.Union([\n attributeString,\n attributeNumber,\n Schema.Boolean,\n Schema.Array(attributeString),\n Schema.Array(attributeNumber),\n Schema.Array(Schema.Boolean)\n]).check(\n Schema.makeFilter(\n (value) =>\n !Array.isArray(value) || value.length <= maximumAttributeArrayLength || {\n path: [],\n issue: `holds ${value.length} elements, over the ${maximumAttributeArrayLength} element limit`\n },\n { title: \"boundedResourceAttributeArrays\" }\n )\n)\n\n/**\n * Runtime schema for OpenTelemetry resource attributes.\n *\n * @category schemas\n * @since 1.0.0-rc.0\n */\nexport const Attributes = Schema.Record(Schema.String, AttributeValue).check(\n Schema.makeFilter(\n (attributes: Readonly<Record<string, unknown>>) => Object.keys(attributes).length <= maximumAttributes,\n { title: \"boundedResourceAttributes\" }\n ),\n Schema.makeFilter(\n (attributes: Readonly<Record<string, unknown>>) =>\n Object.keys(attributes).every(\n (key) => key.length > 0 && key.length <= maximumAttributeKeyLength && isWellFormed(key)\n ),\n { title: \"wellFormedResourceAttributeKeys\" }\n )\n)\n\nconst encoder = new TextEncoder()\n\n/**\n * Counts OTLP JSON fragments, including keys, wrappers, escaping and UTF-8.\n * Stops at the first fragment over budget: the refusal reports a lower bound.\n * A configuration may reuse one large string in thousands of array slots, so\n * serializing the whole resource before checking could allocate gigabytes.\n */\nconst encodedResourceBytes = (configuration: {\n readonly serviceName: string\n readonly serviceVersion?: string | undefined\n readonly attributes?: Record<string, unknown> | undefined\n}): number => {\n const bytes = (value: unknown) => encoder.encode(JSON.stringify(value)).byteLength\n const identityAttributes = OtelResource.configToAttributes({\n serviceName: configuration.serviceName,\n ...(configuration.serviceVersion === undefined ? {} : { serviceVersion: configuration.serviceVersion })\n })\n // Use the pinned SDK projection so its added metadata cannot escape the\n // complete-resource ceiling. Both exporters use these OTLP AnyValue shapes.\n let total = bytes({\n attributes: OtlpResource.entriesToAttributes(Object.entries(identityAttributes)),\n droppedAttributesCount: 0\n })\n for (const [key, value] of Object.entries(configuration.attributes ?? {})) {\n // An identity attribute is always present, so every addition needs a comma.\n total += 1 + bytes({ key, value: Array.isArray(value) ? { arrayValue: { values: [] } } : null })\n if (Array.isArray(value)) {\n for (const [index, element] of value.entries()) {\n total += (index === 0 ? 0 : 1) + bytes(OtlpResource.unknownToAttributeValue(element))\n if (total > maximumResourceBytes) return total\n }\n } else {\n total += bytes(OtlpResource.unknownToAttributeValue(value)) - 4 // replace JSON null\n }\n if (total > maximumResourceBytes) return total\n }\n return total\n}\n\n/**\n * Runtime schema for the service identity attached to exported telemetry.\n *\n * @category schemas\n * @since 1.0.0-rc.0\n */\nexport const Configuration = Schema.Struct({\n serviceName: identity,\n serviceVersion: Schema.optional(identity),\n attributes: Schema.optional(Attributes)\n}).check(\n Schema.makeFilter(\n (configuration: {\n readonly serviceName: string\n readonly serviceVersion?: string | undefined\n readonly attributes?: Record<string, unknown> | undefined\n }) => {\n const bytes = encodedResourceBytes(configuration)\n // Only attributes can carry a resource past the budget: the two identity\n // fields encode to at most 6 KiB each, so the refusal points there.\n return bytes <= maximumResourceBytes || {\n path: [\"attributes\"],\n issue: `bring the resource to at least ${bytes} bytes of OTLP JSON, over the ${maximumResourceBytes} byte limit`\n }\n },\n { title: \"boundedResourceBytes\" }\n )\n)\n\n/**\n * Configuration used to identify the service emitting telemetry.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport type Configuration = typeof Configuration.Type\n\n/**\n * Stable resource-configuration refusal shared by every OTEL layer.\n *\n * @category errors\n * @since 1.0.0-rc.0\n */\nexport class InvalidResourceConfiguration extends Schema.TaggedError<InvalidResourceConfiguration>()(\n \"@smthrs/observability/InvalidResourceConfiguration\",\n {\n code: Schema.Literal(\"invalid_resource_configuration\"),\n path: Schema.String,\n message: Schema.String\n }\n) {}\n\nconst invalid = (cause: unknown): InvalidResourceConfiguration => {\n const path = schemaIssuePath(cause, \"resource\")\n return new InvalidResourceConfiguration({\n code: \"invalid_resource_configuration\",\n path,\n message: `OpenTelemetry resource ${path} ${schemaIssueMessage(cause) ?? \"is invalid\"}`\n })\n}\n\n/**\n * Decodes one resource configuration without retaining rejected values.\n *\n * @category decoding\n * @since 1.0.0-rc.0\n */\nexport const decode = (\n configuration: unknown\n): Effect.Effect<Configuration, InvalidResourceConfiguration> =>\n Schema.decodeUnknownEffect(Configuration)(configuration).pipe(Effect.mapError(invalid))\n\n/**\n * Decodes one resource configuration for the package's pure projection API.\n *\n * @category decoding\n * @since 1.0.0-rc.0\n */\nexport const decodeSync = (configuration: unknown): Configuration => {\n try {\n return Schema.decodeUnknownSync(Configuration)(configuration)\n } catch (cause) {\n throw invalid(cause)\n }\n}\n\n/**\n * Projects a decoded resource into the exact optional-property shape expected\n * by the OpenTelemetry SDK.\n *\n * @category conversions\n * @since 1.0.0-rc.0\n */\nexport const toOpenTelemetryConfiguration = (\n configuration: Configuration\n): {\n readonly serviceName: string\n readonly serviceVersion?: string\n readonly attributes?: OtelAttributes\n} => ({\n serviceName: configuration.serviceName,\n ...(configuration.serviceVersion === undefined ? {} : { serviceVersion: configuration.serviceVersion }),\n ...(configuration.attributes === undefined\n ? {}\n : {\n attributes: Object.fromEntries(\n Object.entries(configuration.attributes).map(([key, value]) => [\n key,\n Array.isArray(value) ? [...value] : value\n ])\n ) as OtelAttributes\n })\n})\n\n/**\n * Converts explicit service metadata into OpenTelemetry resource attributes.\n *\n * No environment variables are read. Invalid metadata throws the same typed\n * {@link InvalidResourceConfiguration} every layer returns during acquisition.\n *\n * @category conversions\n * @since 1.0.0-rc.0\n */\nexport const configToAttributes = (configuration: Configuration): OtelAttributes =>\n OtelResource.configToAttributes(toOpenTelemetryConfiguration(decodeSync(configuration)))\n\n/**\n * Provides an explicitly validated OpenTelemetry resource.\n *\n * @category layers\n * @since 1.0.0-rc.0\n */\nexport const layer = (\n configuration: Configuration\n): Layer.Layer<OtelResource.Resource, InvalidResourceConfiguration> =>\n Layer.unwrap(\n Effect.map(decode(configuration), (decoded) => OtelResource.layer(toOpenTelemetryConfiguration(decoded)))\n )\n\n/**\n * The OpenTelemetry resource service.\n *\n * @category services\n * @since 1.0.0-rc.0\n */\nexport const Resource = OtelResource.Resource\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/esm/Otel.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { type Configuration as ResourceConfiguration, type InvalidResourceConfig
|
|
|
16
16
|
* @since 0.1.0
|
|
17
17
|
*/
|
|
18
18
|
export interface Options {
|
|
19
|
-
/** Validated resource for metrics
|
|
19
|
+
/** Validated resource for metrics and provider factories. */
|
|
20
20
|
readonly resource: ResourceConfiguration;
|
|
21
21
|
/**
|
|
22
22
|
* Borrowed: the layer bridges onto this provider and never flushes or shuts
|
|
@@ -43,7 +43,8 @@ export interface Options {
|
|
|
43
43
|
* layer acquires. Factories run during layer acquisition after resource
|
|
44
44
|
* validation, and the provider factories receive the metric resource.
|
|
45
45
|
* Already-created providers keep the resource captured at construction; the
|
|
46
|
-
* resource option only sets
|
|
46
|
+
* resource option only sets the metric resource for them. Spans and log
|
|
47
|
+
* records carry the instrumentation scope `effect` with the Effect version.
|
|
47
48
|
* Ownership splits: callers own provider flushing and shutdown, including
|
|
48
49
|
* factory-built providers, while the layer scope shuts down every reader the
|
|
49
50
|
* `metricReader` factory returned. No exporter is allocated by this module.
|
package/dist/esm/Otel.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Otel.d.ts","sourceRoot":"","sources":["../../src/Otel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,WAAW,MAAM,mCAAmC,CAAA;AAEhE,OAAO,KAAK,KAAK,GAAG,MAAM,oBAAoB,CAAA;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAE9D,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,EACL,KAAK,aAAa,IAAI,qBAAqB,EAC3C,KAAK,4BAA4B,EAEjC,QAAQ,EACT,MAAM,eAAe,CAAA;AAEtB;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,
|
|
1
|
+
{"version":3,"file":"Otel.d.ts","sourceRoot":"","sources":["../../src/Otel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,WAAW,MAAM,mCAAmC,CAAA;AAEhE,OAAO,KAAK,KAAK,GAAG,MAAM,oBAAoB,CAAA;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAE9D,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,EACL,KAAK,aAAa,IAAI,qBAAqB,EAC3C,KAAK,4BAA4B,EAEjC,QAAQ,EACT,MAAM,eAAe,CAAA;AAEtB;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAA;IACxC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EACpB,GAAG,CAAC,cAAc,GAClB,CAAC,CAAC,QAAQ,EAAE,OAAO,QAAQ,CAAC,OAAO,KAAK,GAAG,CAAC,cAAc,CAAC,GAC3D,SAAS,CAAA;IACb,sDAAsD;IACtD,QAAQ,CAAC,cAAc,CAAC,EACpB,cAAc,GACd,CAAC,CAAC,QAAQ,EAAE,OAAO,QAAQ,CAAC,OAAO,KAAK,cAAc,CAAC,GACvD,SAAS,CAAA;IACb;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC,GAAG,SAAS,CAAA;IACtF,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IACtD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,WAAW,CAAC,qBAAqB,GAAG,SAAS,CAAA;CAC3E;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS,GAAI,SAAS,OAAO,KAAG,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,4BAA4B,CAsC3F,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAe,CAAA"}
|
package/dist/esm/Otel.js
CHANGED
|
@@ -15,7 +15,8 @@ import { layer as resourceLayer, Resource } from "./Resource.js";
|
|
|
15
15
|
* layer acquires. Factories run during layer acquisition after resource
|
|
16
16
|
* validation, and the provider factories receive the metric resource.
|
|
17
17
|
* Already-created providers keep the resource captured at construction; the
|
|
18
|
-
* resource option only sets
|
|
18
|
+
* resource option only sets the metric resource for them. Spans and log
|
|
19
|
+
* records carry the instrumentation scope `effect` with the Effect version.
|
|
19
20
|
* Ownership splits: callers own provider flushing and shutdown, including
|
|
20
21
|
* factory-built providers, while the layer scope shuts down every reader the
|
|
21
22
|
* `metricReader` factory returned. No exporter is allocated by this module.
|
package/dist/esm/Otel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Otel.js","sourceRoot":"","sources":["../../src/Otel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,UAAU,MAAM,kCAAkC,CAAA;AAC9D,OAAO,KAAK,WAAW,MAAM,mCAAmC,CAAA;AAChE,OAAO,KAAK,UAAU,MAAM,kCAAkC,CAAA;AAI9D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,EAGL,KAAK,IAAI,aAAa,EACtB,QAAQ,EACT,MAAM,eAAe,CAAA;AAqCtB
|
|
1
|
+
{"version":3,"file":"Otel.js","sourceRoot":"","sources":["../../src/Otel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,UAAU,MAAM,kCAAkC,CAAA;AAC9D,OAAO,KAAK,WAAW,MAAM,mCAAmC,CAAA;AAChE,OAAO,KAAK,UAAU,MAAM,kCAAkC,CAAA;AAI9D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,EAGL,KAAK,IAAI,aAAa,EACtB,QAAQ,EACT,MAAM,eAAe,CAAA;AAqCtB;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAAgB,EAAoD,EAAE;IAC9F,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAChD,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAA;IAC7C,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAA;IAC7C,MAAM,MAAM,GAAG,cAAc,KAAK,SAAS;QACzC,CAAC,CAAC,KAAK,CAAC,KAAK;QACb,CAAC,CAAC,KAAK,CAAC,OAAO,CACb,UAAU,CAAC,KAAK,EAChB,KAAK,CAAC,MAAM,CACV,UAAU,CAAC,kBAAkB,EAC7B,MAAM,CAAC,GAAG,CACR,QAAQ,EACR,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,cAAc,KAAK,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,cAAc,CAC/F,CACF,CACF,CAAA;IACH,MAAM,MAAM,GAAG,cAAc,KAAK,SAAS;QACzC,CAAC,CAAC,KAAK,CAAC,KAAK;QACb,CAAC,CAAC,KAAK,CAAC,OAAO,CACb,UAAU,CAAC,KAAK,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,uBAAuB,EAAE,CAAC,EACxE,KAAK,CAAC,MAAM,CACV,UAAU,CAAC,kBAAkB,EAC7B,MAAM,CAAC,GAAG,CACR,QAAQ,EACR,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,cAAc,KAAK,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,cAAc,CAC/F,CACF,CACF,CAAA;IACH,MAAM,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAA;IAChD,MAAM,OAAO,GAAG,mBAAmB,KAAK,SAAS;QAC/C,CAAC,CAAC,KAAK,CAAC,KAAK;QACb,CAAC,CAAC,WAAW,CAAC,KAAK,CACjB,GAAG,EAAE,CAAC,mBAAmB,EAA+E,EACxG;YACE,WAAW,EAAE,OAAO,CAAC,iBAAiB;SACvC,CACF,CAAA;IACH,OAAO,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAA;AACnF,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAuB,KAAK,CAAC,KAAK,CAAA"}
|
package/dist/esm/Otlp.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `Metric` counters on their hot paths; what they deliberately do not do is
|
|
6
6
|
* ship an exporter. This module is that exporter: one layer that installs
|
|
7
7
|
* Effect's own OTLP logger, metrics exporter, and tracer
|
|
8
|
-
* (`effect/
|
|
8
|
+
* (`effect/observability/Otlp`) against a collector endpoint, with
|
|
9
9
|
* the flows service identity filled in. Nothing beyond `effect` is involved;
|
|
10
10
|
* no OpenTelemetry SDK dependency.
|
|
11
11
|
*
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
* @since 0.1.0
|
|
19
19
|
*/
|
|
20
20
|
import type * as Duration from "effect/Duration";
|
|
21
|
+
import * as Headers from "effect/http/Headers";
|
|
22
|
+
import * as HttpClient from "effect/http/HttpClient";
|
|
21
23
|
import * as Layer from "effect/Layer";
|
|
22
|
-
import * as Headers from "effect/unstable/http/Headers";
|
|
23
|
-
import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
24
24
|
import * as Endpoint from "./Endpoint.ts";
|
|
25
25
|
import * as Resource from "./Resource.ts";
|
|
26
26
|
/**
|
|
@@ -45,7 +45,7 @@ export declare const defaultServiceName = "flows";
|
|
|
45
45
|
* @category resource
|
|
46
46
|
* @since 0.1.0
|
|
47
47
|
*/
|
|
48
|
-
export declare const defaultServiceVersion = "1.0.0-rc.
|
|
48
|
+
export declare const defaultServiceVersion = "1.0.0-rc.7";
|
|
49
49
|
/**
|
|
50
50
|
* Maximum encoded export request size, in bytes.
|
|
51
51
|
* @category transport
|
|
@@ -63,8 +63,9 @@ export declare const maximumEnvelopeBytes: number;
|
|
|
63
63
|
*
|
|
64
64
|
* The transport discards a request over 1 MiB, and the resource rides in every
|
|
65
65
|
* request, so the largest resource `Resource.decode` admits
|
|
66
|
-
* (`Resource.maximumResourceBytes`, 128 KiB) and the envelope
|
|
67
|
-
* service name (under 8 KiB) come off the top.
|
|
66
|
+
* (`Resource.maximumResourceBytes`, 128 KiB) and the envelope, which in a
|
|
67
|
+
* metrics request repeats the service name (under 8 KiB), come off the top.
|
|
68
|
+
* The 888 KiB left gives each
|
|
68
69
|
* record of a full 1,000-record logger or tracer batch about 900 bytes, three
|
|
69
70
|
* to four times a bare log record or span, and gives the metrics snapshot room
|
|
70
71
|
* for several thousand series. Every resource the decoder accepts therefore
|
|
@@ -126,6 +127,8 @@ export interface Options {
|
|
|
126
127
|
* once a minute a `Warn` record with code `otlp_export_discarded` names the
|
|
127
128
|
* reason, the request size, and the running total through the loggers that
|
|
128
129
|
* were installed when the layer was acquired, never through this exporter.
|
|
130
|
+
* A collector's response body is never read: the exporter acts on the status
|
|
131
|
+
* and the `retry-after` header, and the exchange ends when they arrive.
|
|
129
132
|
*
|
|
130
133
|
* **Details**
|
|
131
134
|
*
|
package/dist/esm/Otlp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Otlp.d.ts","sourceRoot":"","sources":["../../src/Otlp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"Otlp.d.ts","sourceRoot":"","sources":["../../src/Otlp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAIhD,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAA;AAE9C,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAA;AAGpD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AASrC,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AACzC,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AAEzC;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,UAAU,CAAA;AAEzC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,eAAe,CAAA;AAMjD;;;;GAIG;AACH,eAAO,MAAM,eAAe,QAAc,CAAA;AAQ1C;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,QAAW,CAAA;AAE5C;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,QAAyE,CAAA;AA2MxG;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzC,kFAAkF;IAClF,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5C;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;IACzD;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,KAAK,GAAG,SAAS,CAAA;IAC5C,+FAA+F;IAC/F,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,KAAK,GAAG,SAAS,CAAA;IACpD,uEAAuE;IACvE,QAAQ,CAAC,eAAe,CAAC,EAAE,QAAQ,CAAC,KAAK,GAAG,SAAS,CAAA;CACtD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,KAAK,GAChB,SAAS,OAAO,KACf,KAAK,CAAC,KAAK,CACZ,KAAK,EACL,QAAQ,CAAC,4BAA4B,GAAG,QAAQ,CAAC,uBAAuB,EACxE,UAAU,CAAC,UAAU,CAyCpB,CAAA;AAEH;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,UAAU,GACrB,SAAS,OAAO,KACf,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,4BAA4B,GAAG,QAAQ,CAAC,uBAAuB,CACnC,CAAA;AAE3D;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,4BAA4B,GAAG,QAAQ,CAAC,uBAAuB,CAAA;AAEjG;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,GAAG,SAAS,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAc7E,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,GAC3B,aAAa,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EACzD,UAAS,IAAI,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,CAAM,KACjD,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,CAI/B,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAe,CAAA"}
|