@origintrail-official/dkg-node-ui 10.0.1 → 10.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/chain-cursor-stores.d.ts +45 -0
  2. package/dist/chain-cursor-stores.d.ts.map +1 -0
  3. package/dist/chain-cursor-stores.js +107 -0
  4. package/dist/chain-cursor-stores.js.map +1 -0
  5. package/dist/chat-memory.d.ts +0 -17
  6. package/dist/chat-memory.d.ts.map +1 -1
  7. package/dist/chat-memory.js +6 -33
  8. package/dist/chat-memory.js.map +1 -1
  9. package/dist/db.d.ts +15 -0
  10. package/dist/db.d.ts.map +1 -1
  11. package/dist/db.js +40 -1
  12. package/dist/db.js.map +1 -1
  13. package/dist/index.d.ts +6 -3
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +6 -2
  16. package/dist/index.js.map +1 -1
  17. package/dist/notifications-scope.d.ts +19 -0
  18. package/dist/notifications-scope.d.ts.map +1 -1
  19. package/dist/notifications-scope.js +34 -2
  20. package/dist/notifications-scope.js.map +1 -1
  21. package/dist/otlp-log-worker.d.ts +127 -0
  22. package/dist/otlp-log-worker.d.ts.map +1 -0
  23. package/dist/otlp-log-worker.js +268 -0
  24. package/dist/otlp-log-worker.js.map +1 -0
  25. package/dist/telemetry-resource.d.ts +41 -0
  26. package/dist/telemetry-resource.d.ts.map +1 -0
  27. package/dist/telemetry-resource.js +31 -0
  28. package/dist/telemetry-resource.js.map +1 -0
  29. package/dist/telemetry.d.ts +75 -16
  30. package/dist/telemetry.d.ts.map +1 -1
  31. package/dist/telemetry.js +152 -29
  32. package/dist/telemetry.js.map +1 -1
  33. package/dist-ui/assets/{3d-force-graph-DII0C0lY.js → 3d-force-graph-DRDhpplH.js} +1 -1
  34. package/dist-ui/assets/AgentHub-DdUAxJoy.js +1 -0
  35. package/dist-ui/assets/AgentProfilePage-yI8fA4vv.js +1 -0
  36. package/dist-ui/assets/ApproveWalletsModal-9w2edv7e.js +57 -0
  37. package/dist-ui/assets/ConvictionDetailView-CcQMya-y.js +2 -0
  38. package/dist-ui/assets/Network-DpAKVzwi.js +1 -0
  39. package/dist-ui/assets/OnChainProvenanceCard-DMOm3jLz.js +1 -0
  40. package/dist-ui/assets/{Operations-BC6Cv6cR.js → Operations-DKJFp6hM.js} +3 -3
  41. package/dist-ui/assets/PublishingConviction-1CPHxNwp.js +2 -0
  42. package/dist-ui/assets/Settings-DaYMlGHD.js +1 -0
  43. package/dist-ui/assets/ccip-hCQYqfNz.js +1 -0
  44. package/dist-ui/assets/{index-D0Mz0SVt.js → index-Bh_8bMB0.js} +3 -3
  45. package/dist-ui/assets/{index-ByLJSVQ3.js → index-CVwCoJrM.js} +9 -9
  46. package/dist-ui/assets/index-D5UiTYlY.css +1 -0
  47. package/dist-ui/assets/index-DGpnb_b1.js +1661 -0
  48. package/dist-ui/assets/{jsonld-32FQRO67-B4_tUX65.js → jsonld-32FQRO67-C3B_LjZ-.js} +2 -2
  49. package/dist-ui/assets/{jsonld-D5RXTCJi.js → jsonld-CoPRWQuM.js} +1 -1
  50. package/dist-ui/assets/{renderer-3d-2EVDZII7-BTYEjwma.js → renderer-3d-2EVDZII7-Bx6o7Gge.js} +2 -2
  51. package/dist-ui/index.html +2 -2
  52. package/package.json +14 -3
  53. package/dist-ui/assets/AgentHub-D3eOrb3Z.js +0 -1
  54. package/dist-ui/assets/AgentProfilePage-jB-v9soG.js +0 -1
  55. package/dist-ui/assets/Network-d4igcZQ0.js +0 -1
  56. package/dist-ui/assets/OnChainProvenanceCard-BL6ou6s9.js +0 -1
  57. package/dist-ui/assets/Settings-DXSjvx2a.js +0 -1
  58. package/dist-ui/assets/index-B6UQm9N_.js +0 -1670
  59. package/dist-ui/assets/index-BgRu6zNc.css +0 -1
