@logbrew/sdk 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -3
- package/core.cjs +200 -18
- package/index.d.cts +120 -0
- package/index.d.ts +120 -0
- package/index.js +2 -0
- package/issue-diagnostics.cjs +267 -0
- package/issue-stack.cjs +70 -4
- package/package.json +3 -1
- package/react-native.d.ts +3 -0
- package/react-native.js +2 -0
- package/telemetry-context.cjs +298 -0
package/index.d.cts
CHANGED
|
@@ -2,6 +2,48 @@
|
|
|
2
2
|
export type MetadataValue = string | number | boolean | null;
|
|
3
3
|
/** Structured metadata map shared by public LogBrew event attribute types. */
|
|
4
4
|
export type Metadata = Record<string, MetadataValue>;
|
|
5
|
+
/** Bounded service, runtime, or framework identity shared by telemetry signals. */
|
|
6
|
+
export type TelemetryNamedVersion = {
|
|
7
|
+
name: string;
|
|
8
|
+
version?: string;
|
|
9
|
+
};
|
|
10
|
+
/** Privacy-bounded resource identity shared by telemetry signals. */
|
|
11
|
+
export type TelemetryResource = {
|
|
12
|
+
service?: TelemetryNamedVersion;
|
|
13
|
+
deployment?: { environment?: string; release?: string };
|
|
14
|
+
runtime?: TelemetryNamedVersion;
|
|
15
|
+
framework?: TelemetryNamedVersion;
|
|
16
|
+
operatingSystem?: TelemetryNamedVersion & { build?: string };
|
|
17
|
+
device?: { family?: string; model?: string; architecture?: string };
|
|
18
|
+
application?: { name?: string; version?: string; build?: string };
|
|
19
|
+
};
|
|
20
|
+
/** W3C-compatible correlation identity shared by non-span telemetry. */
|
|
21
|
+
export type TelemetryTraceContext = {
|
|
22
|
+
traceId: string;
|
|
23
|
+
spanId?: string;
|
|
24
|
+
parentSpanId?: string;
|
|
25
|
+
sampled?: boolean;
|
|
26
|
+
};
|
|
27
|
+
/** Opaque application session identity. */
|
|
28
|
+
export type TelemetrySessionContext = {
|
|
29
|
+
id: string;
|
|
30
|
+
previousId?: string;
|
|
31
|
+
};
|
|
32
|
+
/** Explicit app-owned subject identity; do not send names, email addresses, or IP addresses. */
|
|
33
|
+
export type TelemetrySubjectContext = {
|
|
34
|
+
id: string;
|
|
35
|
+
kind: "anonymous" | "user";
|
|
36
|
+
};
|
|
37
|
+
/** Versioned shared context available on every LogBrew event type. */
|
|
38
|
+
export type TelemetryContext = {
|
|
39
|
+
schemaVersion: 1;
|
|
40
|
+
resource?: TelemetryResource;
|
|
41
|
+
trace?: TelemetryTraceContext;
|
|
42
|
+
session?: TelemetrySessionContext;
|
|
43
|
+
subject?: TelemetrySubjectContext;
|
|
44
|
+
/** Up to 32 low-cardinality string dimensions with safe machine keys. */
|
|
45
|
+
tags?: Record<string, string>;
|
|
46
|
+
};
|
|
5
47
|
/** Canonical user-facing severity categories accepted by LogBrew. */
|
|
6
48
|
export type Severity = "info" | "warning" | "error" | "critical";
|
|
7
49
|
/** Runtime-level aliases accepted for compatibility and normalized before send. */
|
|
@@ -211,6 +253,7 @@ export type ReleaseAttributes = {
|
|
|
211
253
|
commit?: string;
|
|
212
254
|
notes?: string;
|
|
213
255
|
metadata?: Metadata;
|
|
256
|
+
context?: TelemetryContext;
|
|
214
257
|
};
|
|
215
258
|
|
|
216
259
|
/** Public environment event attributes. */
|
|
@@ -218,6 +261,7 @@ export type EnvironmentAttributes = {
|
|
|
218
261
|
name: string;
|
|
219
262
|
region?: string;
|
|
220
263
|
metadata?: Metadata;
|
|
264
|
+
context?: TelemetryContext;
|
|
221
265
|
};
|
|
222
266
|
|
|
223
267
|
/** Privacy-bounded generated JavaScript frame attached to an issue. */
|
|
@@ -228,18 +272,71 @@ export type IssueStackFrame = {
|
|
|
228
272
|
line: number;
|
|
229
273
|
/** One-based generated source column. */
|
|
230
274
|
column: number;
|
|
275
|
+
/** Optional bounded function or method identity. */
|
|
276
|
+
function?: string;
|
|
277
|
+
/** Optional bounded module, package, or namespace identity. */
|
|
278
|
+
module?: string;
|
|
279
|
+
/** Whether application code classified this frame as app-owned. */
|
|
280
|
+
inApp?: boolean;
|
|
231
281
|
/** Optional release-artifact Debug ID matched to this generated file. */
|
|
232
282
|
debugId?: string;
|
|
233
283
|
};
|
|
234
284
|
|
|
285
|
+
/** Runtime path that captured an exception and whether it escaped that path. */
|
|
286
|
+
export type IssueExceptionMechanism = {
|
|
287
|
+
/** Stable low-cardinality capture mechanism, such as `react.error_boundary`. */
|
|
288
|
+
type: string;
|
|
289
|
+
/** False when the exception escaped the capture boundary. */
|
|
290
|
+
handled: boolean;
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
/** Structured exception identity attached to an issue. */
|
|
294
|
+
export type IssueException = {
|
|
295
|
+
/** Bounded runtime exception class or error type. */
|
|
296
|
+
type: string;
|
|
297
|
+
/** Capture mechanism when the SDK can determine it. */
|
|
298
|
+
mechanism?: IssueExceptionMechanism;
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
export type IssueBreadcrumbLevel = "debug" | "info" | "warning" | "error" | "critical";
|
|
302
|
+
export type IssueBreadcrumbLevelInput = IssueBreadcrumbLevel | "trace" | "log" | "warn" | "fatal";
|
|
303
|
+
export type IssueBreadcrumbDataValue = string | number | boolean | null;
|
|
304
|
+
|
|
305
|
+
/** One privacy-bounded step that happened before an issue. */
|
|
306
|
+
export type IssueBreadcrumb = {
|
|
307
|
+
/** RFC 3339 timestamp with an explicit timezone. */
|
|
308
|
+
timestamp: string;
|
|
309
|
+
/** Optional stable breadcrumb kind, such as `navigation` or `http`. */
|
|
310
|
+
type?: string;
|
|
311
|
+
/** Required low-cardinality source category. */
|
|
312
|
+
category: string;
|
|
313
|
+
level?: IssueBreadcrumbLevel;
|
|
314
|
+
/** Optional bounded display-safe description. */
|
|
315
|
+
message?: string;
|
|
316
|
+
/** At most eight flat primitive fields. Never include authentication material or raw request data. */
|
|
317
|
+
data?: Record<string, IssueBreadcrumbDataValue>;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
/** Input accepted by `addBreadcrumb`; the client supplies the current timestamp when omitted. */
|
|
321
|
+
export type IssueBreadcrumbInput = Omit<IssueBreadcrumb, "timestamp" | "level"> & {
|
|
322
|
+
timestamp?: string;
|
|
323
|
+
level?: IssueBreadcrumbLevelInput;
|
|
324
|
+
};
|
|
325
|
+
|
|
235
326
|
/** Public issue event attributes. */
|
|
236
327
|
export type IssueAttributes = {
|
|
237
328
|
title: string;
|
|
238
329
|
level: SeverityInput;
|
|
239
330
|
message?: string;
|
|
331
|
+
exception?: IssueException;
|
|
240
332
|
/** Ordered privacy-bounded generated frames, capped at 32. */
|
|
241
333
|
stackFrames?: IssueStackFrame[];
|
|
334
|
+
/** Oldest-to-newest issue history, capped at the most recent 64 entries. */
|
|
335
|
+
breadcrumbs?: IssueBreadcrumb[];
|
|
336
|
+
/** True when older or invalid history was omitted before capture. */
|
|
337
|
+
breadcrumbsTruncated?: boolean;
|
|
242
338
|
metadata?: Metadata;
|
|
339
|
+
context?: TelemetryContext;
|
|
243
340
|
};
|
|
244
341
|
|
|
245
342
|
/** Options for creating privacy-bounded issue attributes from a JavaScript error. */
|
|
@@ -248,6 +345,10 @@ export type JavaScriptErrorIssueOptions = {
|
|
|
248
345
|
level?: SeverityInput;
|
|
249
346
|
message?: string;
|
|
250
347
|
metadata?: Metadata;
|
|
348
|
+
/** Stable low-cardinality capture mechanism. Defaults to `javascript.error`. */
|
|
349
|
+
mechanism?: string;
|
|
350
|
+
/** Whether the error was handled by the capture boundary. Defaults to true. */
|
|
351
|
+
handled?: boolean;
|
|
251
352
|
/** Metadata source label. Defaults to `javascript.error`. */
|
|
252
353
|
source?: string;
|
|
253
354
|
/** Active trace copied into primitive correlation metadata. */
|
|
@@ -276,6 +377,7 @@ export type LogAttributes = {
|
|
|
276
377
|
level: SeverityInput;
|
|
277
378
|
logger?: string;
|
|
278
379
|
metadata?: Metadata;
|
|
380
|
+
context?: TelemetryContext;
|
|
279
381
|
};
|
|
280
382
|
|
|
281
383
|
/** Console method names supported by the opt-in console capture helper. */
|
|
@@ -406,6 +508,7 @@ export type SpanAttributes = {
|
|
|
406
508
|
events?: SpanEventSummary[];
|
|
407
509
|
links?: SpanLinkSummary[];
|
|
408
510
|
metadata?: Metadata;
|
|
511
|
+
context?: TelemetryContext;
|
|
409
512
|
};
|
|
410
513
|
|
|
411
514
|
/** Public action event attributes. */
|
|
@@ -413,8 +516,18 @@ export type ActionAttributes = {
|
|
|
413
516
|
name: string;
|
|
414
517
|
status: "queued" | "running" | "success" | "failure";
|
|
415
518
|
metadata?: Metadata;
|
|
519
|
+
context?: TelemetryContext;
|
|
416
520
|
};
|
|
417
521
|
|
|
522
|
+
/** Stable product-analytics event categories carried in reserved action metadata. */
|
|
523
|
+
export type ProductAnalyticsKind = "page_view" | "screen_view" | "interaction";
|
|
524
|
+
|
|
525
|
+
/** Current version of the reserved product-analytics metadata vocabulary. */
|
|
526
|
+
export declare const PRODUCT_ANALYTICS_SCHEMA_VERSION: 1;
|
|
527
|
+
|
|
528
|
+
/** Product-analytics categories understood by this SDK version. */
|
|
529
|
+
export declare const PRODUCT_ANALYTICS_KINDS: readonly ProductAnalyticsKind[];
|
|
530
|
+
|
|
418
531
|
/** App-owned product step input for agent-readable action timelines. */
|
|
419
532
|
export type ProductActionInput = string | {
|
|
420
533
|
name: string;
|
|
@@ -515,6 +628,7 @@ export type MetricAttributes = {
|
|
|
515
628
|
unit: string;
|
|
516
629
|
temporality: "delta" | "cumulative";
|
|
517
630
|
metadata?: Metadata;
|
|
631
|
+
context?: TelemetryContext;
|
|
518
632
|
} | {
|
|
519
633
|
name: string;
|
|
520
634
|
kind: "gauge";
|
|
@@ -656,6 +770,8 @@ export declare class LogBrewClient {
|
|
|
656
770
|
apiKey: string;
|
|
657
771
|
sdkName: string;
|
|
658
772
|
sdkVersion: string;
|
|
773
|
+
/** Versioned context merged into every captured event; event context can override dynamic fields. */
|
|
774
|
+
context?: TelemetryContext;
|
|
659
775
|
/** Retry attempts after the first send. Must be a non-negative integer; defaults to 2. */
|
|
660
776
|
maxRetries?: number;
|
|
661
777
|
eventFilter?: EventFilter;
|
|
@@ -690,6 +806,10 @@ export declare class LogBrewClient {
|
|
|
690
806
|
previewJson(): string;
|
|
691
807
|
/** Purge queued events from memory and persistence while no delivery operation is active. */
|
|
692
808
|
purgePendingEvents(): number;
|
|
809
|
+
/** Add one explicit privacy-bounded breadcrumb to the client's 64-entry issue history. */
|
|
810
|
+
addBreadcrumb(breadcrumb: IssueBreadcrumbInput, timestamp?: string): void;
|
|
811
|
+
/** Clear the current issue breadcrumb history and return the number removed. */
|
|
812
|
+
clearBreadcrumbs(): number;
|
|
693
813
|
release(id: string, timestamp: string, attributes: ReleaseAttributes): void;
|
|
694
814
|
environment(id: string, timestamp: string, attributes: EnvironmentAttributes): void;
|
|
695
815
|
issue(id: string, timestamp: string, attributes: IssueAttributes): void;
|
package/index.d.ts
CHANGED
|
@@ -2,6 +2,48 @@
|
|
|
2
2
|
export type MetadataValue = string | number | boolean | null;
|
|
3
3
|
/** Structured metadata map shared by public LogBrew event attribute types. */
|
|
4
4
|
export type Metadata = Record<string, MetadataValue>;
|
|
5
|
+
/** Bounded service, runtime, or framework identity shared by telemetry signals. */
|
|
6
|
+
export type TelemetryNamedVersion = {
|
|
7
|
+
name: string;
|
|
8
|
+
version?: string;
|
|
9
|
+
};
|
|
10
|
+
/** Privacy-bounded resource identity shared by telemetry signals. */
|
|
11
|
+
export type TelemetryResource = {
|
|
12
|
+
service?: TelemetryNamedVersion;
|
|
13
|
+
deployment?: { environment?: string; release?: string };
|
|
14
|
+
runtime?: TelemetryNamedVersion;
|
|
15
|
+
framework?: TelemetryNamedVersion;
|
|
16
|
+
operatingSystem?: TelemetryNamedVersion & { build?: string };
|
|
17
|
+
device?: { family?: string; model?: string; architecture?: string };
|
|
18
|
+
application?: { name?: string; version?: string; build?: string };
|
|
19
|
+
};
|
|
20
|
+
/** W3C-compatible correlation identity shared by non-span telemetry. */
|
|
21
|
+
export type TelemetryTraceContext = {
|
|
22
|
+
traceId: string;
|
|
23
|
+
spanId?: string;
|
|
24
|
+
parentSpanId?: string;
|
|
25
|
+
sampled?: boolean;
|
|
26
|
+
};
|
|
27
|
+
/** Opaque application session identity. */
|
|
28
|
+
export type TelemetrySessionContext = {
|
|
29
|
+
id: string;
|
|
30
|
+
previousId?: string;
|
|
31
|
+
};
|
|
32
|
+
/** Explicit app-owned subject identity; do not send names, email addresses, or IP addresses. */
|
|
33
|
+
export type TelemetrySubjectContext = {
|
|
34
|
+
id: string;
|
|
35
|
+
kind: "anonymous" | "user";
|
|
36
|
+
};
|
|
37
|
+
/** Versioned shared context available on every LogBrew event type. */
|
|
38
|
+
export type TelemetryContext = {
|
|
39
|
+
schemaVersion: 1;
|
|
40
|
+
resource?: TelemetryResource;
|
|
41
|
+
trace?: TelemetryTraceContext;
|
|
42
|
+
session?: TelemetrySessionContext;
|
|
43
|
+
subject?: TelemetrySubjectContext;
|
|
44
|
+
/** Up to 32 low-cardinality string dimensions with safe machine keys. */
|
|
45
|
+
tags?: Record<string, string>;
|
|
46
|
+
};
|
|
5
47
|
/** Canonical user-facing severity categories accepted by LogBrew. */
|
|
6
48
|
export type Severity = "info" | "warning" | "error" | "critical";
|
|
7
49
|
/** Runtime-level aliases accepted for compatibility and normalized before send. */
|
|
@@ -211,6 +253,7 @@ export type ReleaseAttributes = {
|
|
|
211
253
|
commit?: string;
|
|
212
254
|
notes?: string;
|
|
213
255
|
metadata?: Metadata;
|
|
256
|
+
context?: TelemetryContext;
|
|
214
257
|
};
|
|
215
258
|
|
|
216
259
|
/** Public environment event attributes. */
|
|
@@ -218,6 +261,7 @@ export type EnvironmentAttributes = {
|
|
|
218
261
|
name: string;
|
|
219
262
|
region?: string;
|
|
220
263
|
metadata?: Metadata;
|
|
264
|
+
context?: TelemetryContext;
|
|
221
265
|
};
|
|
222
266
|
|
|
223
267
|
/** Privacy-bounded generated JavaScript frame attached to an issue. */
|
|
@@ -228,18 +272,71 @@ export type IssueStackFrame = {
|
|
|
228
272
|
line: number;
|
|
229
273
|
/** One-based generated source column. */
|
|
230
274
|
column: number;
|
|
275
|
+
/** Optional bounded function or method identity. */
|
|
276
|
+
function?: string;
|
|
277
|
+
/** Optional bounded module, package, or namespace identity. */
|
|
278
|
+
module?: string;
|
|
279
|
+
/** Whether application code classified this frame as app-owned. */
|
|
280
|
+
inApp?: boolean;
|
|
231
281
|
/** Optional release-artifact Debug ID matched to this generated file. */
|
|
232
282
|
debugId?: string;
|
|
233
283
|
};
|
|
234
284
|
|
|
285
|
+
/** Runtime path that captured an exception and whether it escaped that path. */
|
|
286
|
+
export type IssueExceptionMechanism = {
|
|
287
|
+
/** Stable low-cardinality capture mechanism, such as `react.error_boundary`. */
|
|
288
|
+
type: string;
|
|
289
|
+
/** False when the exception escaped the capture boundary. */
|
|
290
|
+
handled: boolean;
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
/** Structured exception identity attached to an issue. */
|
|
294
|
+
export type IssueException = {
|
|
295
|
+
/** Bounded runtime exception class or error type. */
|
|
296
|
+
type: string;
|
|
297
|
+
/** Capture mechanism when the SDK can determine it. */
|
|
298
|
+
mechanism?: IssueExceptionMechanism;
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
export type IssueBreadcrumbLevel = "debug" | "info" | "warning" | "error" | "critical";
|
|
302
|
+
export type IssueBreadcrumbLevelInput = IssueBreadcrumbLevel | "trace" | "log" | "warn" | "fatal";
|
|
303
|
+
export type IssueBreadcrumbDataValue = string | number | boolean | null;
|
|
304
|
+
|
|
305
|
+
/** One privacy-bounded step that happened before an issue. */
|
|
306
|
+
export type IssueBreadcrumb = {
|
|
307
|
+
/** RFC 3339 timestamp with an explicit timezone. */
|
|
308
|
+
timestamp: string;
|
|
309
|
+
/** Optional stable breadcrumb kind, such as `navigation` or `http`. */
|
|
310
|
+
type?: string;
|
|
311
|
+
/** Required low-cardinality source category. */
|
|
312
|
+
category: string;
|
|
313
|
+
level?: IssueBreadcrumbLevel;
|
|
314
|
+
/** Optional bounded display-safe description. */
|
|
315
|
+
message?: string;
|
|
316
|
+
/** At most eight flat primitive fields. Never include authentication material or raw request data. */
|
|
317
|
+
data?: Record<string, IssueBreadcrumbDataValue>;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
/** Input accepted by `addBreadcrumb`; the client supplies the current timestamp when omitted. */
|
|
321
|
+
export type IssueBreadcrumbInput = Omit<IssueBreadcrumb, "timestamp" | "level"> & {
|
|
322
|
+
timestamp?: string;
|
|
323
|
+
level?: IssueBreadcrumbLevelInput;
|
|
324
|
+
};
|
|
325
|
+
|
|
235
326
|
/** Public issue event attributes. */
|
|
236
327
|
export type IssueAttributes = {
|
|
237
328
|
title: string;
|
|
238
329
|
level: SeverityInput;
|
|
239
330
|
message?: string;
|
|
331
|
+
exception?: IssueException;
|
|
240
332
|
/** Ordered privacy-bounded generated frames, capped at 32. */
|
|
241
333
|
stackFrames?: IssueStackFrame[];
|
|
334
|
+
/** Oldest-to-newest issue history, capped at the most recent 64 entries. */
|
|
335
|
+
breadcrumbs?: IssueBreadcrumb[];
|
|
336
|
+
/** True when older or invalid history was omitted before capture. */
|
|
337
|
+
breadcrumbsTruncated?: boolean;
|
|
242
338
|
metadata?: Metadata;
|
|
339
|
+
context?: TelemetryContext;
|
|
243
340
|
};
|
|
244
341
|
|
|
245
342
|
/** Options for creating privacy-bounded issue attributes from a JavaScript error. */
|
|
@@ -248,6 +345,10 @@ export type JavaScriptErrorIssueOptions = {
|
|
|
248
345
|
level?: SeverityInput;
|
|
249
346
|
message?: string;
|
|
250
347
|
metadata?: Metadata;
|
|
348
|
+
/** Stable low-cardinality capture mechanism. Defaults to `javascript.error`. */
|
|
349
|
+
mechanism?: string;
|
|
350
|
+
/** Whether the error was handled by the capture boundary. Defaults to true. */
|
|
351
|
+
handled?: boolean;
|
|
251
352
|
/** Metadata source label. Defaults to `javascript.error`. */
|
|
252
353
|
source?: string;
|
|
253
354
|
/** Active trace copied into primitive correlation metadata. */
|
|
@@ -276,6 +377,7 @@ export type LogAttributes = {
|
|
|
276
377
|
level: SeverityInput;
|
|
277
378
|
logger?: string;
|
|
278
379
|
metadata?: Metadata;
|
|
380
|
+
context?: TelemetryContext;
|
|
279
381
|
};
|
|
280
382
|
|
|
281
383
|
/** Console method names supported by the opt-in console capture helper. */
|
|
@@ -406,6 +508,7 @@ export type SpanAttributes = {
|
|
|
406
508
|
events?: SpanEventSummary[];
|
|
407
509
|
links?: SpanLinkSummary[];
|
|
408
510
|
metadata?: Metadata;
|
|
511
|
+
context?: TelemetryContext;
|
|
409
512
|
};
|
|
410
513
|
|
|
411
514
|
/** Public action event attributes. */
|
|
@@ -413,8 +516,18 @@ export type ActionAttributes = {
|
|
|
413
516
|
name: string;
|
|
414
517
|
status: "queued" | "running" | "success" | "failure";
|
|
415
518
|
metadata?: Metadata;
|
|
519
|
+
context?: TelemetryContext;
|
|
416
520
|
};
|
|
417
521
|
|
|
522
|
+
/** Stable product-analytics event categories carried in reserved action metadata. */
|
|
523
|
+
export type ProductAnalyticsKind = "page_view" | "screen_view" | "interaction";
|
|
524
|
+
|
|
525
|
+
/** Current version of the reserved product-analytics metadata vocabulary. */
|
|
526
|
+
export declare const PRODUCT_ANALYTICS_SCHEMA_VERSION: 1;
|
|
527
|
+
|
|
528
|
+
/** Product-analytics categories understood by this SDK version. */
|
|
529
|
+
export declare const PRODUCT_ANALYTICS_KINDS: readonly ProductAnalyticsKind[];
|
|
530
|
+
|
|
418
531
|
/** App-owned product step input for agent-readable action timelines. */
|
|
419
532
|
export type ProductActionInput = string | {
|
|
420
533
|
name: string;
|
|
@@ -515,6 +628,7 @@ export type MetricAttributes = {
|
|
|
515
628
|
unit: string;
|
|
516
629
|
temporality: "delta" | "cumulative";
|
|
517
630
|
metadata?: Metadata;
|
|
631
|
+
context?: TelemetryContext;
|
|
518
632
|
} | {
|
|
519
633
|
name: string;
|
|
520
634
|
kind: "gauge";
|
|
@@ -656,6 +770,8 @@ export declare class LogBrewClient {
|
|
|
656
770
|
apiKey: string;
|
|
657
771
|
sdkName: string;
|
|
658
772
|
sdkVersion: string;
|
|
773
|
+
/** Versioned context merged into every captured event; event context can override dynamic fields. */
|
|
774
|
+
context?: TelemetryContext;
|
|
659
775
|
/** Retry attempts after the first send. Must be a non-negative integer; defaults to 2. */
|
|
660
776
|
maxRetries?: number;
|
|
661
777
|
eventFilter?: EventFilter;
|
|
@@ -690,6 +806,10 @@ export declare class LogBrewClient {
|
|
|
690
806
|
previewJson(): string;
|
|
691
807
|
/** Purge queued events from memory and persistence while no delivery operation is active. */
|
|
692
808
|
purgePendingEvents(): number;
|
|
809
|
+
/** Add one explicit privacy-bounded breadcrumb to the client's 64-entry issue history. */
|
|
810
|
+
addBreadcrumb(breadcrumb: IssueBreadcrumbInput, timestamp?: string): void;
|
|
811
|
+
/** Clear the current issue breadcrumb history and return the number removed. */
|
|
812
|
+
clearBreadcrumbs(): number;
|
|
693
813
|
release(id: string, timestamp: string, attributes: ReleaseAttributes): void;
|
|
694
814
|
environment(id: string, timestamp: string, attributes: EnvironmentAttributes): void;
|
|
695
815
|
issue(id: string, timestamp: string, attributes: IssueAttributes): void;
|
package/index.js
CHANGED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const MAX_ISSUE_BREADCRUMBS = 64;
|
|
4
|
+
const MAX_EXCEPTION_TYPE_LENGTH = 256;
|
|
5
|
+
const MAX_MECHANISM_TYPE_LENGTH = 64;
|
|
6
|
+
const MAX_BREADCRUMB_NAME_LENGTH = 64;
|
|
7
|
+
const MAX_BREADCRUMB_MESSAGE_LENGTH = 512;
|
|
8
|
+
const MAX_BREADCRUMB_DATA_FIELDS = 8;
|
|
9
|
+
const MAX_BREADCRUMB_DATA_STRING_LENGTH = 256;
|
|
10
|
+
const MACHINE_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/u;
|
|
11
|
+
const DATA_KEY_PATTERN = /^[A-Za-z][A-Za-z0-9_.-]{0,63}$/u;
|
|
12
|
+
const BREADCRUMB_LEVEL_ALIASES = new Map([
|
|
13
|
+
["trace", "debug"],
|
|
14
|
+
["debug", "debug"],
|
|
15
|
+
["info", "info"],
|
|
16
|
+
["log", "info"],
|
|
17
|
+
["warn", "warning"],
|
|
18
|
+
["warning", "warning"],
|
|
19
|
+
["error", "error"],
|
|
20
|
+
["fatal", "critical"],
|
|
21
|
+
["critical", "critical"]
|
|
22
|
+
]);
|
|
23
|
+
|
|
24
|
+
function buildIssueDiagnosticsHelpers({ SdkError, requireTimestamp }) {
|
|
25
|
+
function validationError(message) {
|
|
26
|
+
return new SdkError("validation_error", message);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function validateIssueException(exception) {
|
|
30
|
+
if (exception === undefined) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
requireObject("issue exception", exception);
|
|
34
|
+
rejectUnknownKeys("issue exception", exception, new Set(["type", "mechanism"]));
|
|
35
|
+
const type = boundedText("issue exception type", exception.type, MAX_EXCEPTION_TYPE_LENGTH, {
|
|
36
|
+
rejectLocationText: true
|
|
37
|
+
});
|
|
38
|
+
const mechanism = validateIssueExceptionMechanism(exception.mechanism);
|
|
39
|
+
return {
|
|
40
|
+
type,
|
|
41
|
+
...(mechanism === undefined ? {} : { mechanism })
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function validateIssueExceptionMechanism(mechanism) {
|
|
46
|
+
if (mechanism === undefined) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
requireObject("issue exception mechanism", mechanism);
|
|
50
|
+
rejectUnknownKeys(
|
|
51
|
+
"issue exception mechanism",
|
|
52
|
+
mechanism,
|
|
53
|
+
new Set(["type", "handled"])
|
|
54
|
+
);
|
|
55
|
+
if (typeof mechanism.type !== "string" || !MACHINE_NAME_PATTERN.test(mechanism.type)) {
|
|
56
|
+
throw validationError(
|
|
57
|
+
`issue exception mechanism type must match ${MACHINE_NAME_PATTERN}`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
if (Array.from(mechanism.type).length > MAX_MECHANISM_TYPE_LENGTH) {
|
|
61
|
+
throw validationError(
|
|
62
|
+
`issue exception mechanism type must be at most ${MAX_MECHANISM_TYPE_LENGTH} characters`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if (typeof mechanism.handled !== "boolean") {
|
|
66
|
+
throw validationError("issue exception mechanism handled must be a boolean");
|
|
67
|
+
}
|
|
68
|
+
return { type: mechanism.type, handled: mechanism.handled };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function createIssueException(type, mechanism, handled) {
|
|
72
|
+
return validateIssueException({
|
|
73
|
+
type,
|
|
74
|
+
mechanism: { type: mechanism, handled }
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function validateIssueBreadcrumb(breadcrumb, defaultTimestamp) {
|
|
79
|
+
requireObject("issue breadcrumb", breadcrumb);
|
|
80
|
+
rejectUnknownKeys(
|
|
81
|
+
"issue breadcrumb",
|
|
82
|
+
breadcrumb,
|
|
83
|
+
new Set(["timestamp", "type", "category", "level", "message", "data"])
|
|
84
|
+
);
|
|
85
|
+
const timestamp = breadcrumb.timestamp ?? defaultTimestamp;
|
|
86
|
+
requireTimestamp(timestamp);
|
|
87
|
+
if (typeof breadcrumb.category !== "string" || !MACHINE_NAME_PATTERN.test(breadcrumb.category)) {
|
|
88
|
+
throw validationError(`issue breadcrumb category must match ${MACHINE_NAME_PATTERN}`);
|
|
89
|
+
}
|
|
90
|
+
const type = optionalMachineName("issue breadcrumb type", breadcrumb.type);
|
|
91
|
+
const level = optionalBreadcrumbLevel(breadcrumb.level);
|
|
92
|
+
const message = breadcrumb.message === undefined
|
|
93
|
+
? undefined
|
|
94
|
+
: boundedText(
|
|
95
|
+
"issue breadcrumb message",
|
|
96
|
+
breadcrumb.message,
|
|
97
|
+
MAX_BREADCRUMB_MESSAGE_LENGTH
|
|
98
|
+
);
|
|
99
|
+
const data = validateBreadcrumbData(breadcrumb.data);
|
|
100
|
+
return {
|
|
101
|
+
timestamp,
|
|
102
|
+
...(type === undefined ? {} : { type }),
|
|
103
|
+
category: breadcrumb.category,
|
|
104
|
+
...(level === undefined ? {} : { level }),
|
|
105
|
+
...(message === undefined ? {} : { message }),
|
|
106
|
+
...(data === undefined ? {} : { data })
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function validateIssueBreadcrumbs(breadcrumbs) {
|
|
111
|
+
if (breadcrumbs === undefined) {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
if (!Array.isArray(breadcrumbs) || breadcrumbs.length < 1 || breadcrumbs.length > MAX_ISSUE_BREADCRUMBS) {
|
|
115
|
+
throw validationError(
|
|
116
|
+
`issue breadcrumbs must contain 1-${MAX_ISSUE_BREADCRUMBS} entries`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
return breadcrumbs.map((breadcrumb) => validateIssueBreadcrumb(breadcrumb));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function validateIssueDiagnostics(attributes) {
|
|
123
|
+
const exception = validateIssueException(attributes.exception);
|
|
124
|
+
const breadcrumbs = validateIssueBreadcrumbs(attributes.breadcrumbs);
|
|
125
|
+
if (
|
|
126
|
+
attributes.breadcrumbsTruncated !== undefined
|
|
127
|
+
&& typeof attributes.breadcrumbsTruncated !== "boolean"
|
|
128
|
+
) {
|
|
129
|
+
throw validationError("issue breadcrumbsTruncated must be a boolean");
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
...(exception === undefined ? {} : { exception }),
|
|
133
|
+
...(breadcrumbs === undefined ? {} : { breadcrumbs }),
|
|
134
|
+
...(attributes.breadcrumbsTruncated === true ? { breadcrumbsTruncated: true } : {})
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function cloneIssueDiagnostics(attributes) {
|
|
139
|
+
const diagnostics = {};
|
|
140
|
+
if (attributes.exception !== undefined) {
|
|
141
|
+
diagnostics.exception = {
|
|
142
|
+
...attributes.exception,
|
|
143
|
+
...(attributes.exception.mechanism === undefined
|
|
144
|
+
? {}
|
|
145
|
+
: { mechanism: { ...attributes.exception.mechanism } })
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
if (Array.isArray(attributes.breadcrumbs)) {
|
|
149
|
+
diagnostics.breadcrumbs = attributes.breadcrumbs.map((breadcrumb) => ({
|
|
150
|
+
...breadcrumb,
|
|
151
|
+
...(breadcrumb.data === undefined ? {} : { data: { ...breadcrumb.data } })
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
if (attributes.breadcrumbsTruncated === true) {
|
|
155
|
+
diagnostics.breadcrumbsTruncated = true;
|
|
156
|
+
}
|
|
157
|
+
return diagnostics;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function validateBreadcrumbData(data) {
|
|
161
|
+
if (data === undefined) {
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
requireObject("issue breadcrumb data", data);
|
|
165
|
+
const entries = Object.entries(data);
|
|
166
|
+
if (entries.length > MAX_BREADCRUMB_DATA_FIELDS) {
|
|
167
|
+
throw validationError(
|
|
168
|
+
`issue breadcrumb data must contain at most ${MAX_BREADCRUMB_DATA_FIELDS} fields`
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
const validated = {};
|
|
172
|
+
for (const [key, value] of entries) {
|
|
173
|
+
if (!DATA_KEY_PATTERN.test(key)) {
|
|
174
|
+
throw validationError(`issue breadcrumb data key must match ${DATA_KEY_PATTERN}`);
|
|
175
|
+
}
|
|
176
|
+
if (typeof value === "string") {
|
|
177
|
+
validated[key] = boundedText(
|
|
178
|
+
`issue breadcrumb data value for ${key}`,
|
|
179
|
+
value,
|
|
180
|
+
MAX_BREADCRUMB_DATA_STRING_LENGTH
|
|
181
|
+
);
|
|
182
|
+
} else if (typeof value === "number") {
|
|
183
|
+
if (!Number.isFinite(value)) {
|
|
184
|
+
throw validationError(`issue breadcrumb data value for ${key} must be finite`);
|
|
185
|
+
}
|
|
186
|
+
validated[key] = value;
|
|
187
|
+
} else if (typeof value === "boolean" || value === null) {
|
|
188
|
+
validated[key] = value;
|
|
189
|
+
} else {
|
|
190
|
+
throw validationError(
|
|
191
|
+
`issue breadcrumb data value for ${key} must be a string, number, boolean, or null`
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return validated;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function optionalMachineName(label, value) {
|
|
199
|
+
if (value === undefined) {
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
if (typeof value !== "string" || !MACHINE_NAME_PATTERN.test(value)) {
|
|
203
|
+
throw validationError(`${label} must match ${MACHINE_NAME_PATTERN}`);
|
|
204
|
+
}
|
|
205
|
+
if (Array.from(value).length > MAX_BREADCRUMB_NAME_LENGTH) {
|
|
206
|
+
throw validationError(`${label} must be at most ${MAX_BREADCRUMB_NAME_LENGTH} characters`);
|
|
207
|
+
}
|
|
208
|
+
return value;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function optionalBreadcrumbLevel(value) {
|
|
212
|
+
if (value === undefined) {
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
const normalized = typeof value === "string" ? BREADCRUMB_LEVEL_ALIASES.get(value) : undefined;
|
|
216
|
+
if (normalized === undefined) {
|
|
217
|
+
throw validationError(
|
|
218
|
+
`issue breadcrumb level must be one of: ${Array.from(BREADCRUMB_LEVEL_ALIASES.keys()).join(", ")}`
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
return normalized;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function boundedText(label, value, maxLength, { rejectLocationText = false } = {}) {
|
|
225
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
226
|
+
throw validationError(`${label} must be non-empty`);
|
|
227
|
+
}
|
|
228
|
+
if (
|
|
229
|
+
Array.from(value).length > maxLength
|
|
230
|
+
|| hasControlCharacter(value)
|
|
231
|
+
|| (rejectLocationText && /[?#]/u.test(value))
|
|
232
|
+
) {
|
|
233
|
+
throw validationError(`${label} is invalid or exceeds ${maxLength} characters`);
|
|
234
|
+
}
|
|
235
|
+
return value;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function requireObject(label, value) {
|
|
239
|
+
if (!value || Array.isArray(value) || typeof value !== "object") {
|
|
240
|
+
throw validationError(`${label} must be an object`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function rejectUnknownKeys(label, value, allowed) {
|
|
245
|
+
const unknown = Object.keys(value).filter((key) => !allowed.has(key));
|
|
246
|
+
if (unknown.length > 0) {
|
|
247
|
+
throw validationError(`${label} has unsupported fields: ${unknown.sort().join(", ")}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function hasControlCharacter(value) {
|
|
252
|
+
return Array.from(value).some((character) => {
|
|
253
|
+
const code = character.codePointAt(0);
|
|
254
|
+
return code !== undefined && (code <= 31 || (code >= 127 && code <= 159));
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return {
|
|
259
|
+
MAX_ISSUE_BREADCRUMBS,
|
|
260
|
+
cloneIssueDiagnostics,
|
|
261
|
+
createIssueException,
|
|
262
|
+
validateIssueBreadcrumb,
|
|
263
|
+
validateIssueDiagnostics
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
module.exports = { buildIssueDiagnosticsHelpers };
|