@logbrew/sdk 0.1.19 → 0.1.20

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/core.cjs CHANGED
@@ -133,7 +133,8 @@ const {
133
133
 
134
134
  const {
135
135
  javascriptStackEvidence,
136
- validateIssueStackFrames
136
+ validateIssueStackFrames,
137
+ validateNativeStackFrames
137
138
  } = buildIssueStackHelpers({ SdkError });
138
139
  const {
139
140
  MAX_ISSUE_BREADCRUMBS,
@@ -2256,6 +2257,9 @@ function cloneSpanLinks(links) {
2256
2257
 
2257
2258
  function cloneEvent(event) {
2258
2259
  const attributes = { ...event.attributes, ...cloneIssueDiagnostics(event.attributes) };
2260
+ if (Array.isArray(event.attributes.nativeStackFrames)) {
2261
+ attributes.nativeStackFrames = event.attributes.nativeStackFrames.map((frame) => ({ ...frame }));
2262
+ }
2259
2263
  if (event.attributes.metadata !== undefined) {
2260
2264
  attributes.metadata = { ...event.attributes.metadata };
2261
2265
  }
@@ -2295,11 +2299,13 @@ function validateIssue(attributes) {
2295
2299
  requireNonEmpty("issue title", attributes.title);
2296
2300
  const level = normalizeSeverity("issue level", attributes.level);
2297
2301
  const stackFrames = validateIssueStackFrames(attributes.stackFrames);
2302
+ const nativeStackFrames = validateNativeStackFrames(attributes.nativeStackFrames);
2298
2303
  return withMetadata({
2299
2304
  title: attributes.title,
2300
2305
  level,
2301
2306
  ...(attributes.message !== undefined ? { message: attributes.message } : {}),
2302
2307
  ...(stackFrames !== undefined ? { stackFrames } : {}),
2308
+ ...(nativeStackFrames !== undefined ? { nativeStackFrames } : {}),
2303
2309
  ...validateIssueDiagnostics(attributes)
2304
2310
  }, attributes.metadata, attributes.context);
2305
2311
  }
package/index.d.ts CHANGED
@@ -389,6 +389,14 @@ export type IssueDiagnosticEvidence = {
389
389
  truncatedFields?: string[];
390
390
  };
391
391
 
392
+ export type NativeStackArchitecture = "arm" | "arm64" | "arm64e" | "x86" | "x86_64";
393
+
394
+ export type NativeStackFrame = {
395
+ imageUuid: string;
396
+ architecture: NativeStackArchitecture;
397
+ instructionOffset: string;
398
+ };
399
+
392
400
  /** Public issue event attributes. */
393
401
  export type IssueAttributes = {
394
402
  title: string;
@@ -399,6 +407,8 @@ export type IssueAttributes = {
399
407
  exceptionChain?: IssueExceptionChain;
400
408
  /** Ordered privacy-bounded generated frames, capped at 32. */
401
409
  stackFrames?: IssueStackFrame[];
410
+ /** Ordered native image-relative frames for exact release symbolication, capped at 32. */
411
+ nativeStackFrames?: NativeStackFrame[];
402
412
  /** Oldest-to-newest issue history, capped at the most recent 64 entries. */
403
413
  breadcrumbs?: IssueBreadcrumb[];
404
414
  /** True when older or invalid history was omitted before capture. */
package/issue-stack.cjs CHANGED
@@ -4,6 +4,9 @@ const MAX_ISSUE_STACK_FRAMES = 32;
4
4
  const MAX_ISSUE_STACK_FUNCTION_LENGTH = 256;
5
5
  const MAX_ISSUE_STACK_MODULE_LENGTH = 512;
6
6
  const SAFE_DEBUG_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;
7
+ const NATIVE_IMAGE_UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u;
8
+ const NATIVE_OFFSET_PATTERN = /^[0-9a-f]{16}$/u;
9
+ const NATIVE_ARCHITECTURES = new Set(["arm", "arm64", "arm64e", "x86", "x86_64"]);
7
10
  const LOCAL_ABSOLUTE_PATH_PATTERN = /(?:^|\s)(?:\/(?:Users|home|private|tmp|var|Volumes)\/|[A-Za-z]:[\\/])/u;
8
11
  const DEBUG_ID_REGISTRY = Symbol.for("logbrew.release-artifact.debug-ids");
9
12
 
@@ -87,7 +90,31 @@ function buildIssueStackHelpers({ SdkError }) {
87
90
  });
88
91
  }
89
92
 
90
- return { javascriptStackEvidence, validateIssueStackFrames };
93
+ function validateNativeStackFrames(frames) {
94
+ if (frames === undefined) {
95
+ return undefined;
96
+ }
97
+ if (!Array.isArray(frames) || frames.length === 0 || frames.length > MAX_ISSUE_STACK_FRAMES) {
98
+ throw new SdkError("validation_error", `issue nativeStackFrames must contain 1-${MAX_ISSUE_STACK_FRAMES} frames`);
99
+ }
100
+ return frames.map((frame) => {
101
+ const keys = frame && !Array.isArray(frame) && typeof frame === "object" ? Object.keys(frame) : [];
102
+ if (keys.length !== 3
103
+ || !keys.every((key) => ["imageUuid", "architecture", "instructionOffset"].includes(key))
104
+ || typeof frame.imageUuid !== "string" || !NATIVE_IMAGE_UUID_PATTERN.test(frame.imageUuid)
105
+ || !NATIVE_ARCHITECTURES.has(frame.architecture)
106
+ || typeof frame.instructionOffset !== "string" || !NATIVE_OFFSET_PATTERN.test(frame.instructionOffset)) {
107
+ throw new SdkError("validation_error", "issue native stack frame is invalid");
108
+ }
109
+ return {
110
+ imageUuid: frame.imageUuid,
111
+ architecture: frame.architecture,
112
+ instructionOffset: frame.instructionOffset
113
+ };
114
+ });
115
+ }
116
+
117
+ return { javascriptStackEvidence, validateIssueStackFrames, validateNativeStackFrames };
91
118
  }
92
119
 
93
120
  function parseJavaScriptStackFrame(rawLine) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logbrew/sdk",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "Public LogBrew JavaScript SDK for building, validating, and flushing event batches.",
5
5
  "type": "module",
6
6
  "main": "./index.cjs",