@@ -0,0 +1,127 @@
1
+ /**
2
+ * OTLP/HTTP log exporter — ships structured log records to an OpenTelemetry
3
+ * collector (or any OTLP/HTTP logs endpoint) as a second, opt-in sink
4
+ * alongside the always-on local SQLite store.
5
+ *
6
+ * Why hand-rolled rather than @opentelemetry/sdk-logs: as of 2026 the OTel JS
7
+ * Logs SDK is still "Development" (Traces/Metrics are Stable). We emit the
8
+ * stable OTLP/HTTP JSON wire format (ExportLogsServiceRequest) directly and
9
+ * reuse the buffer/flush/backoff shape proven by the syslog LogPushWorker.
10
+ *
11
+ * Reliability contract (this must NEVER slow down or crash the node):
12
+ * - push() only appends to a bounded in-memory buffer (drop-oldest on
13
+ * overflow) and returns immediately; it never awaits the network.
14
+ * - flush() runs on a timer, is guarded against overlap, and swallows every
15
+ * error. On a retryable failure the batch is requeued and an exponential
16
+ * backoff (with jitter, honoring Retry-After) is applied. On a
17
+ * non-retryable failure the batch is dropped (logged once).
18
+ * - The flush timer is unref'd so it never keeps the process alive.
19
+ * - Transport is outbound HTTPS push only — no inbound scrape endpoint.
20
+ */
21
+ import type { LogRecord } from '@origintrail-official/dkg-core';
22
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
23
+ export interface OtlpLogWorkerOptions {
24
+ /** Full OTLP/HTTP logs URL, e.g. http://localhost:4318/v1/logs */
25
+ endpoint: string;
26
+ /** Bearer credential for the collector (sent as Authorization: Bearer …). */
27
+ token?: string;
28
+ /** Extra static headers to attach to every request. */
29
+ headers?: Record<string, string>;
30
+ /** Network identifier: 'testnet' | 'mainnet' | 'devnet'. */
31
+ network: string;
32
+ /** Node's libp2p peer ID. */
33
+ peerId: string;
34
+ nodeName?: string;
35
+ version?: string;
36
+ commit?: string;
37
+ /** 'core' | 'edge' */
38
+ role?: string;
39
+ /** Chain id string, e.g. 'base:8453' → resource attr dkg.chain (matches traces/metrics). */
40
+ chainId?: string;
41
+ /** OTel resource service.name. Default 'dkg-node'. */
42
+ serviceName?: string;
43
+ /**
44
+ * Per-node identifier. Becomes the OTel `service.instance.id`, which Loki
45
+ * promotes to the index label `service_instance_id` — this is what a Grafana
46
+ * "pick a node" dashboard variable selects on. Defaults to nodeName, then
47
+ * peerId. Hosted nodes should set a unique `name` in config.
48
+ */
49
+ serviceInstanceId?: string;
50
+ /**
51
+ * Deployment environment (e.g. 'testnet' | 'mainnet'). Becomes the OTel
52
+ * `deployment.environment`, which Loki promotes to the label
53
+ * `deployment_environment`. Defaults to `network`.
54
+ */
55
+ deploymentEnvironment?: string;
56
+ /** Minimum level forwarded remotely. Default 'info' (debug stays local). */
57
+ minLevel?: LogLevel;
58
+ /** Bounded in-memory buffer; drop-oldest on overflow. Default 500. */
59
+ bufferMaxEntries?: number;
60
+ flushIntervalMs?: number;
61
+ requestTimeoutMs?: number;
62
+ /** Initial retry backoff in ms (doubles up to maxBackoffMs). Default 1000. */
63
+ baseBackoffMs?: number;
64
+ /** Ceiling for retry backoff in ms. Default 60000. */
65
+ maxBackoffMs?: number;
66
+ /** Optional diagnostic sink (e.g. the daemon log). Never throws. */
67
+ onError?: (message: string) => void;
68
+ }
69
+ interface OtlpAttribute {
70
+ key: string;
71
+ value: {
72
+ stringValue: string;
73
+ };
74
+ }
75
+ export declare class OtlpLogWorker {
76
+ private buffer;
77
+ private timer;
78
+ private stopped;
79
+ private flushing;
80
+ private nextAttemptAt;
81
+ private backoffMs;
82
+ private droppedNonRetryable;
83
+ private loggedNonRetryable;
84
+ private readonly endpoint;
85
+ private readonly minRank;
86
+ private readonly maxBuffer;
87
+ private readonly flushIntervalMs;
88
+ private readonly requestTimeoutMs;
89
+ private readonly baseBackoffMs;
90
+ private readonly maxBackoffMs;
91
+ private readonly authHeaders;
92
+ private readonly resourceAttrs;
93
+ private readonly scopeVersion;
94
+ private readonly onError;
95
+ constructor(opts: OtlpLogWorkerOptions);
96
+ /** Append a record. Filters below minLevel; never awaits the network. */
97
+ push(record: LogRecord): void;
98
+ start(): void;
99
+ stop(): void;
100
+ /**
101
+ * Async teardown for the daemon shutdown / telemetry-disable path: stop the
102
+ * timer and AWAIT a final flush, so the caller can guarantee no batch is still
103
+ * being sent (or stranded in the buffer) once this resolves. stop() is the
104
+ * fire-and-forget variant for callers that can't await.
105
+ */
106
+ shutdown(): Promise<void>;
107
+ /** Test/diagnostic hook. */
108
+ pending(): number;
109
+ private flush;
110
+ private requeue;
111
+ private scheduleBackoff;
112
+ private post;
113
+ private buildPayload;
114
+ }
115
+ /**
116
+ * PURE OTLP/HTTP logs wire-format encoder (ExportLogsServiceRequest JSON).
117
+ * Extracted from `OtlpLogWorker` so the protocol/payload shape is independent
118
+ * from the worker's scheduling + retry/backoff mechanics (review: "OtlpLogWorker
119
+ * mixes too many concerns") — change the wire shape here without touching the
120
+ * buffer/timer logic, and vice-versa. No side effects, no `this`.
121
+ */
122
+ export declare function encodeOtlpLogPayload(batch: ReadonlyArray<{
123
+ r: LogRecord;
124
+ tsMs: number;
125
+ }>, resourceAttrs: ReadonlyArray<OtlpAttribute>, scopeVersion?: string): string;
126
+ export {};
127
+ //# sourceMappingURL=otlp-log-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otlp-log-worker.d.ts","sourceRoot":"","sources":["../src/otlp-log-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,268 @@
1
+ /**
2
+ * OTLP/HTTP log exporter — ships structured log records to an OpenTelemetry
3
+ * collector (or any OTLP/HTTP logs endpoint) as a second, opt-in sink
4
+ * alongside the always-on local SQLite store.
5
+ *
6
+ * Why hand-rolled rather than @opentelemetry/sdk-logs: as of 2026 the OTel JS
7
+ * Logs SDK is still "Development" (Traces/Metrics are Stable). We emit the
8
+ * stable OTLP/HTTP JSON wire format (ExportLogsServiceRequest) directly and
9
+ * reuse the buffer/flush/backoff shape proven by the syslog LogPushWorker.
10
+ *
11
+ * Reliability contract (this must NEVER slow down or crash the node):
12
+ * - push() only appends to a bounded in-memory buffer (drop-oldest on
13
+ * overflow) and returns immediately; it never awaits the network.
14
+ * - flush() runs on a timer, is guarded against overlap, and swallows every
15
+ * error. On a retryable failure the batch is requeued and an exponential
16
+ * backoff (with jitter, honoring Retry-After) is applied. On a
17
+ * non-retryable failure the batch is dropped (logged once).
18
+ * - The flush timer is unref'd so it never keeps the process alive.
19
+ * - Transport is outbound HTTPS push only — no inbound scrape endpoint.
20
+ */
21
+ import { buildTelemetryResourceAttrs } from './telemetry-resource.js';
22
+ // OpenTelemetry severity numbers (logs data model).
23
+ const OTEL_SEVERITY = {
24
+ debug: { num: 5, text: 'DEBUG' },
25
+ info: { num: 9, text: 'INFO' },
26
+ warn: { num: 13, text: 'WARN' },
27
+ error: { num: 17, text: 'ERROR' },
28
+ };
29
+ const LEVEL_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
30
+ const RETRYABLE_STATUS = new Set([408, 429, 500, 502, 503, 504]);
31
+ const DEFAULTS = {
32
+ flushIntervalMs: 2_000,
33
+ maxBuffer: 500,
34
+ maxBatch: 256,
35
+ requestTimeoutMs: 10_000,
36
+ baseBackoffMs: 1_000,
37
+ maxBackoffMs: 60_000,
38
+ serviceName: 'dkg-node',
39
+ minLevel: 'info',
40
+ };
41
+ function attr(key, value) {
42
+ if (value == null || value === '')
43
+ return null;
44
+ return { key, value: { stringValue: String(value) } };
45
+ }
46
+ export class OtlpLogWorker {
47
+ buffer = [];
48
+ timer = null;
49
+ stopped = false;
50
+ flushing = false;
51
+ nextAttemptAt = 0;
52
+ backoffMs = 0;
53
+ droppedNonRetryable = 0;
54
+ loggedNonRetryable = false;
55
+ endpoint;
56
+ minRank;
57
+ maxBuffer;
58
+ flushIntervalMs;
59
+ requestTimeoutMs;
60
+ baseBackoffMs;
61
+ maxBackoffMs;
62
+ authHeaders;
63
+ resourceAttrs;
64
+ scopeVersion;
65
+ onError;
66
+ constructor(opts) {
67
+ this.endpoint = opts.endpoint;
68
+ this.minRank = LEVEL_RANK[opts.minLevel ?? DEFAULTS.minLevel] ?? LEVEL_RANK.info;
69
+ this.maxBuffer = Math.max(1, opts.bufferMaxEntries ?? DEFAULTS.maxBuffer);
70
+ this.flushIntervalMs = opts.flushIntervalMs ?? DEFAULTS.flushIntervalMs;
71
+ this.requestTimeoutMs = opts.requestTimeoutMs ?? DEFAULTS.requestTimeoutMs;
72
+ this.baseBackoffMs = opts.baseBackoffMs ?? DEFAULTS.baseBackoffMs;
73
+ this.maxBackoffMs = opts.maxBackoffMs ?? DEFAULTS.maxBackoffMs;
74
+ this.scopeVersion = opts.version || undefined;
75
+ this.onError = opts.onError ?? (() => { });
76
+ this.authHeaders = { 'content-type': 'application/json', ...(opts.headers ?? {}) };
77
+ if (opts.token)
78
+ this.authHeaders['authorization'] = `Bearer ${opts.token}`;
79
+ // Built from the SHARED resource model so the log resource (and the Loki
80
+ // labels promoted from service.name / service.instance.id /
81
+ // deployment.environment / dkg.node.role) can never drift from the
82
+ // traces/metrics resource. See ./telemetry-resource.
83
+ this.resourceAttrs = Object.entries(buildTelemetryResourceAttrs({
84
+ serviceName: opts.serviceName ?? DEFAULTS.serviceName,
85
+ serviceVersion: opts.version,
86
+ serviceInstanceId: opts.serviceInstanceId,
87
+ deploymentEnvironment: opts.deploymentEnvironment,
88
+ network: opts.network,
89
+ peerId: opts.peerId,
90
+ nodeName: opts.nodeName,
91
+ nodeRole: opts.role,
92
+ commit: opts.commit,
93
+ chainId: opts.chainId,
94
+ })).map(([key, value]) => ({ key, value: { stringValue: value } }));
95
+ }
96
+ /** Append a record. Filters below minLevel; never awaits the network. */
97
+ push(record) {
98
+ if ((LEVEL_RANK[record.level] ?? LEVEL_RANK.info) < this.minRank)
99
+ return;
100
+ if (this.buffer.length >= this.maxBuffer)
101
+ this.buffer.shift();
102
+ this.buffer.push({ r: record, tsMs: Date.now() });
103
+ }
104
+ start() {
105
+ if (this.timer)
106
+ return;
107
+ this.stopped = false;
108
+ this.timer = setInterval(() => {
109
+ void this.flush();
110
+ }, this.flushIntervalMs);
111
+ this.timer.unref();
112
+ }
113
+ stop() {
114
+ this.stopped = true;
115
+ if (this.timer) {
116
+ clearInterval(this.timer);
117
+ this.timer = null;
118
+ }
119
+ // Best-effort final flush; failures are swallowed. Fire-and-forget — use
120
+ // shutdown() when you need to AWAIT the final flush (orderly teardown).
121
+ void this.flush(true);
122
+ }
123
+ /**
124
+ * Async teardown for the daemon shutdown / telemetry-disable path: stop the
125
+ * timer and AWAIT a final flush, so the caller can guarantee no batch is still
126
+ * being sent (or stranded in the buffer) once this resolves. stop() is the
127
+ * fire-and-forget variant for callers that can't await.
128
+ */
129
+ async shutdown() {
130
+ this.stopped = true;
131
+ if (this.timer) {
132
+ clearInterval(this.timer);
133
+ this.timer = null;
134
+ }
135
+ await this.flush(true).catch(() => { });
136
+ }
137
+ /** Test/diagnostic hook. */
138
+ pending() {
139
+ return this.buffer.length;
140
+ }
141
+ async flush(force = false) {
142
+ if (this.flushing)
143
+ return;
144
+ if (this.stopped && !force)
145
+ return;
146
+ if (this.buffer.length === 0)
147
+ return;
148
+ if (!force && Date.now() < this.nextAttemptAt)
149
+ return;
150
+ this.flushing = true;
151
+ const batch = this.buffer.splice(0, DEFAULTS.maxBatch);
152
+ try {
153
+ const body = this.buildPayload(batch);
154
+ const res = await this.post(body);
155
+ if (res.ok) {
156
+ this.backoffMs = 0;
157
+ this.nextAttemptAt = 0;
158
+ }
159
+ else if (RETRYABLE_STATUS.has(res.status)) {
160
+ this.requeue(batch);
161
+ this.scheduleBackoff(res.retryAfterMs);
162
+ }
163
+ else {
164
+ // Non-retryable (e.g. 400/401/403): dropping is correct — retrying
165
+ // a malformed/unauthorized request forever would just grow the buffer.
166
+ this.droppedNonRetryable += batch.length;
167
+ if (!this.loggedNonRetryable) {
168
+ this.loggedNonRetryable = true;
169
+ this.onError(`dropping logs — collector returned ${res.status} (non-retryable); check endpoint/token. ` +
170
+ `${this.droppedNonRetryable} record(s) dropped so far.`);
171
+ }
172
+ }
173
+ }
174
+ catch (err) {
175
+ // Network/timeout error → treat as retryable.
176
+ this.requeue(batch);
177
+ this.scheduleBackoff();
178
+ void err;
179
+ }
180
+ finally {
181
+ this.flushing = false;
182
+ }
183
+ }
184
+ requeue(batch) {
185
+ this.buffer.unshift(...batch);
186
+ while (this.buffer.length > this.maxBuffer)
187
+ this.buffer.shift();
188
+ }
189
+ scheduleBackoff(retryAfterMs) {
190
+ const next = this.backoffMs === 0 ? this.baseBackoffMs : Math.min(this.backoffMs * 2, this.maxBackoffMs);
191
+ this.backoffMs = next;
192
+ const jitter = next * 0.2 * Math.random();
193
+ const delay = retryAfterMs != null ? Math.max(retryAfterMs, next) : next + jitter;
194
+ this.nextAttemptAt = Date.now() + delay;
195
+ }
196
+ async post(body) {
197
+ const ac = new AbortController();
198
+ const timer = setTimeout(() => ac.abort(), this.requestTimeoutMs);
199
+ try {
200
+ const res = await fetch(this.endpoint, {
201
+ method: 'POST',
202
+ headers: this.authHeaders,
203
+ body,
204
+ signal: ac.signal,
205
+ });
206
+ // Drain the body so the socket can be reused / freed.
207
+ await res.arrayBuffer().catch(() => { });
208
+ let retryAfterMs;
209
+ const ra = res.headers.get('retry-after');
210
+ if (ra) {
211
+ const secs = Number(ra);
212
+ if (!Number.isNaN(secs))
213
+ retryAfterMs = secs * 1000;
214
+ }
215
+ return { ok: res.ok, status: res.status, retryAfterMs };
216
+ }
217
+ finally {
218
+ clearTimeout(timer);
219
+ }
220
+ }
221
+ buildPayload(batch) {
222
+ return encodeOtlpLogPayload(batch, this.resourceAttrs, this.scopeVersion);
223
+ }
224
+ }
225
+ /**
226
+ * PURE OTLP/HTTP logs wire-format encoder (ExportLogsServiceRequest JSON).
227
+ * Extracted from `OtlpLogWorker` so the protocol/payload shape is independent
228
+ * from the worker's scheduling + retry/backoff mechanics (review: "OtlpLogWorker
229
+ * mixes too many concerns") — change the wire shape here without touching the
230
+ * buffer/timer logic, and vice-versa. No side effects, no `this`.
231
+ */
232
+ export function encodeOtlpLogPayload(batch, resourceAttrs, scopeVersion) {
233
+ const logRecords = batch.map(({ r, tsMs }) => {
234
+ const sev = OTEL_SEVERITY[r.level] ?? OTEL_SEVERITY.info;
235
+ const nano = String(tsMs * 1_000_000);
236
+ return {
237
+ timeUnixNano: nano,
238
+ observedTimeUnixNano: nano,
239
+ severityNumber: sev.num,
240
+ severityText: sev.text,
241
+ body: { stringValue: r.message },
242
+ // W3C trace correlation — OTLP top-level fields (hex), not attributes.
243
+ // Present only when the log was emitted inside a recording span.
244
+ ...(r.traceId ? { traceId: r.traceId } : {}),
245
+ ...(r.spanId ? { spanId: r.spanId } : {}),
246
+ attributes: [
247
+ attr('dkg.operation_id', r.operationId),
248
+ attr('dkg.operation_name', r.operationName),
249
+ attr('dkg.source_operation_id', r.sourceOperationId),
250
+ attr('dkg.module', r.module),
251
+ ].filter((a) => a !== null),
252
+ };
253
+ });
254
+ return JSON.stringify({
255
+ resourceLogs: [
256
+ {
257
+ resource: { attributes: resourceAttrs },
258
+ scopeLogs: [
259
+ {
260
+ scope: { name: 'dkg-node', version: scopeVersion },
261
+ logRecords,
262
+ },
263
+ ],
264
+ },
265
+ ],
266
+ });
267
+ }
268
+ //# sourceMappingURL=otlp-log-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otlp-log-worker.js","sourceRoot":"","sources":["../src/otlp-log-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * THE one canonical node-identity → OTel resource-attribute mapping, shared by
3
+ * BOTH the hand-rolled log exporter (`OtlpLogWorker`) and the OTel SDK bootstrap
4
+ * (`telemetry.ts`). Keeping a single builder is the whole point: logs, traces,
5
+ * and metrics describe the same node, so a key/default must change in exactly
6
+ * one place or Loki labels, trace resources, and metric resources silently drift
7
+ * apart (review: "resource identity is duplicated between logs and traces/metrics").
8
+ *
9
+ * Pure (no OTel SDK, no Node built-ins) → safe to import from anywhere.
10
+ */
11
+ export interface TelemetryResourceInput {
12
+ /** OTel service.name. Default 'dkg-node'. */
13
+ serviceName?: string;
14
+ /** OTel service.version (node build version). */
15
+ serviceVersion?: string;
16
+ /**
17
+ * Per-node id → service.instance.id (the Grafana node selector / Loki
18
+ * `service_instance_id` label). Falls back to nodeName then peerId so logs and
19
+ * traces/metrics resolve the SAME instance id even if a caller omits it.
20
+ */
21
+ serviceInstanceId?: string;
22
+ /** Explicit deployment.environment; defaults to `network` when unset. */
23
+ deploymentEnvironment?: string;
24
+ /** testnet | mainnet | devnet → deployment.environment (default) + dkg.network. */
25
+ network?: string;
26
+ peerId?: string;
27
+ nodeName?: string;
28
+ /** 'core' | 'edge' → dkg.node.role */
29
+ nodeRole?: string;
30
+ commit?: string;
31
+ /** e.g. 'base:8453' → dkg.chain */
32
+ chainId?: string;
33
+ }
34
+ /**
35
+ * Build the resource attribute map. Standard OTel keys (service.*, deployment.*)
36
+ * plus the DKG identity keys (dkg.network, dkg.peer_id, dkg.node.name,
37
+ * dkg.node.role, dkg.chain, dkg.commit). Unset values are omitted so the
38
+ * resource never carries empty strings.
39
+ */
40
+ export declare function buildTelemetryResourceAttrs(r?: TelemetryResourceInput): Record<string, string>;
41
+ //# sourceMappingURL=telemetry-resource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry-resource.d.ts","sourceRoot":"","sources":["../src/telemetry-resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAsB;IACrC,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,GAAE,sBAA2B,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAclG"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Build the resource attribute map. Standard OTel keys (service.*, deployment.*)
3
+ * plus the DKG identity keys (dkg.network, dkg.peer_id, dkg.node.name,
4
+ * dkg.node.role, dkg.chain, dkg.commit). Unset values are omitted so the
5
+ * resource never carries empty strings.
6
+ */
7
+ export function buildTelemetryResourceAttrs(r = {}) {
8
+ const attrs = { 'service.name': r.serviceName || 'dkg-node' };
9
+ if (r.serviceVersion)
10
+ attrs['service.version'] = r.serviceVersion;
11
+ const instanceId = r.serviceInstanceId || r.nodeName || r.peerId;
12
+ if (instanceId)
13
+ attrs['service.instance.id'] = instanceId;
14
+ const env = r.deploymentEnvironment || r.network;
15
+ if (env)
16
+ attrs['deployment.environment'] = env;
17
+ if (r.network)
18
+ attrs['dkg.network'] = r.network;
19
+ if (r.peerId)
20
+ attrs['dkg.peer_id'] = r.peerId;
21
+ if (r.nodeName)
22
+ attrs['dkg.node.name'] = r.nodeName;
23
+ if (r.nodeRole)
24
+ attrs['dkg.node.role'] = r.nodeRole;
25
+ if (r.commit)
26
+ attrs['dkg.commit'] = r.commit;
27
+ if (r.chainId)
28
+ attrs['dkg.chain'] = r.chainId;
29
+ return attrs;
30
+ }
31
+ //# sourceMappingURL=telemetry-resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry-resource.js","sourceRoot":"","sources":["../src/telemetry-resource.ts"],"names":[],"mappings":"AAkCA;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CAAC,IAA4B,EAAE;IACxE,MAAM,KAAK,GAA2B,EAAE,cAAc,EAAE,CAAC,CAAC,WAAW,IAAI,UAAU,EAAE,CAAC;IACtF,IAAI,CAAC,CAAC,cAAc;QAAE,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC;IAClE,MAAM,UAAU,GAAG,CAAC,CAAC,iBAAiB,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,CAAC;IACjE,IAAI,UAAU;QAAE,KAAK,CAAC,qBAAqB,CAAC,GAAG,UAAU,CAAC;IAC1D,MAAM,GAAG,GAAG,CAAC,CAAC,qBAAqB,IAAI,CAAC,CAAC,OAAO,CAAC;IACjD,IAAI,GAAG;QAAE,KAAK,CAAC,wBAAwB,CAAC,GAAG,GAAG,CAAC;IAC/C,IAAI,CAAC,CAAC,OAAO;QAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;IAChD,IAAI,CAAC,CAAC,MAAM;QAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,IAAI,CAAC,CAAC,QAAQ;QAAE,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;IACpD,IAAI,CAAC,CAAC,QAAQ;QAAE,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;IACpD,IAAI,CAAC,CAAC,MAAM;QAAE,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,IAAI,CAAC,CAAC,OAAO;QAAE,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;IAC9C,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -1,12 +1,58 @@
1
1
  /**
2
- * Optional OpenTelemetry integration for the Node UI.
3
- * When enabled (via config), exports metrics and optionally traces to an OTLP endpoint.
4
- * operationId is set as the trace/span attribute for correlation with the dashboard.
2
+ * OpenTelemetry SDK bootstrap for a DKG node (boot side, daemon-only consumer).
5
3
  *
6
- * To enable: add @opentelemetry/api, @opentelemetry/sdk-metrics, and
7
- * @opentelemetry/exporter-metrics-otlp-http; then implement registerMeter() and
8
- * use the same metric names below. For traces, use @opentelemetry/sdk-trace-base
9
- * and set span attributes { 'dkg.operation_id': operationId }.
4
+ * Registers the global Tracer + Meter providers at daemon startup so that the
5
+ * call-site facade in `@origintrail-official/dkg-core` (getTracer/withSpan/
6
+ * getMetrics) used across agent/publisher/chain/sync produces real spans and
7
+ * metrics. When telemetry is disabled, or a signal has no endpoint, this
8
+ * registers NOTHING: the core facade then talks to the API's built-in no-op
9
+ * providers (zero cost, no outbound calls).
10
+ *
11
+ * Logs are NOT handled here — they stay on the hand-rolled `OtlpLogWorker`
12
+ * (bounded buffer + retry + at-source redaction); the OTel Logs SDK is still
13
+ * "Development". This module only wires traces + metrics, and shares ONE
14
+ * Resource with the log worker so all three signals describe the same node.
15
+ *
16
+ * BROWSER SAFETY: the heavy Node-only OTel SDK packages (sdk-trace-node,
17
+ * sdk-metrics, exporter-*-otlp-proto, resources) and `@origintrail-official/dkg-core`
18
+ * are loaded via DYNAMIC import inside `initTelemetry`/`shutdownTelemetry`, never
19
+ * statically. Only `@opentelemetry/api` (browser-safe, no Node built-ins) is a
20
+ * static import. That keeps this module — and the package root that re-exports
21
+ * it — free of server-only code in any static bundle graph: a browser bundler
22
+ * never pulls the Node SDK because it sits behind a runtime `import()` that the
23
+ * UI never triggers.
24
+ */
25
+ import { type TelemetryResourceInput } from './telemetry-resource.js';
26
+ /**
27
+ * Stable resource identity, shared by logs + traces + metrics. Single canonical
28
+ * type — re-exported alias of `TelemetryResourceInput` (the shared resource
29
+ * model in ./telemetry-resource) so logs and traces/metrics can't drift.
30
+ */
31
+ export type TelemetryResource = TelemetryResourceInput;
32
+ export interface OtlpSignalConfig {
33
+ endpoint?: string;
34
+ /** Bearer token → Authorization header. */
35
+ token?: string;
36
+ headers?: Record<string, string>;
37
+ /** Per-signal opt-out. A signal is on only when it has an endpoint AND this is not false. */
38
+ enabled?: boolean;
39
+ }
40
+ export interface TelemetryInitConfig {
41
+ /** Master gate. When false, nothing is registered. */
42
+ enabled?: boolean;
43
+ resource?: TelemetryResource;
44
+ traces?: OtlpSignalConfig & {
45
+ sampleRatio?: number;
46
+ };
47
+ metrics?: OtlpSignalConfig & {
48
+ exportIntervalMs?: number;
49
+ };
50
+ }
51
+ /**
52
+ * LEGACY config shape (pre-PR #1317 stub). Kept so old JS callers that pass
53
+ * `{ enabled, metricsEndpoint, serviceName }` keep working — `initTelemetry`
54
+ * normalizes it into `TelemetryInitConfig` (metricsEndpoint → metrics.endpoint).
55
+ * @deprecated Use `TelemetryInitConfig` (traces/metrics signal blocks).
10
56
  */
