@foam-ai/node 0.1.0-alpha.12 → 0.1.0-alpha.13
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 +73 -21
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -1
- package/dist/init.d.ts +1 -0
- package/dist/init.js +23 -27
- package/dist/lifecycle.d.ts +6 -0
- package/dist/lifecycle.js +53 -0
- package/dist/state.d.ts +1 -0
- package/dist/state.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -131,6 +131,7 @@ init({
|
|
|
131
131
|
additionalResourceAttributes?,
|
|
132
132
|
disableLogSending?,
|
|
133
133
|
networkCapture?,
|
|
134
|
+
dbCapture?,
|
|
134
135
|
ignoredOutboundHosts?,
|
|
135
136
|
redact?,
|
|
136
137
|
beforeSend?,
|
|
@@ -167,6 +168,14 @@ log records is unaffected (see Loggers).
|
|
|
167
168
|
`networkCapture` defaults to `"basic"`. Upgrade to `"advanced"` unless you
|
|
168
169
|
cannot; it gives much more powerful HTTP and Undici capture. See Network capture.
|
|
169
170
|
|
|
171
|
+
`dbCapture` defaults to `false` and is accepted but not used yet. It will
|
|
172
|
+
gate database query and result capture from the driver instrumentations
|
|
173
|
+
(statements, row counts, and result payloads where drivers expose them).
|
|
174
|
+
See the TODO on expanded data capture at the end of this document.
|
|
175
|
+
|
|
176
|
+
TODO(pcga11): Wire dbCapture into the driver instrumentations
|
|
177
|
+
(responseHook/requestHook per driver, opt-in result capture).
|
|
178
|
+
|
|
170
179
|
`redact` adds keys to Foam's built-in redaction. `secrets` preserves the last
|
|
171
180
|
four characters of longer values; `pii` fully masks values.
|
|
172
181
|
|
|
@@ -211,6 +220,48 @@ TODO(pcga11): Add other common Gen AI providers.
|
|
|
211
220
|
If another SDK already registered traces, metrics, logs, or the propagator,
|
|
212
221
|
`init()` leaves the signal's slot untouched and only takes what is available. When a slot is taken, use its ingest helper instead.
|
|
213
222
|
|
|
223
|
+
### `flush()`
|
|
224
|
+
|
|
225
|
+
Exports all buffered telemetry (spans, metrics, and logs sitting in
|
|
226
|
+
Foam's batch processors) and resolves when the export settles. The SDK
|
|
227
|
+
keeps running.
|
|
228
|
+
|
|
229
|
+
Use it before a step that may end the process abruptly, or in short-lived
|
|
230
|
+
processes (jobs, scripts, serverless handlers) where waiting for the batch
|
|
231
|
+
interval would lose the final window of telemetry.
|
|
232
|
+
|
|
233
|
+
```js
|
|
234
|
+
import { flush } from "@foam-ai/node";
|
|
235
|
+
|
|
236
|
+
await flush();
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
It never rejects: per-provider export failures are swallowed, matching the
|
|
240
|
+
SDK's fail-open behavior everywhere else. Calling it before `init()` is a
|
|
241
|
+
no-op.
|
|
242
|
+
|
|
243
|
+
### `shutdown()`
|
|
244
|
+
|
|
245
|
+
Flushes and permanently stops Foam's providers, releases the global
|
|
246
|
+
OpenTelemetry slots Foam owns (slots owned by another SDK are left
|
|
247
|
+
untouched), and marks the SDK uninitialized so a later `init()` can
|
|
248
|
+
register again.
|
|
249
|
+
|
|
250
|
+
```js
|
|
251
|
+
import { shutdown } from "@foam-ai/node";
|
|
252
|
+
|
|
253
|
+
await shutdown();
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Use it for a graceful teardown you control (test suites, embedding Foam in
|
|
257
|
+
a tool that starts and stops). Notes:
|
|
258
|
+
|
|
259
|
+
- Library patches from auto-instrumentation stay in place; after shutdown
|
|
260
|
+
they emit into unregistered providers, which is inert.
|
|
261
|
+
- `shutdown()` never rejects and is safe to call twice. Foam still shuts
|
|
262
|
+
its providers down on `beforeExit`, so calling it on a normal exit is
|
|
263
|
+
optional.
|
|
264
|
+
|
|
214
265
|
### `createFoamIngestSpanProcessor(name, environment, token, options?)`
|
|
215
266
|
|
|
216
267
|
The helper returns a span processor but does not attach it to the
|
|
@@ -486,6 +537,7 @@ getState();
|
|
|
486
537
|
// metrics: "global",
|
|
487
538
|
// logs: "global",
|
|
488
539
|
// baggage: "global",
|
|
540
|
+
// context: "global",
|
|
489
541
|
// profile: "none",
|
|
490
542
|
// },
|
|
491
543
|
// }
|
|
@@ -501,14 +553,14 @@ loads.
|
|
|
501
553
|
Each `signals` value names the source of the Foam export path for that
|
|
502
554
|
signal:
|
|
503
555
|
|
|
504
|
-
- `"global"
|
|
556
|
+
- `"global"`: `init()` registered Foam's provider in the global
|
|
505
557
|
OpenTelemetry slot.
|
|
506
|
-
- `"ingest"
|
|
558
|
+
- `"ingest"`: a `createFoamIngest*` processor/reader was constructed for
|
|
507
559
|
another SDK's pipeline. Foam cannot tell whether you actually registered
|
|
508
560
|
the returned object.
|
|
509
|
-
- `"local"`
|
|
561
|
+
- `"local"` (logs only): another SDK owns the global LoggerProvider, but
|
|
510
562
|
Foam keeps its own local provider so `log()` still delivers to Foam.
|
|
511
|
-
- `"none"
|
|
563
|
+
- `"none"`: no Foam export path.
|
|
512
564
|
|
|
513
565
|
A value other than `"none"` means telemetry is expected, not that the app
|
|
514
566
|
has already produced or exported it.
|
|
@@ -580,9 +632,9 @@ well-known names and any key containing a sensitive term (`legacy_api_key_2`,
|
|
|
580
632
|
application-specific keys with the `redact` option shown under `init(options)`;
|
|
581
633
|
customer keys match exactly after normalization.
|
|
582
634
|
|
|
583
|
-
Redaction applies to everything Foam exports
|
|
584
|
-
|
|
585
|
-
|
|
635
|
+
Redaction applies to everything Foam exports, including the ingest
|
|
636
|
+
helpers: span, span event, and link attributes, log bodies and attributes,
|
|
637
|
+
metric data-point attributes, and resource attributes. It does not modify
|
|
586
638
|
telemetry sent through other exporters.
|
|
587
639
|
|
|
588
640
|
## Loggers
|
|
@@ -652,62 +704,62 @@ Extension points Foam is not using yet, ordered by how much new data they
|
|
|
652
704
|
unlock. All payload extraction flows through the same redaction and size
|
|
653
705
|
caps as HTTP network capture.
|
|
654
706
|
|
|
655
|
-
### Database results
|
|
707
|
+
### Database results: biggest win, zero patching
|
|
656
708
|
|
|
657
709
|
`responseHook` hands Foam the raw driver result (in memory, no extra query)
|
|
658
|
-
before the span ends. Each package has its own payload shape
|
|
710
|
+
before the span ends. Each package has its own payload shape, so do not
|
|
659
711
|
assume a shared contract: `pg` passes `{ data }`, `mysql2`
|
|
660
712
|
`{ queryResults }`, `mongoose` `{ response }`, `mongodb` the command
|
|
661
713
|
response, `cassandra-driver` only the first result page, and
|
|
662
714
|
`ioredis`/`redis` (v4+) use positional `(cmdName, cmdArgs, response)`
|
|
663
715
|
args. Also `requestHook` (pg, ioredis, oracledb) for full query/args, and
|
|
664
716
|
`maskStatementHook` (mysql2) to wire SQL text into Foam redaction. No
|
|
665
|
-
hooks: `mysql` v1, `tedious`, `memcached
|
|
717
|
+
hooks (spans only): `mysql` v1, `tedious`, `memcached`. Ship as opt-in:
|
|
666
718
|
results are the most PII-dense payload in the system.
|
|
667
719
|
`enhancedDatabaseReporting` (adds bound parameter values) must likewise
|
|
668
|
-
stay opt-in
|
|
720
|
+
stay opt-in; redaction cannot key-match values inside SQL text.
|
|
669
721
|
|
|
670
|
-
### http2 + gRPC
|
|
722
|
+
### http2 + gRPC: currently fully dark
|
|
671
723
|
|
|
672
724
|
Node ships `http2.client.stream.*` / `http2.server.stream.*` lifecycle
|
|
673
725
|
channels since 24.1 (backported to 22.x), and the request-body channels
|
|
674
|
-
`bodyChunkSent` / `bodySent` since 24.12.0 / 22.22.1
|
|
726
|
+
`bodyChunkSent` / `bodySent` since 24.12.0 / 22.22.1; pin those floors in
|
|
675
727
|
`support.ts`, gated on the Node version (core emits these, unlike undici's
|
|
676
728
|
own channels). The adapter mirrors `src/network-capture/undici.ts` but the
|
|
677
729
|
payloads differ: Node publishes `{ stream, writev, data, encoding }` for
|
|
678
730
|
`bodyChunkSent` and `{ stream }` for `bodySent`, vs undici's
|
|
679
|
-
`{ request, chunk }
|
|
731
|
+
`{ request, chunk }`, so map fields explicitly. No OTel instrumentation
|
|
680
732
|
exists for http2, so Foam creates the spans too. Response bodies have no
|
|
681
733
|
channel and the exposed `ClientHttp2Stream` is live, not replayable:
|
|
682
734
|
collect passively (wrap `push()` as `http.ts` does) without reading the
|
|
683
735
|
stream or switching it into flowing mode, or leave response capture out.
|
|
684
736
|
For gRPC, `instrumentation-grpc` gives spans but zero payload hooks
|
|
685
|
-
(only `metadataToSpanAttributes
|
|
737
|
+
(only `metadataToSpanAttributes`; enable it). The http2 body chunks carry
|
|
686
738
|
gRPC framing, not bare protobuf: reassemble the 1-byte compression flag +
|
|
687
739
|
4-byte big-endian length prefix per message, decompressing flagged
|
|
688
|
-
messages, before any protobuf decode
|
|
740
|
+
messages, before any protobuf decode, or skip framing entirely with a
|
|
689
741
|
custom patch of `@grpc/grpc-js` serialization.
|
|
690
742
|
|
|
691
|
-
### Messaging and cloud payloads
|
|
743
|
+
### Messaging and cloud payloads: hooks receive the actual message
|
|
692
744
|
|
|
693
745
|
- `kafkajs` `producerHook`/`consumerHook` receive `{ topic, message }`
|
|
694
746
|
(value, key, headers); `amqplib` `publishHook`/`consumeHook`
|
|
695
747
|
(+confirm/end variants) receive the message `content` plus
|
|
696
|
-
routing/options metadata
|
|
748
|
+
routing/options metadata; shapes differ per hook.
|
|
697
749
|
- `socket.io` `emitHook`/`onHook`: event payloads (covers the socket.io
|
|
698
750
|
slice of WebSocket traffic).
|
|
699
751
|
- `aws-sdk` `preRequestHook`/`responseHook`/`exceptionHook` (the latter
|
|
700
752
|
gets `(span, requestInfo, err)`): normalized request/response for every
|
|
701
753
|
AWS call. SDK v3 only.
|
|
702
754
|
|
|
703
|
-
### Crash and shutdown capture
|
|
755
|
+
### Crash and shutdown capture: data we currently lose
|
|
704
756
|
|
|
705
757
|
Errors outside any span (timer callbacks, unhandled rejections, startup)
|
|
706
|
-
are invisible, and `beforeExit`
|
|
758
|
+
are invisible, and `beforeExit` (Foam's only lifecycle hook) does not
|
|
707
759
|
fire on crashes or signals, so the batch holding the spans that explain a
|
|
708
760
|
crash dies with the process, and every SIGTERM (each deploy) drops the
|
|
709
761
|
final batch window. Use `uncaughtExceptionMonitor` (never plain
|
|
710
|
-
`uncaughtException`, which suppresses the default crash)
|
|
762
|
+
`uncaughtException`, which suppresses the default crash), but note an
|
|
711
763
|
async flush started there is abandoned when the process terminates, so
|
|
712
764
|
crash delivery needs a synchronous durable handoff (sync write to disk, or
|
|
713
765
|
a helper process that ships it) rather than relying on the async exporter.
|
package/dist/constants.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare const FOAM_INGEST_HOST: string;
|
|
|
4
4
|
export declare const ATTR_FOAM_INGEST_HOST = "foam.ingest.host";
|
|
5
5
|
export declare const FOAM_IDENTIFIER_NAME = "[foam-otel]";
|
|
6
6
|
export declare const FOAM_DISTRO_NAME = "@foam-ai/node";
|
|
7
|
-
export declare const FOAM_DISTRO_VERSION = "0.1.0-alpha.
|
|
7
|
+
export declare const FOAM_DISTRO_VERSION = "0.1.0-alpha.13";
|
|
8
8
|
export declare const FOAM_OTLP_TRACES_PATH = "/v1/traces";
|
|
9
9
|
export declare const FOAM_OTLP_LOGS_PATH = "/v1/logs";
|
|
10
10
|
export declare const FOAM_OTLP_METRICS_PATH = "/v1/metrics";
|
package/dist/constants.js
CHANGED
|
@@ -7,7 +7,7 @@ exports.FOAM_INGEST_HOST = new URL(exports.FOAM_ENDPOINT).hostname;
|
|
|
7
7
|
exports.ATTR_FOAM_INGEST_HOST = "foam.ingest.host";
|
|
8
8
|
exports.FOAM_IDENTIFIER_NAME = "[foam-otel]";
|
|
9
9
|
exports.FOAM_DISTRO_NAME = "@foam-ai/node";
|
|
10
|
-
exports.FOAM_DISTRO_VERSION = "0.1.0-alpha.
|
|
10
|
+
exports.FOAM_DISTRO_VERSION = "0.1.0-alpha.13";
|
|
11
11
|
exports.FOAM_OTLP_TRACES_PATH = "/v1/traces";
|
|
12
12
|
exports.FOAM_OTLP_LOGS_PATH = "/v1/logs";
|
|
13
13
|
exports.FOAM_OTLP_METRICS_PATH = "/v1/metrics";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { init, type InitOptions } from "./init.js";
|
|
2
|
+
export { flush, shutdown } from "./lifecycle.js";
|
|
2
3
|
export type { BeforeSendEvent, BeforeSendHook, } from "./before-send.js";
|
|
3
4
|
export type { RedactOptions } from "./redaction.js";
|
|
4
5
|
export { getState } from "./state.js";
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.recordException = exports.SeverityNumber = exports.log = exports.setMetric = exports.recordHistogram = exports.incrementCounter = exports.addUpDownCounter = exports.setBaggage = exports.injectTraceContext = exports.getBaggage = exports.extractTraceContext = exports.createFoamIngestSpanProcessor = exports.createFoamIngestMetricReader = exports.createFoamIngestLogRecordProcessor = exports.setEndpoint = exports.getState = exports.init = void 0;
|
|
3
|
+
exports.recordException = exports.SeverityNumber = exports.log = exports.setMetric = exports.recordHistogram = exports.incrementCounter = exports.addUpDownCounter = exports.setBaggage = exports.injectTraceContext = exports.getBaggage = exports.extractTraceContext = exports.createFoamIngestSpanProcessor = exports.createFoamIngestMetricReader = exports.createFoamIngestLogRecordProcessor = exports.setEndpoint = exports.getState = exports.shutdown = exports.flush = exports.init = void 0;
|
|
4
4
|
var init_js_1 = require("./init.js");
|
|
5
5
|
Object.defineProperty(exports, "init", { enumerable: true, get: function () { return init_js_1.init; } });
|
|
6
|
+
var lifecycle_js_1 = require("./lifecycle.js");
|
|
7
|
+
Object.defineProperty(exports, "flush", { enumerable: true, get: function () { return lifecycle_js_1.flush; } });
|
|
8
|
+
Object.defineProperty(exports, "shutdown", { enumerable: true, get: function () { return lifecycle_js_1.shutdown; } });
|
|
6
9
|
var state_js_1 = require("./state.js");
|
|
7
10
|
Object.defineProperty(exports, "getState", { enumerable: true, get: function () { return state_js_1.getState; } });
|
|
8
11
|
var endpoint_js_1 = require("./endpoint.js");
|
package/dist/init.d.ts
CHANGED
package/dist/init.js
CHANGED
|
@@ -14,9 +14,12 @@ const report_js_1 = require("./report.js");
|
|
|
14
14
|
const exporters_js_1 = require("./exporters.js");
|
|
15
15
|
const instrumentations_js_1 = require("./instrumentations.js");
|
|
16
16
|
const before_send_js_1 = require("./before-send.js");
|
|
17
|
+
const lifecycle_js_1 = require("./lifecycle.js");
|
|
17
18
|
const logs_js_1 = require("./logs.js");
|
|
18
19
|
const redaction_js_1 = require("./redaction.js");
|
|
19
20
|
const state_js_1 = require("./state.js");
|
|
21
|
+
const utils_js_1 = require("./utils.js");
|
|
22
|
+
let exitHookInstalled = false;
|
|
20
23
|
// TODO(pcga11): conflicts handling pending.
|
|
21
24
|
function init(options) {
|
|
22
25
|
const { sampleRate = 1, disableLogSending = false, networkCapture = "basic", enabled = true, } = options;
|
|
@@ -66,10 +69,6 @@ function init(options) {
|
|
|
66
69
|
});
|
|
67
70
|
return;
|
|
68
71
|
}
|
|
69
|
-
// pcga11: Hoisted so the catch block can shut down providers whose batch/periodic
|
|
70
|
-
// export timers started in their constructors, even when init fails midway.
|
|
71
|
-
let tracerProvider;
|
|
72
|
-
let meterProvider;
|
|
73
72
|
try {
|
|
74
73
|
(0, redaction_js_1.setActiveRedactionConfig)(redactionConfig);
|
|
75
74
|
const resource = (0, resource_js_1.createFoamResource)(options.name, options.environment, options.version, options.additionalResourceAttributes);
|
|
@@ -79,7 +78,10 @@ function init(options) {
|
|
|
79
78
|
// is first-wins: if another SDK already installed one, we keep theirs and disable ours.
|
|
80
79
|
const contextManager = new context_async_hooks_1.AsyncLocalStorageContextManager();
|
|
81
80
|
contextManager.enable();
|
|
82
|
-
if (
|
|
81
|
+
if (api_1.context.setGlobalContextManager(contextManager)) {
|
|
82
|
+
(0, state_js_1.setSignal)(state_js_1.Signals.context, state_js_1.SignalSources.global);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
83
85
|
contextManager.disable();
|
|
84
86
|
}
|
|
85
87
|
(0, state_js_1.setSignal)(state_js_1.Signals.baggage, api_1.propagation.setGlobalPropagator(new core_1.CompositePropagator({
|
|
@@ -90,7 +92,9 @@ function init(options) {
|
|
|
90
92
|
})) ? state_js_1.SignalSources.global : state_js_1.SignalSources.none);
|
|
91
93
|
// pcga11: The @opentelemetry/api setters return false when another SDK already owns a slot (registration is first-wins). So we try to register our own and if it fails or already taken, nothing happens.
|
|
92
94
|
// TODO(pcga11): Implement a way to handle piggy backing the context and propagation from another SDK.
|
|
93
|
-
|
|
95
|
+
// pcga11: Providers are registered at construction (their export timers
|
|
96
|
+
// start in the constructor) so the catch's shutdown() always finds them.
|
|
97
|
+
const tracerProvider = (0, lifecycle_js_1.setFoamTracerProvider)(new sdk_trace_base_1.BasicTracerProvider({
|
|
94
98
|
resource,
|
|
95
99
|
sampler: new sdk_trace_base_1.ParentBasedSampler({
|
|
96
100
|
root: new sdk_trace_base_1.TraceIdRatioBasedSampler(sampleRate),
|
|
@@ -102,8 +106,8 @@ function init(options) {
|
|
|
102
106
|
})),
|
|
103
107
|
...(options.additionalSpanProcessors ?? []),
|
|
104
108
|
],
|
|
105
|
-
});
|
|
106
|
-
meterProvider = new sdk_metrics_1.MeterProvider({
|
|
109
|
+
}));
|
|
110
|
+
const meterProvider = (0, lifecycle_js_1.setFoamMeterProvider)(new sdk_metrics_1.MeterProvider({
|
|
107
111
|
resource,
|
|
108
112
|
readers: [
|
|
109
113
|
new sdk_metrics_1.PeriodicExportingMetricReader({
|
|
@@ -113,7 +117,7 @@ function init(options) {
|
|
|
113
117
|
}),
|
|
114
118
|
...(options.additionalMetricReaders ?? []),
|
|
115
119
|
],
|
|
116
|
-
});
|
|
120
|
+
}));
|
|
117
121
|
const loggerProvider = new sdk_logs_1.LoggerProvider({
|
|
118
122
|
resource,
|
|
119
123
|
processors: [
|
|
@@ -135,13 +139,12 @@ function init(options) {
|
|
|
135
139
|
// pcga11: registerInstrumentations turns on instrumentation "hooks". OpenTelemetry wraps supported libraries when the app imports them.
|
|
136
140
|
(0, instrumentation_1.registerInstrumentations)({ instrumentations });
|
|
137
141
|
(0, state_js_1.setInstrumentations)(instrumentations.map(instrumentations_js_1.instrumentationLabel));
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
});
|
|
142
|
+
// pcga11: shutdown() never rejects, so it doubles as the exit hook.
|
|
143
|
+
// Installed once per process; re-inits must not stack listeners.
|
|
144
|
+
if (!exitHookInstalled) {
|
|
145
|
+
exitHookInstalled = true;
|
|
146
|
+
process.once("beforeExit", () => void (0, lifecycle_js_1.shutdown)());
|
|
147
|
+
}
|
|
145
148
|
(0, state_js_1.setInitialized)(true);
|
|
146
149
|
(0, report_js_1.report)({
|
|
147
150
|
token: options.token,
|
|
@@ -150,17 +153,10 @@ function init(options) {
|
|
|
150
153
|
});
|
|
151
154
|
}
|
|
152
155
|
catch (error) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
void Promise.all([
|
|
158
|
-
tracerProvider?.shutdown(),
|
|
159
|
-
meterProvider?.shutdown(),
|
|
160
|
-
(0, logs_js_1.getFoamLoggerProvider)()?.shutdown(),
|
|
161
|
-
]).catch(() => undefined);
|
|
162
|
-
(0, logs_js_1.clearFoamLoggerProvider)();
|
|
163
|
-
(0, state_js_1.setInitialized)(false);
|
|
156
|
+
// pcga11: Nothing in a catch may throw (it would escape into app code):
|
|
157
|
+
// shutdown() never rejects, safely() covers throwing toString().
|
|
158
|
+
void (0, lifecycle_js_1.shutdown)();
|
|
159
|
+
const errorMessage = (0, utils_js_1.safely)(() => (error instanceof Error ? error.message : String(error)), "unknown");
|
|
164
160
|
(0, report_js_1.report)({
|
|
165
161
|
token: options.token,
|
|
166
162
|
severity: api_logs_1.SeverityNumber.ERROR,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MeterProvider } from "@opentelemetry/sdk-metrics";
|
|
2
|
+
import type { BasicTracerProvider } from "@opentelemetry/sdk-trace-base";
|
|
3
|
+
export declare function setFoamTracerProvider(provider: BasicTracerProvider): BasicTracerProvider;
|
|
4
|
+
export declare function setFoamMeterProvider(provider: MeterProvider): MeterProvider;
|
|
5
|
+
export declare function flush(): Promise<void>;
|
|
6
|
+
export declare function shutdown(): Promise<void>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setFoamTracerProvider = setFoamTracerProvider;
|
|
4
|
+
exports.setFoamMeterProvider = setFoamMeterProvider;
|
|
5
|
+
exports.flush = flush;
|
|
6
|
+
exports.shutdown = shutdown;
|
|
7
|
+
const api_1 = require("@opentelemetry/api");
|
|
8
|
+
const api_logs_1 = require("@opentelemetry/api-logs");
|
|
9
|
+
const logs_js_1 = require("./logs.js");
|
|
10
|
+
const utils_js_1 = require("./utils.js");
|
|
11
|
+
const state_js_1 = require("./state.js");
|
|
12
|
+
// pcga11: How flush()/shutdown() reach the providers. init() registers each
|
|
13
|
+
// at construction, so the registry is current even when init() fails midway.
|
|
14
|
+
// The logger provider has its own registry in logs.ts.
|
|
15
|
+
let foamTracerProvider;
|
|
16
|
+
let foamMeterProvider;
|
|
17
|
+
function setFoamTracerProvider(provider) {
|
|
18
|
+
foamTracerProvider = provider;
|
|
19
|
+
return provider;
|
|
20
|
+
}
|
|
21
|
+
function setFoamMeterProvider(provider) {
|
|
22
|
+
foamMeterProvider = provider;
|
|
23
|
+
return provider;
|
|
24
|
+
}
|
|
25
|
+
// pcga11: Both methods fail open: the async mappers turn synchronous throws
|
|
26
|
+
// into rejections and allSettled swallows them, so neither can ever reject.
|
|
27
|
+
const providers = () => [foamTracerProvider, foamMeterProvider, (0, logs_js_1.getFoamLoggerProvider)()];
|
|
28
|
+
async function flush() {
|
|
29
|
+
await Promise.allSettled(providers().map(async (provider) => provider?.forceFlush()));
|
|
30
|
+
}
|
|
31
|
+
async function shutdown() {
|
|
32
|
+
const active = providers();
|
|
33
|
+
foamTracerProvider = undefined;
|
|
34
|
+
foamMeterProvider = undefined;
|
|
35
|
+
(0, logs_js_1.clearFoamLoggerProvider)();
|
|
36
|
+
// pcga11: Release only the global API slots Foam owns (registration is
|
|
37
|
+
// first-wins, so a later SDK could not register otherwise). Slots owned
|
|
38
|
+
// by another SDK are left untouched.
|
|
39
|
+
const slots = [
|
|
40
|
+
[state_js_1.Signals.traces, api_1.trace],
|
|
41
|
+
[state_js_1.Signals.metrics, api_1.metrics],
|
|
42
|
+
[state_js_1.Signals.logs, api_logs_1.logs],
|
|
43
|
+
[state_js_1.Signals.baggage, api_1.propagation],
|
|
44
|
+
[state_js_1.Signals.context, api_1.context],
|
|
45
|
+
];
|
|
46
|
+
for (const [signal, api] of slots) {
|
|
47
|
+
if ((0, state_js_1.getSignal)(signal) === state_js_1.SignalSources.global)
|
|
48
|
+
(0, utils_js_1.safely)(() => api.disable());
|
|
49
|
+
(0, state_js_1.setSignal)(signal, state_js_1.SignalSources.none);
|
|
50
|
+
}
|
|
51
|
+
(0, state_js_1.setInitialized)(false);
|
|
52
|
+
await Promise.allSettled(active.map(async (provider) => provider?.shutdown()));
|
|
53
|
+
}
|
package/dist/state.d.ts
CHANGED
package/dist/state.js
CHANGED
|
@@ -7,6 +7,7 @@ var Signals;
|
|
|
7
7
|
Signals["metrics"] = "metrics";
|
|
8
8
|
Signals["logs"] = "logs";
|
|
9
9
|
Signals["baggage"] = "baggage";
|
|
10
|
+
Signals["context"] = "context";
|
|
10
11
|
Signals["profile"] = "profile";
|
|
11
12
|
})(Signals || (exports.Signals = Signals = {}));
|
|
12
13
|
var SignalSources;
|
|
@@ -24,6 +25,7 @@ const state = {
|
|
|
24
25
|
metrics: SignalSources.none,
|
|
25
26
|
logs: SignalSources.none,
|
|
26
27
|
baggage: SignalSources.none,
|
|
28
|
+
context: SignalSources.none,
|
|
27
29
|
profile: SignalSources.none,
|
|
28
30
|
},
|
|
29
31
|
params: {},
|