@deeptracer/core 0.3.0 → 0.4.1

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/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- export { B as BeforeSendEvent, a as Breadcrumb, E as ErrorReport, I as InactiveSpan, L as LLMUsageReport, b as LogEntry, c as LogLevel, d as Logger, e as LoggerConfig, M as MiddlewareOptions, S as Span, f as SpanData, U as User, g as createLogger } from './internal-DdKQRgCs.cjs';
1
+ export { B as BeforeSendEvent, a as Breadcrumb, E as ErrorReport, I as InactiveSpan, L as LLMUsageReport, b as LogEntry, c as LogLevel, d as Logger, e as LoggerConfig, M as MiddlewareOptions, S as Span, f as SpanData, U as User, g as createLogger } from './logger-BDTEt7Gi.cjs';
2
2
 
3
3
  /** SDK version. Update on each release. */
4
- declare const SDK_VERSION = "0.3.0";
4
+ declare const SDK_VERSION = "0.4.1";
5
5
  declare const SDK_NAME = "core";
6
6
 
7
7
  export { SDK_NAME, SDK_VERSION };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { B as BeforeSendEvent, a as Breadcrumb, E as ErrorReport, I as InactiveSpan, L as LLMUsageReport, b as LogEntry, c as LogLevel, d as Logger, e as LoggerConfig, M as MiddlewareOptions, S as Span, f as SpanData, U as User, g as createLogger } from './internal-DdKQRgCs.js';
1
+ export { B as BeforeSendEvent, a as Breadcrumb, E as ErrorReport, I as InactiveSpan, L as LLMUsageReport, b as LogEntry, c as LogLevel, d as Logger, e as LoggerConfig, M as MiddlewareOptions, S as Span, f as SpanData, U as User, g as createLogger } from './logger-BDTEt7Gi.js';
2
2
 
3
3
  /** SDK version. Update on each release. */
4
- declare const SDK_VERSION = "0.3.0";
4
+ declare const SDK_VERSION = "0.4.1";
5
5
  declare const SDK_NAME = "core";
6
6
 
7
7
  export { SDK_NAME, SDK_VERSION };
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  SDK_NAME,
4
4
  SDK_VERSION,
5
5
  createLogger