11
57
  export interface TelemetryConfig {
12
58
  enabled?: boolean;
@@ -16,20 +62,33 @@ export interface TelemetryConfig {
16
62
  serviceName?: string;
17
63
  }
18
64
  /**
19
- * Initialize telemetry. No-op if disabled or OTel packages not installed.
20
- * Call once at daemon startup.
65
+ * Initialize traces + metrics. No-op when disabled or when a signal has no
66
+ * endpoint. Safe to call once at daemon boot. Idempotent (subsequent calls are
67
+ * ignored once configured). Async because the Node OTel SDK is dynamically
68
+ * imported (see the BROWSER SAFETY note above).
21
69
  */
22
- export declare function initTelemetry(_config: TelemetryConfig): void;
70
+ export declare function initTelemetry(input: TelemetryInitConfig | TelemetryConfig): Promise<void>;
71
+ /** True once EITHER signal (traces or metrics) has registered a real provider. */
72
+ export declare function isTelemetryConfigured(): boolean;
23
73
  /**
24
- * Record a gauge value for export. No-op when telemetry is disabled.
25
- * Metric names match dashboard: dkg.network.peers, dkg.knowledge.triples, dkg.system.cpu_percent, etc.
74
+ * Flush + shut down providers. Used both at daemon teardown AND when telemetry
75
+ * is turned off via the runtime master gate, so it must FULLY reverse
76
+ * `initTelemetry`: stop the exporters, then clear the OTel API globals so a
77
+ * later `initTelemetry` (live re-enable) can register fresh providers — without
78
+ * the `disable()` calls, the API keeps the first (now shut-down) provider and a
79
+ * re-enable would silently no-op. Safe if never initialized; idempotent.
80
+ */
81
+ export declare function shutdownTelemetry(): Promise<void>;
82
+ /**
83
+ * @deprecated No-op compatibility shim for the pre-PR #1317 telemetry API. Node
84
+ * metrics flow through the `@origintrail-official/dkg-core` facade
85
+ * (`getMetrics()`), not this call. Kept so old callers don't break at import.
26
86
  */
27
87
  export declare function recordGauge(_name: string, _value: number): void;
28
88
  /**
29
- * Start a span for an operation (for trace correlation).
30
- * operationId should be set as span attribute so traces match the Operations panel.
31
- * No-op when telemetry is disabled.
89
+ * @deprecated No-op compatibility shim for the pre-PR #1317 telemetry API. Spans
90
+ * are created via the core facade `withSpan()`/`getTracer()`. Kept so old
91
+ * callers don't break at import.
32
92
  */
33
93
  export declare function setOperationSpan(_operationId: string, _operationName: string): void;
34
- export declare function isTelemetryConfigured(): boolean;
35
94
  //# sourceMappingURL=telemetry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAK5D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAG/D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAGnF;AAED,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C"}
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EAA+B,KAAK,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAKnG;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,sBAAsB,CAAC;AAEvD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,6FAA6F;IAC7F,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,MAAM,CAAC,EAAE,gBAAgB,GAAG;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,OAAO,CAAC,EAAE,gBAAgB,GAAG;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5D;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA+BD;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,mBAAmB,GAAG,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAwD/F;AAED,kFAAkF;AAClF,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAyBvD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAE/D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAEnF"}