@adonis-agora/telescope 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -0
- package/dist/providers/telescope_provider.d.ts +16 -0
- package/dist/providers/telescope_provider.d.ts.map +1 -1
- package/dist/providers/telescope_provider.js +39 -1
- package/dist/providers/telescope_provider.js.map +1 -1
- package/dist/src/ai/index.d.ts +1 -1
- package/dist/src/ai/index.js +1 -1
- package/dist/src/alerts/index.d.ts +1 -1
- package/dist/src/alerts/index.js +1 -1
- package/dist/src/define_config.d.ts +64 -0
- package/dist/src/define_config.d.ts.map +1 -1
- package/dist/src/define_config.js +18 -0
- package/dist/src/define_config.js.map +1 -1
- package/dist/src/diagnostics_registry.d.ts +9 -0
- package/dist/src/diagnostics_registry.d.ts.map +1 -1
- package/dist/src/diagnostics_registry.js +2 -1
- package/dist/src/diagnostics_registry.js.map +1 -1
- package/dist/src/diagnostics_watcher.d.ts +5 -0
- package/dist/src/diagnostics_watcher.d.ts.map +1 -1
- package/dist/src/diagnostics_watcher.js +6 -0
- package/dist/src/diagnostics_watcher.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/mcp/index.d.ts +1 -1
- package/dist/src/mcp/index.js +1 -1
- package/dist/src/otel/index.d.ts +11 -0
- package/dist/src/otel/index.d.ts.map +1 -0
- package/dist/src/otel/index.js +11 -0
- package/dist/src/otel/index.js.map +1 -0
- package/dist/src/otel/mapper.d.ts +118 -0
- package/dist/src/otel/mapper.d.ts.map +1 -0
- package/dist/src/otel/mapper.js +205 -0
- package/dist/src/otel/mapper.js.map +1 -0
- package/dist/src/otel/otel_exporter.d.ts +17 -0
- package/dist/src/otel/otel_exporter.d.ts.map +1 -0
- package/dist/src/otel/otel_exporter.js +107 -0
- package/dist/src/otel/otel_exporter.js.map +1 -0
- package/dist/src/otel/otel_exporting_store.d.ts +49 -0
- package/dist/src/otel/otel_exporting_store.d.ts.map +1 -0
- package/dist/src/otel/otel_exporting_store.js +83 -0
- package/dist/src/otel/otel_exporting_store.js.map +1 -0
- package/dist/src/profiling/index.d.ts +1 -1
- package/dist/src/profiling/index.js +1 -1
- package/dist/src/ui/define_config.d.ts +40 -4
- package/dist/src/ui/define_config.d.ts.map +1 -1
- package/dist/src/ui/define_config.js.map +1 -1
- package/dist/src/ui/guard.d.ts +13 -4
- package/dist/src/ui/guard.d.ts.map +1 -1
- package/dist/src/ui/guard.js +21 -6
- package/dist/src/ui/guard.js.map +1 -1
- package/dist/src/ui/index.d.ts +1 -1
- package/dist/src/ui/index.js +1 -1
- package/dist/src/watchers/index.d.ts +1 -1
- package/dist/src/watchers/index.js +1 -1
- package/package.json +40 -2
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { Entry } from '../entry.js';
|
|
2
|
+
/**
|
|
3
|
+
* The generic diagnostics-entry → OTel mapper. Pure, dependency-free (no
|
|
4
|
+
* `@opentelemetry/*` import anywhere in this file) so it is trivially unit-testable
|
|
5
|
+
* and so importing it never pulls in the OTel SDK — only `otel_exporter.ts` (which
|
|
6
|
+
* consumes this module's OUTPUT) does that, and only when OTel export is enabled.
|
|
7
|
+
*
|
|
8
|
+
* ## The mapping, in one paragraph
|
|
9
|
+
*
|
|
10
|
+
* Every recorded entry already carries a uniform shape (`type`, `content`, `tags`,
|
|
11
|
+
* `durationMs`, `traceId`, `createdAt` — see `entry.ts`). This module turns that
|
|
12
|
+
* shape into either a {@link SpanExportInput} or a {@link LogExportInput}:
|
|
13
|
+
*
|
|
14
|
+
* - **Has a duration → SPAN.** {@link resolveDurationMs} looks for it in two
|
|
15
|
+
* places: the entry's own top-level `durationMs` (set for every `diagnostic`
|
|
16
|
+
* entry whose envelope carried `@adonis-agora/diagnostics`'s `emit(..., {
|
|
17
|
+
* durationMs })`), or — when absent — a numeric `payload.durationMs` field
|
|
18
|
+
* (the convention several libs use when they stuff a richer lifecycle-event
|
|
19
|
+
* object as the payload; `@adonis-agora/durable`'s diagnostics bridge is exactly
|
|
20
|
+
* this: `emit('durable', event.type, event)` with `event.durationMs` inside).
|
|
21
|
+
* The span's start time is reconstructed as `end - durationMs` (the event is
|
|
22
|
+
* ALREADY FINISHED by the time telescope observes it — there is no live span to
|
|
23
|
+
* attach to, only a historical record — the same reconstruction
|
|
24
|
+
* `@adonis-agora/durable`'s bespoke `attachDurableOtel` uses for its step spans).
|
|
25
|
+
* - **No duration → LOG.** A point-in-time occurrence becomes an OTel log record
|
|
26
|
+
* instead of a zero-duration span, which is both more idiomatic (Loki, not
|
|
27
|
+
* Tempo, is where "something happened" belongs) and cheaper (one log record vs.
|
|
28
|
+
* a full span with an implicit trace).
|
|
29
|
+
*
|
|
30
|
+
* Both forms share: a name/body of `agora.<lib>.<event>` (matching the naming
|
|
31
|
+
* `@adonis-agora/diagnostics`'s OWN OTel bridge uses for the SAME channels, so a
|
|
32
|
+
* host running both sees consistent naming), flattened scalar/array payload
|
|
33
|
+
* fields as `agora.payload.<key>` attributes, `agora.lib`/`agora.event` attributes,
|
|
34
|
+
* `agora.entry_id` (the Telescope entry id, so a span/log in Grafana links back to
|
|
35
|
+
* the exact entry in the Telescope dashboard), and error detection reusing the
|
|
36
|
+
* SAME `isErrorEntry` heuristic the sampling store already uses for `keepErrors`
|
|
37
|
+
* (kept consistent on purpose: "this looks like an error" should mean the same
|
|
38
|
+
* thing everywhere in this package) plus a couple of diagnostics-specific
|
|
39
|
+
* additions (`payload.error` truthy, or an event name containing `error`/`fail`)
|
|
40
|
+
* that `isErrorEntry` cannot see because it only reads shallow, entry-type-generic
|
|
41
|
+
* fields.
|
|
42
|
+
*
|
|
43
|
+
* ## Trace correlation
|
|
44
|
+
*
|
|
45
|
+
* `entry.traceId` is the trace id `@adonis-agora/context` resolved at record time —
|
|
46
|
+
* either a fresh random 16-byte value, or (when the inbound HTTP request carried
|
|
47
|
+
* one) the EXACT W3C `traceparent` trace-id, parsed byte-for-byte. When it is
|
|
48
|
+
* present AND well-formed (32 lowercase hex chars, not all-zero — see
|
|
49
|
+
* {@link isValidW3cTraceId}), the mapper carries it through so the exporter can
|
|
50
|
+
* parent the reconstructed span/log under it — the same correlation id a real
|
|
51
|
+
* OTel span from an instrumented gateway upstream would have used, so Tempo/Loki
|
|
52
|
+
* group them into the SAME trace even though telescope's span was synthesized
|
|
53
|
+
* after the fact from a diagnostics event, not from a live OTel context.
|
|
54
|
+
*/
|
|
55
|
+
/**
|
|
56
|
+
* An OTel attribute value: a primitive, or a HOMOGENEOUS array of one primitive
|
|
57
|
+
* type — matching `@opentelemetry/api`'s own `AttributeValue` exactly (a mixed
|
|
58
|
+
* `(string | number)[]` array is not a valid OTel attribute value), so a caller
|
|
59
|
+
* can pass this straight through to `Span.setAttribute`/`startSpan({ attributes })`
|
|
60
|
+
* with no cast.
|
|
61
|
+
*/
|
|
62
|
+
export type AttributeValue = string | number | boolean | string[] | number[] | boolean[];
|
|
63
|
+
/** A flat attribute bag — every key namespaced `agora.*` by the builders below. */
|
|
64
|
+
export type AttributeMap = Record<string, AttributeValue>;
|
|
65
|
+
/** The pure, OTel-SDK-agnostic description of one reconstructed span. */
|
|
66
|
+
export interface SpanExportInput {
|
|
67
|
+
/** `agora.<lib>.<event>`. */
|
|
68
|
+
name: string;
|
|
69
|
+
/** Epoch millis the operation started (`endTimeMs - durationMs`). */
|
|
70
|
+
startTimeMs: number;
|
|
71
|
+
/** Epoch millis the operation completed (the entry's timestamp). */
|
|
72
|
+
endTimeMs: number;
|
|
73
|
+
attributes: AttributeMap;
|
|
74
|
+
status: 'OK' | 'ERROR';
|
|
75
|
+
/** Present only when {@link status} is `'ERROR'`. */
|
|
76
|
+
errorMessage?: string;
|
|
77
|
+
/** A valid W3C trace id to parent the span under, or `null` when unavailable. */
|
|
78
|
+
traceId: string | null;
|
|
79
|
+
}
|
|
80
|
+
/** The pure, OTel-SDK-agnostic description of one log record. */
|
|
81
|
+
export interface LogExportInput {
|
|
82
|
+
/** `agora.<lib>.<event>`. */
|
|
83
|
+
body: string;
|
|
84
|
+
/** Epoch millis the event occurred. */
|
|
85
|
+
timestampMs: number;
|
|
86
|
+
/** OTel numeric severity (`SeverityNumber` values — kept as a literal so this file needs no OTel import). */
|
|
87
|
+
severityNumber: number;
|
|
88
|
+
severityText: 'INFO' | 'WARN' | 'ERROR';
|
|
89
|
+
attributes: AttributeMap;
|
|
90
|
+
traceId: string | null;
|
|
91
|
+
}
|
|
92
|
+
/** Discriminated mapper result. `null` when the entry has no interpretable shape. */
|
|
93
|
+
export type MappedEntry = {
|
|
94
|
+
kind: 'span';
|
|
95
|
+
span: SpanExportInput;
|
|
96
|
+
} | {
|
|
97
|
+
kind: 'log';
|
|
98
|
+
log: LogExportInput;
|
|
99
|
+
} | null;
|
|
100
|
+
/** Whether `id` is a well-formed, non-zero W3C trace id (32 lowercase hex chars). */
|
|
101
|
+
export declare function isValidW3cTraceId(id: string | null | undefined): id is string;
|
|
102
|
+
/**
|
|
103
|
+
* Resolve the duration this entry describes, in ms, or `null` when it is a
|
|
104
|
+
* point-in-time occurrence with no associated duration. Checks the entry's own
|
|
105
|
+
* top-level `durationMs` first (the standard, entry-type-generic field every
|
|
106
|
+
* watcher can set — see `entry.ts`), falling back to a numeric
|
|
107
|
+
* `content.payload.durationMs` (the convention a diagnostics-bridged lifecycle
|
|
108
|
+
* event, e.g. `@adonis-agora/durable`'s, uses instead).
|
|
109
|
+
*/
|
|
110
|
+
export declare function resolveDurationMs(entry: Entry): number | null;
|
|
111
|
+
/**
|
|
112
|
+
* Map one recorded {@link Entry} to a span or log export input, or `null` when it
|
|
113
|
+
* has no interpretable `{ lib, event }` shape (only `diagnostic`-shaped content —
|
|
114
|
+
* `lib`/`event` strings — is currently mapped; entries of other configured
|
|
115
|
+
* `entryTypes` degrade to `null`, i.e. skipped, until they get their own mapping).
|
|
116
|
+
*/
|
|
117
|
+
export declare function mapEntryToOtel(entry: Entry): MappedEntry;
|
|
118
|
+
//# sourceMappingURL=mapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../../../src/otel/mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC;AAEzF,mFAAmF;AACnF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAE1D,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,YAAY,CAAC;IACzB,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;IACvB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,iEAAiE;AACjE,MAAM,WAAW,cAAc;IAC7B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,6GAA6G;IAC7G,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACxC,UAAU,EAAE,YAAY,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,qFAAqF;AACrF,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,eAAe,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,cAAc,CAAA;CAAE,GACpC,IAAI,CAAC;AAeT,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,EAAE,IAAI,MAAM,CAE7E;AASD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAI7D;AAgHD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,WAAW,CAqCxD"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { isErrorEntry } from '../sampling/sampling.js';
|
|
2
|
+
const SEVERITY_NUMBER = {
|
|
3
|
+
// Mirrors `@opentelemetry/api-logs`' `SeverityNumber` enum values exactly
|
|
4
|
+
// (INFO=9, WARN=13, ERROR=17) without importing the package — this file must
|
|
5
|
+
// stay dependency-free. `otel_exporter.ts` only ever reads these as opaque
|
|
6
|
+
// numbers it forwards verbatim to the real `LogRecord`.
|
|
7
|
+
INFO: 9,
|
|
8
|
+
WARN: 13,
|
|
9
|
+
ERROR: 17,
|
|
10
|
+
};
|
|
11
|
+
const W3C_TRACE_ID_RE = /^[0-9a-f]{32}$/;
|
|
12
|
+
const ALL_ZERO_TRACE_ID = '0'.repeat(32);
|
|
13
|
+
/** Whether `id` is a well-formed, non-zero W3C trace id (32 lowercase hex chars). */
|
|
14
|
+
export function isValidW3cTraceId(id) {
|
|
15
|
+
return typeof id === 'string' && W3C_TRACE_ID_RE.test(id) && id !== ALL_ZERO_TRACE_ID;
|
|
16
|
+
}
|
|
17
|
+
/** Best-effort read of a positive, finite numeric field off an unknown value. */
|
|
18
|
+
function readPositiveNumber(value, key) {
|
|
19
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
20
|
+
return null;
|
|
21
|
+
const raw = value[key];
|
|
22
|
+
return typeof raw === 'number' && Number.isFinite(raw) && raw >= 0 ? raw : null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the duration this entry describes, in ms, or `null` when it is a
|
|
26
|
+
* point-in-time occurrence with no associated duration. Checks the entry's own
|
|
27
|
+
* top-level `durationMs` first (the standard, entry-type-generic field every
|
|
28
|
+
* watcher can set — see `entry.ts`), falling back to a numeric
|
|
29
|
+
* `content.payload.durationMs` (the convention a diagnostics-bridged lifecycle
|
|
30
|
+
* event, e.g. `@adonis-agora/durable`'s, uses instead).
|
|
31
|
+
*/
|
|
32
|
+
export function resolveDurationMs(entry) {
|
|
33
|
+
if (typeof entry.durationMs === 'number' && entry.durationMs >= 0)
|
|
34
|
+
return entry.durationMs;
|
|
35
|
+
const content = entry.content;
|
|
36
|
+
return readPositiveNumber(content?.payload, 'durationMs');
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* True when `value` is a valid OTel attribute value: a primitive, or a
|
|
40
|
+
* HOMOGENEOUS array of one primitive type (nulls/undefined allowed as array
|
|
41
|
+
* holes, matching `@opentelemetry/api`'s own `AttributeValue`). A mixed-type
|
|
42
|
+
* array (`[1, 'a']`) is rejected — it has no valid OTel representation.
|
|
43
|
+
*/
|
|
44
|
+
function isAttributeValue(value) {
|
|
45
|
+
if (value === null || value === undefined)
|
|
46
|
+
return false;
|
|
47
|
+
const t = typeof value;
|
|
48
|
+
if (t === 'string' || t === 'number' || t === 'boolean')
|
|
49
|
+
return true;
|
|
50
|
+
if (Array.isArray(value)) {
|
|
51
|
+
const types = new Set(value.filter((v) => v !== null && v !== undefined).map((v) => typeof v));
|
|
52
|
+
if (types.size > 1)
|
|
53
|
+
return false;
|
|
54
|
+
const [only] = types;
|
|
55
|
+
return only === undefined || only === 'string' || only === 'number' || only === 'boolean';
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Flatten a payload's own enumerable scalar/array fields into namespaced
|
|
61
|
+
* `agora.payload.<key>` attributes. Best-effort and bounded to the payload's OWN
|
|
62
|
+
* keys (one level — this is attribute flattening for search/filter, not a full
|
|
63
|
+
* structural dump; the complete payload is still visible in the Telescope entry
|
|
64
|
+
* itself via `agora.entry_id`). Never throws.
|
|
65
|
+
*/
|
|
66
|
+
function payloadAttributes(payload) {
|
|
67
|
+
const attrs = {};
|
|
68
|
+
if (payload === null || typeof payload !== 'object' || Array.isArray(payload))
|
|
69
|
+
return attrs;
|
|
70
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
71
|
+
if (isAttributeValue(value))
|
|
72
|
+
attrs[`agora.payload.${key}`] = value;
|
|
73
|
+
}
|
|
74
|
+
return attrs;
|
|
75
|
+
}
|
|
76
|
+
function asDiagnosticLike(content) {
|
|
77
|
+
if (content === null || typeof content !== 'object' || Array.isArray(content))
|
|
78
|
+
return null;
|
|
79
|
+
return content;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Whether this entry "looks like an error", for span status / log severity.
|
|
83
|
+
* Layers two checks:
|
|
84
|
+
* 1. {@link isErrorEntry} — the SAME shallow heuristic the sampling store's
|
|
85
|
+
* `keepErrors` already uses (`tags` has `'failed'`, `content.failed === true`,
|
|
86
|
+
* `content.statusCode >= 500`, or `content.level` is warn/error/fatal).
|
|
87
|
+
* 2. Diagnostics-specific additions `isErrorEntry` cannot see: a truthy
|
|
88
|
+
* `payload.error` field (the `{ error }` shape lifecycle-event bridges commonly
|
|
89
|
+
* use, e.g. `@adonis-agora/durable`'s `EngineEvent`), or an `event` name
|
|
90
|
+
* containing `error`/`fail` (`'run.failed'`, `'step.failed'`, …).
|
|
91
|
+
*/
|
|
92
|
+
function looksLikeError(entry) {
|
|
93
|
+
if (isErrorEntry({ type: entry.type, content: entry.content, tags: entry.tags }))
|
|
94
|
+
return true;
|
|
95
|
+
const content = asDiagnosticLike(entry.content);
|
|
96
|
+
if (content === null)
|
|
97
|
+
return false;
|
|
98
|
+
const payload = content.payload;
|
|
99
|
+
if (payload !== null && typeof payload === 'object' && !Array.isArray(payload)) {
|
|
100
|
+
const error = payload.error;
|
|
101
|
+
if (error !== undefined && error !== null && error !== false)
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
if (typeof content.event === 'string') {
|
|
105
|
+
const lower = content.event.toLowerCase();
|
|
106
|
+
if (lower.includes('error') || lower.includes('fail'))
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
/** Read an explicit log level off the payload/content, when present, normalized to our severity trio. */
|
|
112
|
+
function explicitSeverity(entry) {
|
|
113
|
+
const content = asDiagnosticLike(entry.content);
|
|
114
|
+
const payload = content?.payload !== null && typeof content?.payload === 'object'
|
|
115
|
+
? content.payload
|
|
116
|
+
: null;
|
|
117
|
+
const raw = payload?.level ?? entry.content?.level;
|
|
118
|
+
if (typeof raw !== 'string')
|
|
119
|
+
return null;
|
|
120
|
+
const lower = raw.toLowerCase();
|
|
121
|
+
if (lower === 'warn' || lower === 'warning')
|
|
122
|
+
return 'WARN';
|
|
123
|
+
if (lower === 'error' || lower === 'fatal')
|
|
124
|
+
return 'ERROR';
|
|
125
|
+
if (lower === 'info' || lower === 'debug' || lower === 'trace')
|
|
126
|
+
return 'INFO';
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Shared attribute base for both span and log mappings. `agora.trace_id` is
|
|
131
|
+
* whatever `@adonis-agora/context` resolved verbatim — a plain search/filter
|
|
132
|
+
* attribute, kept even when it is not valid W3C shape. This is deliberately
|
|
133
|
+
* SEPARATE from `SpanExportInput.traceId`/`LogExportInput.traceId` (strictly
|
|
134
|
+
* {@link isValidW3cTraceId}-checked), which is used for the actual OTel
|
|
135
|
+
* parent-context correlation and must never be malformed.
|
|
136
|
+
*/
|
|
137
|
+
function baseAttributes(entry, lib, event) {
|
|
138
|
+
const content = asDiagnosticLike(entry.content);
|
|
139
|
+
return {
|
|
140
|
+
'agora.lib': lib,
|
|
141
|
+
'agora.event': event,
|
|
142
|
+
'agora.entry_id': entry.id,
|
|
143
|
+
...(entry.traceId ? { 'agora.trace_id': entry.traceId } : {}),
|
|
144
|
+
...payloadAttributes(content?.payload),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Map one recorded {@link Entry} to a span or log export input, or `null` when it
|
|
149
|
+
* has no interpretable `{ lib, event }` shape (only `diagnostic`-shaped content —
|
|
150
|
+
* `lib`/`event` strings — is currently mapped; entries of other configured
|
|
151
|
+
* `entryTypes` degrade to `null`, i.e. skipped, until they get their own mapping).
|
|
152
|
+
*/
|
|
153
|
+
export function mapEntryToOtel(entry) {
|
|
154
|
+
const content = asDiagnosticLike(entry.content);
|
|
155
|
+
if (content === null || typeof content.lib !== 'string' || typeof content.event !== 'string') {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
const { lib, event } = content;
|
|
159
|
+
const name = `agora.${lib}.${event}`;
|
|
160
|
+
const traceId = isValidW3cTraceId(entry.traceId) ? entry.traceId : null;
|
|
161
|
+
const errored = looksLikeError(entry);
|
|
162
|
+
const durationMs = resolveDurationMs(entry);
|
|
163
|
+
const ts = typeof content.ts === 'number' ? content.ts : null;
|
|
164
|
+
if (durationMs !== null) {
|
|
165
|
+
const endTimeMs = ts ?? entry.createdAt.getTime();
|
|
166
|
+
const span = {
|
|
167
|
+
name,
|
|
168
|
+
startTimeMs: endTimeMs - durationMs,
|
|
169
|
+
endTimeMs,
|
|
170
|
+
attributes: baseAttributes(entry, lib, event),
|
|
171
|
+
status: errored ? 'ERROR' : 'OK',
|
|
172
|
+
...(errored ? { errorMessage: errorMessageOf(content) ?? `${name} failed` } : {}),
|
|
173
|
+
traceId,
|
|
174
|
+
};
|
|
175
|
+
return { kind: 'span', span };
|
|
176
|
+
}
|
|
177
|
+
const severity = explicitSeverity(entry) ?? (errored ? 'ERROR' : 'INFO');
|
|
178
|
+
const log = {
|
|
179
|
+
body: name,
|
|
180
|
+
timestampMs: ts ?? entry.createdAt.getTime(),
|
|
181
|
+
severityNumber: SEVERITY_NUMBER[severity],
|
|
182
|
+
severityText: severity,
|
|
183
|
+
attributes: baseAttributes(entry, lib, event),
|
|
184
|
+
traceId,
|
|
185
|
+
};
|
|
186
|
+
return { kind: 'log', log };
|
|
187
|
+
}
|
|
188
|
+
/** Best-effort extraction of a human-readable error message from a diagnostic payload. */
|
|
189
|
+
function errorMessageOf(content) {
|
|
190
|
+
const payload = content.payload;
|
|
191
|
+
if (payload === null || typeof payload !== 'object' || Array.isArray(payload))
|
|
192
|
+
return undefined;
|
|
193
|
+
const error = payload.error;
|
|
194
|
+
if (error instanceof Error)
|
|
195
|
+
return error.message;
|
|
196
|
+
if (error !== undefined && error !== null && typeof error === 'object') {
|
|
197
|
+
const message = error.message;
|
|
198
|
+
if (typeof message === 'string')
|
|
199
|
+
return message;
|
|
200
|
+
}
|
|
201
|
+
if (typeof error === 'string')
|
|
202
|
+
return error;
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mapper.js","sourceRoot":"","sources":["../../../src/otel/mapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ResolvedOtelConfig } from '../define_config.js';
|
|
2
|
+
import type { LogExportInput, SpanExportInput } from './mapper.js';
|
|
3
|
+
/** What `telescope_otel_exporting_store.ts` calls per mapped entry. */
|
|
4
|
+
export interface OtelExporter {
|
|
5
|
+
exportSpan(input: SpanExportInput): void;
|
|
6
|
+
exportLog(input: LogExportInput): void;
|
|
7
|
+
/** Flush + shut down both providers. Called at telescope provider shutdown. */
|
|
8
|
+
shutdown(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Build the OTel exporter from resolved config. Each call constructs its own
|
|
12
|
+
* private `BasicTracerProvider` + `LoggerProvider` (with a `BatchSpanProcessor` /
|
|
13
|
+
* `BatchLogRecordProcessor` batching to the configured OTLP/HTTP endpoint) — cheap
|
|
14
|
+
* enough to build once at provider boot and reuse for the process lifetime.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createOtelExporter(config: ResolvedOtelConfig): OtelExporter;
|
|
17
|
+
//# sourceMappingURL=otel_exporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel_exporter.d.ts","sourceRoot":"","sources":["../../../src/otel/otel_exporter.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA0BnE,uEAAuE;AACvE,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACvC,+EAA+E;IAC/E,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAaD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CAmE3E"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { context as otelContext, trace as otelTrace, SpanKind, SpanStatusCode, TraceFlags, } from '@opentelemetry/api';
|
|
2
|
+
import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
|
|
3
|
+
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
4
|
+
import { resourceFromAttributes } from '@opentelemetry/resources';
|
|
5
|
+
import { BatchLogRecordProcessor, LoggerProvider } from '@opentelemetry/sdk-logs';
|
|
6
|
+
import { BasicTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
|
|
7
|
+
/**
|
|
8
|
+
* THE ONLY FILE in this package that imports `@opentelemetry/*` at the module
|
|
9
|
+
* top level. It is loaded exclusively via a dynamic `import()` from
|
|
10
|
+
* `telescope_provider.ts`'s `applyOtel`, and ONLY when `config.otel.enabled` is
|
|
11
|
+
* `true` — so a host who never turns this on never pays for (or needs to install)
|
|
12
|
+
* any OTel package. Mirrors the exact convention `stores/factory.ts` uses for the
|
|
13
|
+
* `lucid` driver's peer dependency.
|
|
14
|
+
*
|
|
15
|
+
* Deliberately minimal: `BasicTracerProvider`/`LoggerProvider` from `sdk-trace-base`
|
|
16
|
+
* / `sdk-logs` plus their OTLP/HTTP exporters — no auto-instrumentation SDK, no
|
|
17
|
+
* Node context-manager registration, no global provider registration
|
|
18
|
+
* (`trace.setGlobalTracerProvider` is never called). This bridge owns a PRIVATE
|
|
19
|
+
* tracer/logger pair and reads span context explicitly per call — it never
|
|
20
|
+
* touches (or conflicts with) a host's own OTel setup (e.g. `@adonisjs/otel`),
|
|
21
|
+
* which may already have its own global provider wired for live request tracing.
|
|
22
|
+
*/
|
|
23
|
+
/** A non-existent parent span id used to synthesize a "remote parent" `SpanContext`
|
|
24
|
+
* carrying only a known trace id (see the module doc on `mapper.ts` for why: telescope
|
|
25
|
+
* only ever learns a trace ID, never a real parent span id, for an already-finished
|
|
26
|
+
* diagnostics event). Any valid (non-all-zero) 16-hex value works — Tempo/Grafana group
|
|
27
|
+
* by trace id, so this never needs to resolve to a real span. */
|
|
28
|
+
const SYNTHETIC_PARENT_SPAN_ID = '0000000000000001';
|
|
29
|
+
/** Build the `Context` carrying a synthesized remote-parent `SpanContext` for `traceId`. */
|
|
30
|
+
function contextFor(traceId) {
|
|
31
|
+
if (traceId === null)
|
|
32
|
+
return undefined;
|
|
33
|
+
return otelTrace.setSpanContext(otelContext.active(), {
|
|
34
|
+
traceId,
|
|
35
|
+
spanId: SYNTHETIC_PARENT_SPAN_ID,
|
|
36
|
+
traceFlags: TraceFlags.SAMPLED,
|
|
37
|
+
isRemote: true,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Build the OTel exporter from resolved config. Each call constructs its own
|
|
42
|
+
* private `BasicTracerProvider` + `LoggerProvider` (with a `BatchSpanProcessor` /
|
|
43
|
+
* `BatchLogRecordProcessor` batching to the configured OTLP/HTTP endpoint) — cheap
|
|
44
|
+
* enough to build once at provider boot and reuse for the process lifetime.
|
|
45
|
+
*/
|
|
46
|
+
export function createOtelExporter(config) {
|
|
47
|
+
const resource = resourceFromAttributes({ 'service.name': config.serviceName });
|
|
48
|
+
const traceExporter = new OTLPTraceExporter({
|
|
49
|
+
url: `${config.endpoint}${config.tracesPath}`,
|
|
50
|
+
headers: config.headers,
|
|
51
|
+
timeoutMillis: config.timeoutMs,
|
|
52
|
+
});
|
|
53
|
+
const tracerProvider = new BasicTracerProvider({
|
|
54
|
+
resource,
|
|
55
|
+
spanProcessors: [new BatchSpanProcessor(traceExporter)],
|
|
56
|
+
});
|
|
57
|
+
const tracer = tracerProvider.getTracer('@adonis-agora/telescope');
|
|
58
|
+
const logExporter = new OTLPLogExporter({
|
|
59
|
+
url: `${config.endpoint}${config.logsPath}`,
|
|
60
|
+
headers: config.headers,
|
|
61
|
+
timeoutMillis: config.timeoutMs,
|
|
62
|
+
});
|
|
63
|
+
const loggerProvider = new LoggerProvider({
|
|
64
|
+
resource,
|
|
65
|
+
processors: [new BatchLogRecordProcessor({ exporter: logExporter })],
|
|
66
|
+
});
|
|
67
|
+
const logger = loggerProvider.getLogger('@adonis-agora/telescope');
|
|
68
|
+
return {
|
|
69
|
+
exportSpan(input) {
|
|
70
|
+
const span = tracer.startSpan(input.name, {
|
|
71
|
+
startTime: input.startTimeMs,
|
|
72
|
+
kind: SpanKind.INTERNAL,
|
|
73
|
+
attributes: input.attributes,
|
|
74
|
+
}, contextFor(input.traceId) ?? otelContext.active());
|
|
75
|
+
if (input.status === 'ERROR') {
|
|
76
|
+
span.setStatus({
|
|
77
|
+
code: SpanStatusCode.ERROR,
|
|
78
|
+
...(input.errorMessage !== undefined ? { message: input.errorMessage } : {}),
|
|
79
|
+
});
|
|
80
|
+
if (input.errorMessage !== undefined)
|
|
81
|
+
span.recordException(input.errorMessage);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
85
|
+
}
|
|
86
|
+
span.end(input.endTimeMs);
|
|
87
|
+
},
|
|
88
|
+
exportLog(input) {
|
|
89
|
+
// `input.severityNumber` is already the OTel `SeverityNumber` numeric value
|
|
90
|
+
// (mapper.ts documents the 9/13/17 literals it uses) — passed through
|
|
91
|
+
// verbatim so this file needn't import `@opentelemetry/api-logs` at all.
|
|
92
|
+
const ctx = contextFor(input.traceId);
|
|
93
|
+
logger.emit({
|
|
94
|
+
body: input.body,
|
|
95
|
+
timestamp: input.timestampMs,
|
|
96
|
+
severityNumber: input.severityNumber,
|
|
97
|
+
severityText: input.severityText,
|
|
98
|
+
attributes: input.attributes,
|
|
99
|
+
...(ctx !== undefined ? { context: ctx } : {}),
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
async shutdown() {
|
|
103
|
+
await Promise.allSettled([tracerProvider.shutdown(), loggerProvider.shutdown()]);
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=otel_exporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel_exporter.js","sourceRoot":"","sources":["../../../src/otel/otel_exporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Entry, RecordInput } from '../entry.js';
|
|
2
|
+
import type { EntryQuery, TelescopeStore } from '../store.js';
|
|
3
|
+
import type { OtelExporter } from './otel_exporter.js';
|
|
4
|
+
/**
|
|
5
|
+
* A {@link TelescopeStore} decorator that exports each PERSISTED entry (of a
|
|
6
|
+
* configured `entryTypes`) to an OTel Collector via {@link OtelExporter}, as
|
|
7
|
+
* either a span (has a duration) or a log record (point-in-time) — see
|
|
8
|
+
* `mapper.ts` for the exact mapping.
|
|
9
|
+
*
|
|
10
|
+
* Placed in the provider's chain the SAME way {@link
|
|
11
|
+
* import('../stream/streaming_store.js').StreamingTelescopeStore} is: AFTER
|
|
12
|
+
* redaction and sampling, so it only ever sees the final, already-scrubbed entry
|
|
13
|
+
* that actually got stored:
|
|
14
|
+
*
|
|
15
|
+
* - **Redaction**: `record()` delegates to `inner.record()` FIRST and exports
|
|
16
|
+
* from the RETURNED entry, never the raw input — so whatever the redacting
|
|
17
|
+
* decorator masked is what leaves the process as OTel attributes/log bodies,
|
|
18
|
+
* never the pre-redaction content. This is deliberate ordering, not an
|
|
19
|
+
* accident: exporting to an external Collector is a strictly bigger
|
|
20
|
+
* exfiltration surface than the local Telescope store, so it must never see
|
|
21
|
+
* anything the local store itself wasn't already allowed to keep.
|
|
22
|
+
* - **Sampling**: a sampled-away entry comes back with `sequence: -1` (the
|
|
23
|
+
* sampling decorator's synthetic placeholder, never persisted) — skipped here
|
|
24
|
+
* exactly like `StreamingTelescopeStore` skips it, so a dropped-from-storage
|
|
25
|
+
* entry costs no OTel export either (same tail-sampling decision, no separate
|
|
26
|
+
* OTel-side sampling knob; see the `otel` docs page for why this was the
|
|
27
|
+
* chosen default over an independent rate).
|
|
28
|
+
* - **Overload guard**: checked EXPLICITLY here (`getTelescopeRuntime().paused`)
|
|
29
|
+
* before doing any export work. This is IN ADDITION to whatever the ingestion
|
|
30
|
+
* entry point itself does — it guarantees that even if a producer's `paused`
|
|
31
|
+
* check has already let an entry through, no NEW export work (an OTLP HTTP
|
|
32
|
+
* call) starts while the guard has shed load. The entry is still recorded/
|
|
33
|
+
* returned normally either way; only the export side-effect is skipped.
|
|
34
|
+
*/
|
|
35
|
+
export declare class OtelExportingTelescopeStore implements TelescopeStore {
|
|
36
|
+
private readonly inner;
|
|
37
|
+
private readonly exporter;
|
|
38
|
+
private readonly entryTypes;
|
|
39
|
+
constructor(inner: TelescopeStore, exporter: OtelExporter, entryTypes: readonly string[]);
|
|
40
|
+
record<TContent>(input: RecordInput<TContent>): Promise<Entry<TContent>>;
|
|
41
|
+
/** Map + export one entry, swallowing every failure — observability must never break recording. */
|
|
42
|
+
private export;
|
|
43
|
+
get(id: string): Promise<Entry | null>;
|
|
44
|
+
list(query?: EntryQuery): Promise<Entry[]>;
|
|
45
|
+
count(): Promise<number>;
|
|
46
|
+
prune(olderThan: Date, keepLast?: number): Promise<number>;
|
|
47
|
+
clear(): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=otel_exporting_store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel_exporting_store.d.ts","sourceRoot":"","sources":["../../../src/otel/otel_exporting_store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,2BAA4B,YAAW,cAAc;IAI9D,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ3B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IAEjD,YACmB,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,YAAY,EACvC,UAAU,EAAE,SAAS,MAAM,EAAE,EAG9B;IAEK,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAM7E;IAED,mGAAmG;IACnG,OAAO,CAAC,MAAM;IAcd,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAErC;IAED,IAAI,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAEzC;IAED,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAEvB;IAED,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEzD;IAED,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAErB;CACF"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { getTelescopeRuntime } from '../registry.js';
|
|
2
|
+
import { mapEntryToOtel } from './mapper.js';
|
|
3
|
+
/**
|
|
4
|
+
* A {@link TelescopeStore} decorator that exports each PERSISTED entry (of a
|
|
5
|
+
* configured `entryTypes`) to an OTel Collector via {@link OtelExporter}, as
|
|
6
|
+
* either a span (has a duration) or a log record (point-in-time) — see
|
|
7
|
+
* `mapper.ts` for the exact mapping.
|
|
8
|
+
*
|
|
9
|
+
* Placed in the provider's chain the SAME way {@link
|
|
10
|
+
* import('../stream/streaming_store.js').StreamingTelescopeStore} is: AFTER
|
|
11
|
+
* redaction and sampling, so it only ever sees the final, already-scrubbed entry
|
|
12
|
+
* that actually got stored:
|
|
13
|
+
*
|
|
14
|
+
* - **Redaction**: `record()` delegates to `inner.record()` FIRST and exports
|
|
15
|
+
* from the RETURNED entry, never the raw input — so whatever the redacting
|
|
16
|
+
* decorator masked is what leaves the process as OTel attributes/log bodies,
|
|
17
|
+
* never the pre-redaction content. This is deliberate ordering, not an
|
|
18
|
+
* accident: exporting to an external Collector is a strictly bigger
|
|
19
|
+
* exfiltration surface than the local Telescope store, so it must never see
|
|
20
|
+
* anything the local store itself wasn't already allowed to keep.
|
|
21
|
+
* - **Sampling**: a sampled-away entry comes back with `sequence: -1` (the
|
|
22
|
+
* sampling decorator's synthetic placeholder, never persisted) — skipped here
|
|
23
|
+
* exactly like `StreamingTelescopeStore` skips it, so a dropped-from-storage
|
|
24
|
+
* entry costs no OTel export either (same tail-sampling decision, no separate
|
|
25
|
+
* OTel-side sampling knob; see the `otel` docs page for why this was the
|
|
26
|
+
* chosen default over an independent rate).
|
|
27
|
+
* - **Overload guard**: checked EXPLICITLY here (`getTelescopeRuntime().paused`)
|
|
28
|
+
* before doing any export work. This is IN ADDITION to whatever the ingestion
|
|
29
|
+
* entry point itself does — it guarantees that even if a producer's `paused`
|
|
30
|
+
* check has already let an entry through, no NEW export work (an OTLP HTTP
|
|
31
|
+
* call) starts while the guard has shed load. The entry is still recorded/
|
|
32
|
+
* returned normally either way; only the export side-effect is skipped.
|
|
33
|
+
*/
|
|
34
|
+
export class OtelExportingTelescopeStore {
|
|
35
|
+
inner;
|
|
36
|
+
exporter;
|
|
37
|
+
entryTypes;
|
|
38
|
+
constructor(inner, exporter, entryTypes) {
|
|
39
|
+
this.inner = inner;
|
|
40
|
+
this.exporter = exporter;
|
|
41
|
+
this.entryTypes = new Set(entryTypes);
|
|
42
|
+
}
|
|
43
|
+
async record(input) {
|
|
44
|
+
const entry = await this.inner.record(input);
|
|
45
|
+
if (entry.sequence >= 0 && this.entryTypes.has(entry.type) && !getTelescopeRuntime().paused) {
|
|
46
|
+
this.export(entry);
|
|
47
|
+
}
|
|
48
|
+
return entry;
|
|
49
|
+
}
|
|
50
|
+
/** Map + export one entry, swallowing every failure — observability must never break recording. */
|
|
51
|
+
export(entry) {
|
|
52
|
+
try {
|
|
53
|
+
const mapped = mapEntryToOtel(entry);
|
|
54
|
+
if (mapped === null)
|
|
55
|
+
return;
|
|
56
|
+
if (mapped.kind === 'span') {
|
|
57
|
+
this.exporter.exportSpan(mapped.span);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
this.exporter.exportLog(mapped.log);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
console.error('@adonis-agora/telescope: OTel export failed for one entry:', err);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
get(id) {
|
|
68
|
+
return this.inner.get(id);
|
|
69
|
+
}
|
|
70
|
+
list(query) {
|
|
71
|
+
return this.inner.list(query);
|
|
72
|
+
}
|
|
73
|
+
count() {
|
|
74
|
+
return this.inner.count();
|
|
75
|
+
}
|
|
76
|
+
prune(olderThan, keepLast) {
|
|
77
|
+
return this.inner.prune(olderThan, keepLast);
|
|
78
|
+
}
|
|
79
|
+
clear() {
|
|
80
|
+
return this.inner.clear();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=otel_exporting_store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel_exporting_store.js","sourceRoot":"","sources":["../../../src/otel/otel_exporting_store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,OAAO,2BAA2B;IAInB,KAAK;IACL,QAAQ;IAJV,UAAU,CAAsB;IAEjD,YACmB,KAAqB,EACrB,QAAsB,EACvC,UAA6B;qBAFZ,KAAK;wBACL,QAAQ;QAGzB,IAAI,CAAC,UAAU,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,MAAM,CAAW,KAA4B;QACjD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC7C,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC,MAAM,EAAE,CAAC;YAC5F,IAAI,CAAC,MAAM,CAAC,KAAc,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,mGAAmG;IAC3F,MAAM,CAAC,KAAY;QACzB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;YACrC,IAAI,MAAM,KAAK,IAAI;gBAAE,OAAO;YAC5B,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC3B,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACxC,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,4DAA4D,EAAE,GAAG,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC;IAED,IAAI,CAAC,KAAkB;QACrB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IAED,KAAK;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,SAAe,EAAE,QAAiB;QACtC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;CACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export declare const VERSION = "0.
|
|
2
|
+
export declare const VERSION = "0.20.0";
|
|
3
3
|
export { aggregateCpuProfile } from './aggregate-profile.js';
|
|
4
4
|
export type { CpuProfilerOptions, CpuProfilerResult, InspectorSessionLike, SessionFactory, } from './cpu-profiler.js';
|
|
5
5
|
export { CpuProfiler, defaultSessionFactory } from './cpu-profiler.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export const VERSION = '0.
|
|
2
|
+
export const VERSION = '0.20.0';
|
|
3
3
|
export { aggregateCpuProfile } from './aggregate-profile.js';
|
|
4
4
|
export { CpuProfiler, defaultSessionFactory } from './cpu-profiler.js';
|
|
5
5
|
export { defineConfig, resolveConfig } from './define_config.js';
|