6
- } from "./chunk-BRUVRV5O.js";
6
+ } from "./chunk-YBQXVNNR.js";
7
7
  export {
8
8
  Logger,
9
9
  SDK_NAME,
package/dist/internal.cjs CHANGED
@@ -21,7 +21,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var internal_exports = {};
22
22
  __export(internal_exports, {
23
23
  Logger: () => Logger,
24
- _originalConsole: () => _originalConsole
24
+ Transport: () => Transport,
25
+ _originalConsole: () => _originalConsole,
26
+ parseConsoleArgs: () => parseConsoleArgs,
27
+ parseTraceparent: () => parseTraceparent
25
28
  });
26
29
  module.exports = __toCommonJS(internal_exports);
27
30
 
@@ -60,15 +63,24 @@ var Batcher = class {
60
63
  };
61
64
 
62
65
  // src/version.ts
63
- var SDK_VERSION = "0.3.0";
66
+ var SDK_VERSION = "0.4.1";
64
67
  var SDK_NAME = "core";
65
68
 
66
69
  // src/transport.ts
67
70
  var Transport = class {
68
71
  constructor(config) {
69
72
  this.config = config;
73
+ if (config.secretKey?.startsWith("dt_secret_") && typeof globalThis.window !== "undefined") {
74
+ console.error(
75
+ "[@deeptracer/core] WARNING: `secretKey` (dt_secret_...) detected in a browser bundle. This exposes your server key to end users. Use `publicKey` (dt_public_...) for client-side code."
76
+ );
77
+ }
70
78
  }
71
79
  inFlightRequests = /* @__PURE__ */ new Set();
80
+ /** Resolve the auth key: prefer secretKey (server), fall back to publicKey (client). */
81
+ get authKey() {
82
+ return this.config.secretKey ?? this.config.publicKey ?? "";
83
+ }
72
84
  /**
73
85
  * Send a request with automatic retry and exponential backoff.
74
86
  * Retries up to `maxRetries` times on network errors and 5xx responses.
@@ -82,7 +94,7 @@ var Transport = class {
82
94
  method: "POST",
83
95
  headers: {
84
96
  "Content-Type": "application/json",
85
- Authorization: `Bearer ${this.config.apiKey}`,
97
+ Authorization: `Bearer ${this.authKey}`,
86
98
  "x-deeptracer-sdk": `${SDK_NAME}/${SDK_VERSION}`
87
99
  },
88
100
  body: JSON.stringify(body)
@@ -106,9 +118,7 @@ var Transport = class {
106
118
  await this.sleep(this.jitter(baseDelays[attempt]));
107
119
  continue;
108
120
  }
109
- console.warn(
110
- `[@deeptracer/core] Failed to send ${label} (exhausted ${maxRetries} retries)`
111
- );
121
+ console.warn(`[@deeptracer/core] Failed to send ${label} (exhausted ${maxRetries} retries)`);
112
122
  }
113
123
  }
114
124
  }
@@ -129,7 +139,6 @@ var Transport = class {
129
139
  const p = this.sendWithRetry(
130
140
  `${this.config.endpoint}/ingest/logs`,
131
141
  {
132
- product: this.config.product,
133
142
  service: this.config.service,
134
143
  environment: this.config.environment,
135
144
  logs
@@ -144,7 +153,6 @@ var Transport = class {
144
153
  `${this.config.endpoint}/ingest/errors`,
145
154
  {
146
155
  ...error,
147
- product: this.config.product,
148
156
  service: this.config.service,
149
157
  environment: this.config.environment
150
158
  },
@@ -158,7 +166,6 @@ var Transport = class {
158
166
  `${this.config.endpoint}/ingest/traces`,
159
167
  {
160
168
  ...span,
161
- product: this.config.product,
162
169
  service: this.config.service,
163
170
  environment: this.config.environment
164
171
  },
@@ -172,7 +179,6 @@ var Transport = class {
172
179
  `${this.config.endpoint}/ingest/llm`,
173
180
  {
174
181
  ...report,
175
- product: this.config.product,
176
182
  service: this.config.service,
177
183
  environment: this.config.environment
178
184
  },
@@ -206,6 +212,17 @@ function createLoggerState(maxBreadcrumbs) {
206
212
  maxBreadcrumbs
207
213
  };
208
214
  }
215
+ function cloneState(state) {
216
+ return {
217
+ user: state.user ? { ...state.user } : null,
218
+ tags: { ...state.tags },
219
+ contexts: Object.fromEntries(
220
+ Object.entries(state.contexts).map(([k, v]) => [k, { ...v }])
221
+ ),
222
+ breadcrumbs: [...state.breadcrumbs],
223
+ maxBreadcrumbs: state.maxBreadcrumbs
224
+ };
225
+ }
209
226
  function addBreadcrumb(state, breadcrumb) {
210
227
  state.breadcrumbs.push(breadcrumb);
211
228
  if (state.breadcrumbs.length > state.maxBreadcrumbs) {
@@ -214,11 +231,33 @@ function addBreadcrumb(state, breadcrumb) {
214
231
  }
215
232
 
216
233
  // src/logger.ts
234
+ var LOG_LEVEL_VALUES = {
235
+ debug: 0,
236
+ info: 1,
237
+ warn: 2,
238
+ error: 3
239
+ };
217
240
  function generateId() {
218
241
  const bytes = new Uint8Array(8);
219
242
  crypto.getRandomValues(bytes);
220
243
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
221
244
  }
245
+ function generateTraceId() {
246
+ const bytes = new Uint8Array(16);
247
+ crypto.getRandomValues(bytes);
248
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
249
+ }
250
+ function parseTraceparent(header) {
251
+ const parts = header.trim().split("-");
252
+ if (parts.length !== 4) return null;
253
+ const [version, traceId, parentId, flags] = parts;
254
+ if (version !== "00") return null;
255
+ if (traceId.length !== 32 || !/^[0-9a-f]{32}$/.test(traceId)) return null;
256
+ if (parentId.length !== 16 || !/^[0-9a-f]{16}$/.test(parentId)) return null;
257
+ if (flags.length !== 2 || !/^[0-9a-f]{2}$/.test(flags)) return null;
258
+ if (/^0+$/.test(traceId) || /^0+$/.test(parentId)) return null;
259
+ return { traceId, parentId, flags };
260
+ }
222
261
  var _originalConsole = {
223
262
  log: console.log,
224
263
  info: console.info,
@@ -229,6 +268,7 @@ var _originalConsole = {
229
268
  var Logger = class _Logger {
230
269
  batcher;
231
270
  transport;
271
+ effectiveLevel;
232
272
  contextName;
233
273
  config;
234
274
  state;
@@ -238,6 +278,17 @@ var Logger = class _Logger {
238
278
  this.contextName = contextName;
239
279
  this.requestMeta = requestMeta;
240
280
  this.state = state ?? createLoggerState(config.maxBreadcrumbs ?? 20);
281
+ if (!config.secretKey && !config.publicKey) {
282
+ _originalConsole.error(
283
+ "[@deeptracer/core] No `secretKey` or `publicKey` provided. Events will not be authenticated."
284
+ );
285
+ }
286
+ if (!config.endpoint) {
287
+ _originalConsole.error(
288
+ "[@deeptracer/core] No `endpoint` provided. Events will not be sent."
289
+ );
290
+ }
291
+ this.effectiveLevel = LOG_LEVEL_VALUES[config.level ?? (config.environment === "production" ? "info" : "debug")];
241
292
  this.transport = new Transport(config);
242
293
  this.batcher = new Batcher(
243
294
  { batchSize: config.batchSize, flushIntervalMs: config.flushIntervalMs },
@@ -251,7 +302,8 @@ var Logger = class _Logger {
251
302
  // ---------------------------------------------------------------------------
252
303
  /**
253
304
  * Set the current user context. Attached to all subsequent logs, errors, spans, and LLM reports.
254
- * Shared across all child loggers (withContext, forRequest).
305
+ * Only affects this logger instance — child loggers created via `withContext()` or `forRequest()`
306
+ * have their own independent state.
255
307
  *
256
308
  * @example
257
309
  * ```ts
@@ -373,26 +425,13 @@ var Logger = class _Logger {
373
425
  };
374
426
  }
375
427
  metadata = this.mergeStateMetadata(metadata);
376
- const entry = {
377
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
378
- level,
379
- message,
380
- metadata,
381
- context: this.contextName,
382
- trace_id: this.requestMeta?.trace_id,
383
- span_id: this.requestMeta?.span_id,
384
- request_id: this.requestMeta?.request_id,
385
- vercel_id: this.requestMeta?.vercel_id
386
- };
387
- const hookResult = this.applyBeforeSend({ type: "log", data: entry });
388
- if (hookResult === null) return;
389
- const finalEntry = hookResult.data;
428
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
390
429
  if (this.config.debug) {
391
430
  const prefix = this.contextName ? `[${this.contextName}]` : "";
392
431
  const lvl = level.toUpperCase().padEnd(5);
393
432
  const consoleFn = level === "error" ? _originalConsole.error : level === "warn" ? _originalConsole.warn : level === "debug" ? _originalConsole.debug : _originalConsole.log;
394
- if (finalEntry.metadata) {
395
- consoleFn(`${lvl} ${prefix} ${message}`, finalEntry.metadata);
433
+ if (metadata) {
434
+ consoleFn(`${lvl} ${prefix} ${message}`, metadata);
396
435
  } else {
397
436
  consoleFn(`${lvl} ${prefix} ${message}`);
398
437
  }
@@ -400,9 +439,23 @@ var Logger = class _Logger {
400
439
  addBreadcrumb(this.state, {
401
440
  type: "log",
402
441
  message: `[${level}] ${message}`,
403
- timestamp: entry.timestamp
442
+ timestamp
404
443
  });
405
- this.batcher.add(finalEntry);
444
+ if (LOG_LEVEL_VALUES[level] < this.effectiveLevel) return;
445
+ const entry = {
446
+ timestamp,
447
+ level,
448
+ message,
449
+ metadata,
450
+ context: this.contextName,
451
+ trace_id: this.requestMeta?.trace_id,
452
+ span_id: this.requestMeta?.span_id,
453
+ request_id: this.requestMeta?.request_id,
454
+ vercel_id: this.requestMeta?.vercel_id
455
+ };
456
+ const hookResult = this.applyBeforeSend({ type: "log", data: entry });
457
+ if (hookResult === null) return;
458
+ this.batcher.add(hookResult.data);
406
459
  }
407
460
  /** Log a debug message. */
408
461
  debug(message, dataOrError, error) {
@@ -423,22 +476,37 @@ var Logger = class _Logger {
423
476
  // ---------------------------------------------------------------------------
424
477
  // Child loggers
425
478
  // ---------------------------------------------------------------------------
426
- /** Create a context-scoped logger. All logs include the context name. Shares state with parent. */
479
+ /** Create a context-scoped logger. All logs include the context name. Gets an independent copy of state. */
427
480
  withContext(name) {
428
- return new _Logger(this.config, name, this.requestMeta, this.state);
481
+ return new _Logger(this.config, name, this.requestMeta, cloneState(this.state));
429
482
  }
430
- /** Create a request-scoped logger that extracts trace context from headers. Shares state with parent. */
483
+ /** Create a request-scoped logger that extracts trace context from headers. Gets an independent copy of state. */
431
484
  forRequest(request) {
432
- const vercelId = request.headers.get("x-vercel-id") || void 0;
485
+ let traceId;
486
+ let spanId;
487
+ const traceparent = request.headers.get("traceparent");
488
+ if (traceparent) {
489
+ const parsed = parseTraceparent(traceparent);
490
+ if (parsed) {
491
+ traceId = parsed.traceId;
492
+ spanId = parsed.parentId;
493
+ }
494
+ }
495
+ traceId = traceId || request.headers.get("x-trace-id") || void 0;
496
+ spanId = spanId || request.headers.get("x-span-id") || void 0;
433
497
  const requestId = request.headers.get("x-request-id") || void 0;
434
- const traceId = request.headers.get("x-trace-id") || void 0;
435
- const spanId = request.headers.get("x-span-id") || void 0;
436
- return new _Logger(this.config, this.contextName, {
437
- trace_id: traceId,
438
- span_id: spanId,
439
- request_id: requestId || (vercelId ? vercelId.split("::").pop() : void 0),
440
- vercel_id: vercelId
441
- }, this.state);
498
+ const vercelId = request.headers.get("x-vercel-id") || void 0;
499
+ return new _Logger(
500
+ this.config,
501
+ this.contextName,
502
+ {
503
+ trace_id: traceId,
504
+ span_id: spanId,
505
+ request_id: requestId || (vercelId ? vercelId.split("::").pop() : void 0),
506
+ vercel_id: vercelId
507
+ },
508
+ cloneState(this.state)
509
+ );
442
510
  }
443
511
  // ---------------------------------------------------------------------------
444
512
  // Error capture
@@ -457,7 +525,8 @@ var Logger = class _Logger {
457
525
  const enrichedContext = { ...context?.context };
458
526
  if (this.state.user) enrichedContext.user = this.state.user;
459
527
  if (Object.keys(this.state.tags).length > 0) enrichedContext._tags = { ...this.state.tags };
460
- if (Object.keys(this.state.contexts).length > 0) enrichedContext._contexts = { ...this.state.contexts };
528
+ if (Object.keys(this.state.contexts).length > 0)
529
+ enrichedContext._contexts = { ...this.state.contexts };
461
530
  const report = {
462
531
  error_message: err.message,
463
532
  stack_trace: err.stack || "",
@@ -538,7 +607,7 @@ var Logger = class _Logger {
538
607
  }
539
608
  /** Start a span with manual lifecycle. You must call span.end(). */
540
609
  startInactiveSpan(operation) {
541
- const traceId = this.requestMeta?.trace_id || generateId();
610
+ const traceId = this.requestMeta?.trace_id || generateTraceId();
542
611
  const parentSpanId = this.requestMeta?.span_id || "";
543
612
  const spanId = generateId();
544
613
  const startTime = (/* @__PURE__ */ new Date()).toISOString();
@@ -578,10 +647,16 @@ var Logger = class _Logger {
578
647
  const childLogger = new _Logger(this.config, this.contextName, childMeta, this.state);
579
648
  return childLogger.startInactiveSpan(childOp);
580
649
  },
581
- getHeaders: () => ({
582
- "x-trace-id": traceId,
583
- "x-span-id": spanId
584
- })
650
+ getHeaders: () => {
651
+ const headers = {
652
+ "x-trace-id": traceId,
653
+ "x-span-id": spanId
654
+ };
655
+ if (/^[0-9a-f]{32}$/.test(traceId)) {
656
+ headers.traceparent = `00-${traceId}-${spanId}-01`;
657
+ }
658
+ return headers;
659
+ }
585
660
  };
586
661
  return span;
587
662
  }
@@ -615,8 +690,71 @@ var Logger = class _Logger {
615
690
  await this.transport.drain(timeoutMs);
616
691
  }
617
692
  };
693
+
694
+ // src/internal.ts
695
+ function safeStringify(value) {
696
+ const seen = /* @__PURE__ */ new WeakSet();
697
+ return JSON.stringify(value, (_key, val) => {
698
+ if (val instanceof Error) {
699
+ return { name: val.name, message: val.message, stack: val.stack };
700
+ }
701
+ if (typeof val === "bigint") return val.toString();
702
+ if (typeof val === "symbol") return val.toString();
703
+ if (typeof val === "function") return `[Function: ${val.name || "anonymous"}]`;
704
+ if (val !== null && typeof val === "object") {
705
+ if (seen.has(val)) return "[Circular]";
706
+ seen.add(val);
707
+ }
708
+ return val;
709
+ });
710
+ }
711
+ function parseConsoleArgs(args) {
712
+ if (args.length === 0) return { message: "" };
713
+ const first = args[0];
714
+ if (typeof first === "string" && /%[sdifoc%]/.test(first)) {
715
+ return { message: args.map(String).join(" ") };
716
+ }
717
+ if (typeof first === "string") {
718
+ const messageParts = [first];
719
+ const metadata = {};
720
+ let metadataCount = 0;
721
+ for (let i = 1; i < args.length; i++) {
722
+ const arg = args[i];
723
+ if (arg instanceof Error) {
724
+ metadata[`error${metadataCount > 0 ? `_${metadataCount}` : ""}`] = {
725
+ name: arg.name,
726
+ message: arg.message,
727
+ stack: arg.stack
728
+ };
729
+ metadataCount++;
730
+ } else if (arg !== null && typeof arg === "object") {
731
+ Object.assign(metadata, arg);
732
+ metadataCount++;
733
+ } else if (arg !== void 0) {
734
+ messageParts.push(String(arg));
735
+ }
736
+ }
737
+ return {
738
+ message: messageParts.join(" "),
739
+ metadata: metadataCount > 0 ? metadata : void 0
740
+ };
741
+ }
742
+ if (first instanceof Error) {
743
+ return {
744
+ message: first.message,
745
+ metadata: { error: { name: first.name, message: first.message, stack: first.stack } }
746
+ };
747
+ }
748
+ if (first !== null && typeof first === "object") {
749
+ return { message: safeStringify(first) };
750
+ }
751
+ return { message: String(first) };
752
+ }
618
753
  // Annotate the CommonJS export names for ESM import in node:
619
754
  0 && (module.exports = {
620
755
  Logger,
621
- _originalConsole
756
+ Transport,
757
+ _originalConsole,
758
+ parseConsoleArgs,
759
+ parseTraceparent
622
760
  });
@@ -1 +1,66 @@
1
- export { d as Logger, e as LoggerConfig, h as LoggerState, M as MiddlewareOptions, _ as _originalConsole } from './internal-DdKQRgCs.cjs';
1
+ import { e as LoggerConfig, b as LogEntry, E as ErrorReport, f as SpanData } from './logger-BDTEt7Gi.cjs';
2
+ export { d as Logger, h as LoggerState, M as MiddlewareOptions, _ as _originalConsole, p as parseTraceparent } from './logger-BDTEt7Gi.cjs';
3
+
4
+ /**
5
+ * HTTP transport for sending data to the DeepTracer ingestion API.
6
+ *
7
+ * Features:
8
+ * - Automatic retry with exponential backoff (3 retries, 1s/2s/4s + jitter)
9
+ * - Only retries on network errors and 5xx (not 4xx client errors)
10
+ * - SDK version header on every request (`x-deeptracer-sdk: core/0.3.0`)
11
+ * - In-flight request tracking for graceful shutdown via `drain()`
12
+ */
13
+ declare class Transport {
14
+ private config;
15
+ private inFlightRequests;
16
+ constructor(config: Pick<LoggerConfig, "endpoint" | "secretKey" | "publicKey" | "service" | "environment">);
17
+ /** Resolve the auth key: prefer secretKey (server), fall back to publicKey (client). */
18
+ private get authKey();
19
+ /**
20
+ * Send a request with automatic retry and exponential backoff.
21
+ * Retries up to `maxRetries` times on network errors and 5xx responses.
22
+ * Does NOT retry on 4xx (client errors — bad payload, auth failure, etc.).
23
+ */
24
+ private sendWithRetry;
25
+ /** Add +/- 20% jitter to a delay to prevent thundering herd. */
26
+ private jitter;
27
+ private sleep;
28
+ /** Track an in-flight request and remove it when done. */
29
+ private track;
30
+ sendLogs(logs: LogEntry[]): Promise<void>;
31
+ sendError(error: ErrorReport): Promise<void>;
32
+ sendTrace(span: SpanData): Promise<void>;
33
+ sendLLMUsage(report: {
34
+ model: string;
35
+ provider: string;
36
+ operation: string;
37
+ input_tokens: number;
38
+ output_tokens: number;
39
+ cost_usd: number;
40
+ latency_ms: number;
41
+ metadata?: Record<string, unknown>;
42
+ }): Promise<void>;
43
+ /**
44
+ * Wait for all in-flight requests to complete, with a timeout.
45
+ * Used by `logger.destroy()` to ensure data is sent before process exit.
46
+ *
47
+ * @param timeoutMs - Maximum time to wait (default: 2000ms)
48
+ */
49
+ drain(timeoutMs?: number): Promise<void>;
50
+ }
51
+
52
+ /**
53
+ * Parse console.log/info/warn/error arguments into a structured `{ message, metadata }` pair.
54
+ *
55
+ * - First string arg → message; remaining objects → merged into metadata
56
+ * - If first string has printf patterns (`%s`, `%d`, `%o`, etc.) → join all as string, no metadata
57
+ * - First non-string arg → `safeStringify` it for message
58
+ * - Error objects → serialize `{ name, message, stack }` into metadata
59
+ * - Remaining primitives → append to message string
60
+ */
61
+ declare function parseConsoleArgs(args: unknown[]): {
62
+ message: string;
63
+ metadata?: Record<string, unknown>;
64
+ };
65
+
66
+ export { LoggerConfig, Transport, parseConsoleArgs };
@@ -1 +1,66 @@
1
- export { d as Logger, e as LoggerConfig, h as LoggerState, M as MiddlewareOptions, _ as _originalConsole } from './internal-DdKQRgCs.js';
1
+ import { e as LoggerConfig, b as LogEntry, E as ErrorReport, f as SpanData } from './logger-BDTEt7Gi.js';
2
+ export { d as Logger, h as LoggerState, M as MiddlewareOptions, _ as _originalConsole, p as parseTraceparent } from './logger-BDTEt7Gi.js';
3
+
4
+ /**
5
+ * HTTP transport for sending data to the DeepTracer ingestion API.
6
+ *
7
+ * Features:
8
+ * - Automatic retry with exponential backoff (3 retries, 1s/2s/4s + jitter)
9
+ * - Only retries on network errors and 5xx (not 4xx client errors)
10
+ * - SDK version header on every request (`x-deeptracer-sdk: core/0.3.0`)
11
+ * - In-flight request tracking for graceful shutdown via `drain()`
12
+ */
13
+ declare class Transport {
14
+ private config;
15
+ private inFlightRequests;
16
+ constructor(config: Pick<LoggerConfig, "endpoint" | "secretKey" | "publicKey" | "service" | "environment">);
17
+ /** Resolve the auth key: prefer secretKey (server), fall back to publicKey (client). */
18
+ private get authKey();
19
+ /**
20
+ * Send a request with automatic retry and exponential backoff.
21
+ * Retries up to `maxRetries` times on network errors and 5xx responses.
22
+ * Does NOT retry on 4xx (client errors — bad payload, auth failure, etc.).
23
+ */
24
+ private sendWithRetry;
25
+ /** Add +/- 20% jitter to a delay to prevent thundering herd. */
26
+ private jitter;
27
+ private sleep;
28
+ /** Track an in-flight request and remove it when done. */
29
+ private track;
30
+ sendLogs(logs: LogEntry[]): Promise<void>;
31
+ sendError(error: ErrorReport): Promise<void>;
32
+ sendTrace(span: SpanData): Promise<void>;
33
+ sendLLMUsage(report: {
34
+ model: string;
35
+ provider: string;
36
+ operation: string;
37
+ input_tokens: number;
38
+ output_tokens: number;
39
+ cost_usd: number;
40
+ latency_ms: number;
41
+ metadata?: Record<string, unknown>;
42
+ }): Promise<void>;
43
+ /**
44
+ * Wait for all in-flight requests to complete, with a timeout.
45
+ * Used by `logger.destroy()` to ensure data is sent before process exit.
46
+ *
47
+ * @param timeoutMs - Maximum time to wait (default: 2000ms)
48
+ */
49
+ drain(timeoutMs?: number): Promise<void>;
50
+ }
51
+
52
+ /**
53
+ * Parse console.log/info/warn/error arguments into a structured `{ message, metadata }` pair.
54
+ *
55
+ * - First string arg → message; remaining objects → merged into metadata
56
+ * - If first string has printf patterns (`%s`, `%d`, `%o`, etc.) → join all as string, no metadata
57
+ * - First non-string arg → `safeStringify` it for message
58
+ * - Error objects → serialize `{ name, message, stack }` into metadata
59
+ * - Remaining primitives → append to message string
60
+ */
61
+ declare function parseConsoleArgs(args: unknown[]): {
62
+ message: string;
63
+ metadata?: Record<string, unknown>;
64
+ };
65
+
66
+ export { LoggerConfig, Transport, parseConsoleArgs };
package/dist/internal.js CHANGED
@@ -1,8 +1,73 @@
1
1
  import {
2
2
  Logger,
3
- _originalConsole
4
- } from "./chunk-BRUVRV5O.js";
3
+ Transport,
4
+ _originalConsole,
5
+ parseTraceparent
6
+ } from "./chunk-YBQXVNNR.js";
7
+
8
+ // src/internal.ts
9
+ function safeStringify(value) {
10
+ const seen = /* @__PURE__ */ new WeakSet();
11
+ return JSON.stringify(value, (_key, val) => {
12
+ if (val instanceof Error) {
13
+ return { name: val.name, message: val.message, stack: val.stack };
14
+ }
15
+ if (typeof val === "bigint") return val.toString();
16
+ if (typeof val === "symbol") return val.toString();
17
+ if (typeof val === "function") return `[Function: ${val.name || "anonymous"}]`;
18
+ if (val !== null && typeof val === "object") {
19
+ if (seen.has(val)) return "[Circular]";
20
+ seen.add(val);
21
+ }
22
+ return val;
23
+ });
24
+ }
25
+ function parseConsoleArgs(args) {
26
+ if (args.length === 0) return { message: "" };
27
+ const first = args[0];
28
+ if (typeof first === "string" && /%[sdifoc%]/.test(first)) {
29
+ return { message: args.map(String).join(" ") };
30
+ }
31
+ if (typeof first === "string") {
32
+ const messageParts = [first];
33
+ const metadata = {};
34
+ let metadataCount = 0;
35
+ for (let i = 1; i < args.length; i++) {
36
+ const arg = args[i];
37
+ if (arg instanceof Error) {
38
+ metadata[`error${metadataCount > 0 ? `_${metadataCount}` : ""}`] = {
39
+ name: arg.name,
40
+ message: arg.message,
41
+ stack: arg.stack
42
+ };
43
+ metadataCount++;
44
+ } else if (arg !== null && typeof arg === "object") {
45
+ Object.assign(metadata, arg);
46
+ metadataCount++;
47
+ } else if (arg !== void 0) {
48
+ messageParts.push(String(arg));
49
+ }
50
+ }
51
+ return {
52
+ message: messageParts.join(" "),
53
+ metadata: metadataCount > 0 ? metadata : void 0
54
+ };
55
+ }
56
+ if (first instanceof Error) {
57
+ return {
58
+ message: first.message,
59
+ metadata: { error: { name: first.name, message: first.message, stack: first.stack } }
60
+ };
61
+ }
62
+ if (first !== null && typeof first === "object") {
63
+ return { message: safeStringify(first) };
64
+ }
65
+ return { message: String(first) };
66
+ }
5
67
  export {
6
68
  Logger,
7
- _originalConsole
69
+ Transport,
70
+ _originalConsole,
71
+ parseConsoleArgs,
72
+ parseTraceparent
8
73
  };