@logbrew/sdk 0.1.37 → 0.1.39
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/automatic-delivery.cjs +271 -0
- package/batch-sender.cjs +164 -0
- package/bounded-number.cjs +34 -0
- package/browser-breadcrumbs.cjs +346 -136
- package/capture-support.cjs +100 -0
- package/client-options.cjs +292 -0
- package/client-report.cjs +232 -0
- package/client.cjs +447 -0
- package/console-arguments.cjs +151 -0
- package/console-capture.cjs +194 -0
- package/core.cjs +35 -2984
- package/delivery-health.cjs +133 -0
- package/error-causes.cjs +130 -0
- package/error-details.cjs +124 -0
- package/error-issue.cjs +187 -0
- package/event-clone.cjs +55 -0
- package/event-metadata.cjs +40 -0
- package/event-pipeline.cjs +325 -0
- package/event-queue.cjs +306 -0
- package/event-store.cjs +237 -0
- package/event-validation.cjs +159 -0
- package/examples/agent-timeline.cjs +57 -46
- package/examples/agent-timeline.mjs +41 -35
- package/examples/index.mjs +122 -94
- package/examples/readme-example.cjs +36 -27
- package/examples/readme-example.mjs +21 -17
- package/examples/real-user-smoke.cjs +41 -32
- package/examples/real-user-smoke.mjs +26 -22
- package/exception-chain.cjs +205 -0
- package/index.d.ts +144 -1076
- package/index.js +1 -1
- package/issue-breadcrumbs.cjs +143 -0
- package/issue-diagnostics.cjs +94 -582
- package/issue-evidence.cjs +256 -0
- package/issue-exception.cjs +268 -0
- package/issue-stack-frames.cjs +220 -0
- package/issue-stack-text.cjs +101 -0
- package/issue-stack.cjs +188 -225
- package/issue-text.cjs +72 -0
- package/log-context.cjs +87 -67
- package/metric-validation.cjs +95 -0
- package/network-milestone.cjs +155 -0
- package/null-value.cjs +4 -0
- package/opentelemetry-bridge.cjs +330 -0
- package/opentelemetry-context.cjs +245 -0
- package/opentelemetry-exceptions.cjs +69 -0
- package/opentelemetry-keys.cjs +183 -0
- package/opentelemetry-span.cjs +286 -0
- package/opentelemetry-summary.cjs +213 -0
- package/opentelemetry-time.cjs +131 -0
- package/opentelemetry.cjs +99 -1068
- package/package.json +64 -1
- package/pino-destination.cjs +108 -0
- package/pino-record.cjs +237 -0
- package/product-action.cjs +163 -0
- package/provided-breadcrumbs.cjs +117 -0
- package/random-hex.cjs +29 -0
- package/react-native.js +1 -1
- package/recording-transport.cjs +68 -0
- package/release-artifacts-build.cjs +263 -84
- package/release-artifacts-common.js +347 -66
- package/release-artifacts-debug-id.js +178 -0
- package/release-artifacts-inspect.js +213 -0
- package/release-artifacts-issue-event.js +99 -0
- package/release-artifacts-manifest-artifact.js +107 -0
- package/release-artifacts-manifest.js +77 -0
- package/release-artifacts-mappings.js +265 -0
- package/release-artifacts-prepare.js +297 -0
- package/release-artifacts-source-context.js +210 -0
- package/release-artifacts-symbolication.js +272 -421
- package/release-artifacts-upload-files.js +122 -0
- package/release-artifacts-upload-request.js +246 -0
- package/release-artifacts-upload.js +155 -300
- package/release-artifacts-urls.js +49 -0
- package/release-artifacts.js +189 -662
- package/retry-delay.cjs +32 -0
- package/sdk-error.cjs +36 -0
- package/span-validation.cjs +191 -0
- package/stored-events.cjs +243 -0
- package/support-ticket.cjs +232 -122
- package/telemetry-context.cjs +343 -251
- package/trace-context.cjs +376 -179
- package/transport-error.cjs +23 -0
- package/types/client.d.ts +67 -0
- package/types/delivery.d.ts +125 -0
- package/types/issues.d.ts +249 -0
- package/types/logging.d.ts +175 -0
- package/types/opentelemetry.d.ts +205 -0
- package/types/product.d.ts +128 -0
- package/types/recording-transport.d.ts +15 -0
- package/types/sdk-error.d.ts +9 -0
- package/types/telemetry.d.ts +171 -0
- package/types/trace-context.d.ts +110 -0
- package/types/transport-error.d.ts +10 -0
- package/utf8.cjs +37 -0
- package/validation.cjs +327 -0
- package/vite-release-artifacts-config.cjs +120 -0
- package/vite-release-artifacts.cjs +199 -99
- package/vite-release-artifacts.d.cts +65 -40
- package/vite-release-artifacts.d.ts +65 -40
- package/vite-release-artifacts.js +2 -2
- package/winston-info.cjs +205 -0
- package/winston.cjs +189 -290
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { SdkError } = require("./sdk-error.cjs");
|
|
4
|
+
const { isRecord } = require("./validation.cjs");
|
|
5
|
+
const {
|
|
6
|
+
SAFE_DEBUG_ID_PATTERN,
|
|
7
|
+
frameCoordinateFromText,
|
|
8
|
+
frameIdentity,
|
|
9
|
+
hasControlCharacter,
|
|
10
|
+
sanitizeFrameFilename
|
|
11
|
+
} = require("./issue-stack-text.cjs");
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @import { IssueStackFrame, NativeStackArchitecture, NativeStackFrame } from "./index.cjs"
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const MAX_ISSUE_STACK_FRAMES = 32;
|
|
18
|
+
const MAX_ISSUE_STACK_FUNCTION_LENGTH = 256;
|
|
19
|
+
const MAX_ISSUE_STACK_MODULE_LENGTH = 512;
|
|
20
|
+
const MAX_ISSUE_STACK_FILENAME_LENGTH = 2048;
|
|
21
|
+
const MAX_FRAME_COORDINATE = 2_147_483_647;
|
|
22
|
+
const NATIVE_FRAME_KEY_COUNT = 3;
|
|
23
|
+
const NO_FRAMES = 0;
|
|
24
|
+
const NATIVE_FRAME_KEYS = new Set(["imageUuid", "architecture", "instructionOffset"]);
|
|
25
|
+
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;
|
|
26
|
+
const NATIVE_OFFSET_PATTERN = /^[0-9a-f]{16}$/u;
|
|
27
|
+
/** @type {ReadonlySet<string>} */
|
|
28
|
+
const NATIVE_ARCHITECTURES = new Set(["arm", "arm64", "arm64e", "x86", "x86_64"]);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {unknown} value
|
|
32
|
+
* @returns {value is NativeStackArchitecture}
|
|
33
|
+
*/
|
|
34
|
+
function isNativeArchitecture(value) {
|
|
35
|
+
return typeof value === "string" && NATIVE_ARCHITECTURES.has(value);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param {unknown} value
|
|
40
|
+
* @returns {string}
|
|
41
|
+
*/
|
|
42
|
+
function requireFrameFilename(value) {
|
|
43
|
+
if (typeof value !== "string") {
|
|
44
|
+
throw new SdkError("validation_error", "issue stack frame filename is invalid");
|
|
45
|
+
}
|
|
46
|
+
const filename = sanitizeFrameFilename(value);
|
|
47
|
+
if (filename === "" || filename.length > MAX_ISSUE_STACK_FILENAME_LENGTH || hasControlCharacter(filename)) {
|
|
48
|
+
throw new SdkError("validation_error", "issue stack frame filename is invalid");
|
|
49
|
+
}
|
|
50
|
+
return filename;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {unknown} value
|
|
55
|
+
* @returns {number | undefined}
|
|
56
|
+
*/
|
|
57
|
+
function boundedFrameCoordinate(value) {
|
|
58
|
+
const coordinate = frameCoordinateFromText(value);
|
|
59
|
+
return coordinate !== undefined && coordinate <= MAX_FRAME_COORDINATE ? coordinate : undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @param {unknown} value
|
|
64
|
+
* @returns {string | undefined}
|
|
65
|
+
*/
|
|
66
|
+
function optionalFrameDebugId(value) {
|
|
67
|
+
if (value === undefined) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
if (typeof value !== "string" || !SAFE_DEBUG_ID_PATTERN.test(value.trim())) {
|
|
71
|
+
throw new SdkError("validation_error", "issue stack frame debugId is invalid");
|
|
72
|
+
}
|
|
73
|
+
return value.trim().toLowerCase();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @param {unknown} value
|
|
78
|
+
* @returns {string | undefined}
|
|
79
|
+
*/
|
|
80
|
+
function optionalFrameFunction(value) {
|
|
81
|
+
if (value === undefined) {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
const functionName = typeof value === "string" ? frameIdentity(value, MAX_ISSUE_STACK_FUNCTION_LENGTH, false) : undefined;
|
|
85
|
+
if (functionName === undefined) {
|
|
86
|
+
throw new SdkError("validation_error", "issue stack frame function is invalid");
|
|
87
|
+
}
|
|
88
|
+
return functionName;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @param {unknown} value
|
|
93
|
+
* @returns {string | undefined}
|
|
94
|
+
*/
|
|
95
|
+
function optionalFrameModule(value) {
|
|
96
|
+
if (value === undefined) {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
const moduleName = typeof value === "string" ? frameIdentity(value, MAX_ISSUE_STACK_MODULE_LENGTH, true) : undefined;
|
|
100
|
+
if (moduleName === undefined) {
|
|
101
|
+
throw new SdkError("validation_error", "issue stack frame module is invalid");
|
|
102
|
+
}
|
|
103
|
+
return moduleName;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @param {unknown} value
|
|
108
|
+
* @returns {boolean | undefined}
|
|
109
|
+
*/
|
|
110
|
+
function optionalFrameInApp(value) {
|
|
111
|
+
if (value === undefined || typeof value === "boolean") {
|
|
112
|
+
return value;
|
|
113
|
+
}
|
|
114
|
+
throw new SdkError("validation_error", "issue stack frame inApp is invalid");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @param {Readonly<Record<string, unknown>>} frame
|
|
119
|
+
* @returns {Pick<IssueStackFrame, "debugId" | "function" | "inApp" | "module">}
|
|
120
|
+
*/
|
|
121
|
+
function optionalFrameFields(frame) {
|
|
122
|
+
const debugId = optionalFrameDebugId(frame["debugId"]);
|
|
123
|
+
const functionName = optionalFrameFunction(frame["function"]);
|
|
124
|
+
const moduleName = optionalFrameModule(frame["module"]);
|
|
125
|
+
const inApp = optionalFrameInApp(frame["inApp"]);
|
|
126
|
+
return {
|
|
127
|
+
...(functionName === undefined ? {} : { function: functionName }),
|
|
128
|
+
...(moduleName === undefined ? {} : { module: moduleName }),
|
|
129
|
+
...(inApp === undefined ? {} : { inApp }),
|
|
130
|
+
...(debugId === undefined ? {} : { debugId })
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @param {unknown} frame
|
|
136
|
+
* @returns {IssueStackFrame}
|
|
137
|
+
*/
|
|
138
|
+
function validateIssueStackFrame(frame) {
|
|
139
|
+
if (!isRecord(frame)) {
|
|
140
|
+
throw new SdkError("validation_error", "issue stack frame must be an object");
|
|
141
|
+
}
|
|
142
|
+
const filename = requireFrameFilename(frame["filename"]);
|
|
143
|
+
const line = boundedFrameCoordinate(frame["line"]);
|
|
144
|
+
const column = boundedFrameCoordinate(frame["column"]);
|
|
145
|
+
if (line === undefined || column === undefined) {
|
|
146
|
+
throw new SdkError("validation_error", "issue stack frame coordinates must be positive integers");
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
filename,
|
|
150
|
+
line,
|
|
151
|
+
|
|
152
|
+
column,
|
|
153
|
+
...optionalFrameFields(frame)
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* @param {unknown} stackFrames
|
|
159
|
+
* @returns {IssueStackFrame[] | undefined}
|
|
160
|
+
*/
|
|
161
|
+
function validateIssueStackFrames(stackFrames) {
|
|
162
|
+
if (stackFrames === undefined) {
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
if (!Array.isArray(stackFrames) || stackFrames.length === NO_FRAMES || stackFrames.length > MAX_ISSUE_STACK_FRAMES) {
|
|
166
|
+
throw new SdkError("validation_error", `issue stackFrames must contain 1-${MAX_ISSUE_STACK_FRAMES} frames`);
|
|
167
|
+
}
|
|
168
|
+
/** @type {readonly unknown[]} */
|
|
169
|
+
const frames = stackFrames;
|
|
170
|
+
return frames.map((frame) => validateIssueStackFrame(frame));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @param {unknown} frame
|
|
175
|
+
* @returns {NativeStackFrame}
|
|
176
|
+
*/
|
|
177
|
+
function validateNativeStackFrame(frame) {
|
|
178
|
+
const keys = isRecord(frame) ? Object.keys(frame) : [];
|
|
179
|
+
if (
|
|
180
|
+
!isRecord(frame)
|
|
181
|
+
|| keys.length !== NATIVE_FRAME_KEY_COUNT
|
|
182
|
+
|| !keys.every((key) => NATIVE_FRAME_KEYS.has(key))
|
|
183
|
+
) {
|
|
184
|
+
throw new SdkError("validation_error", "issue native stack frame is invalid");
|
|
185
|
+
}
|
|
186
|
+
const { architecture, imageUuid, instructionOffset } = frame;
|
|
187
|
+
if (
|
|
188
|
+
typeof imageUuid !== "string"
|
|
189
|
+
|| !NATIVE_IMAGE_UUID_PATTERN.test(imageUuid)
|
|
190
|
+
|| !isNativeArchitecture(architecture)
|
|
191
|
+
|| typeof instructionOffset !== "string"
|
|
192
|
+
|| !NATIVE_OFFSET_PATTERN.test(instructionOffset)
|
|
193
|
+
) {
|
|
194
|
+
throw new SdkError("validation_error", "issue native stack frame is invalid");
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
imageUuid,
|
|
198
|
+
|
|
199
|
+
architecture,
|
|
200
|
+
instructionOffset
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* @param {unknown} frames
|
|
206
|
+
* @returns {NativeStackFrame[] | undefined}
|
|
207
|
+
*/
|
|
208
|
+
function validateNativeStackFrames(frames) {
|
|
209
|
+
if (frames === undefined) {
|
|
210
|
+
return undefined;
|
|
211
|
+
}
|
|
212
|
+
if (!Array.isArray(frames) || frames.length === NO_FRAMES || frames.length > MAX_ISSUE_STACK_FRAMES) {
|
|
213
|
+
throw new SdkError("validation_error", `issue nativeStackFrames must contain 1-${MAX_ISSUE_STACK_FRAMES} frames`);
|
|
214
|
+
}
|
|
215
|
+
/** @type {readonly unknown[]} */
|
|
216
|
+
const list = frames;
|
|
217
|
+
return list.map((frame) => validateNativeStackFrame(frame));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
module.exports = { validateIssueStackFrames, validateNativeStackFrames };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const NOT_FOUND = -1;
|
|
4
|
+
const TEXT_START = 0;
|
|
5
|
+
const MARKER_WIDTH = 1;
|
|
6
|
+
const NO_OFFSET = 0;
|
|
7
|
+
const MIN_FRAME_COORDINATE = 1;
|
|
8
|
+
const LAST_CONTROL_CHARACTER = 31;
|
|
9
|
+
const DELETE_CHARACTER = 127;
|
|
10
|
+
const FILE_URL_PREFIX = "file://";
|
|
11
|
+
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;
|
|
12
|
+
const FRAME_COORDINATE_PATTERN = /^(?:0|[1-9][0-9]*)$/u;
|
|
13
|
+
const TRAILING_SLASHES_PATTERN = /\/+$/u;
|
|
14
|
+
const LOCAL_ABSOLUTE_PATH_PATTERN = /(?:^|\s)(?:\/(?:Users|home|private|tmp|var|Volumes)\/|[A-Za-z]:[\\/])/u;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {string} value
|
|
18
|
+
* @returns {boolean}
|
|
19
|
+
*/
|
|
20
|
+
function hasControlCharacter(value) {
|
|
21
|
+
return [...value].some((character) => {
|
|
22
|
+
const code = character.codePointAt(TEXT_START);
|
|
23
|
+
return code !== undefined && (code <= LAST_CONTROL_CHARACTER || code === DELETE_CHARACTER);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {string} value
|
|
29
|
+
* @returns {string}
|
|
30
|
+
*/
|
|
31
|
+
function basename(value) {
|
|
32
|
+
const normalized = value.replaceAll("\\", "/").replace(TRAILING_SLASHES_PATTERN, "");
|
|
33
|
+
const marker = normalized.lastIndexOf("/");
|
|
34
|
+
return marker === NOT_FOUND ? normalized : normalized.slice(marker + MARKER_WIDTH);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {string} text
|
|
39
|
+
* @param {string} marker
|
|
40
|
+
* @returns {string}
|
|
41
|
+
*/
|
|
42
|
+
function beforeFirst(text, marker) {
|
|
43
|
+
const index = text.indexOf(marker);
|
|
44
|
+
return index === NOT_FOUND ? text : text.slice(TEXT_START, index);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @param {string} value
|
|
49
|
+
* @returns {string}
|
|
50
|
+
*/
|
|
51
|
+
function sanitizeFrameFilename(value) {
|
|
52
|
+
const trimmed = value.trim();
|
|
53
|
+
if (trimmed === "") {
|
|
54
|
+
return "";
|
|
55
|
+
}
|
|
56
|
+
const withoutQuery = beforeFirst(beforeFirst(trimmed, "?"), "#");
|
|
57
|
+
const filename = withoutQuery.startsWith(FILE_URL_PREFIX) ? withoutQuery.slice(FILE_URL_PREFIX.length) : withoutQuery;
|
|
58
|
+
return LOCAL_ABSOLUTE_PATH_PATTERN.test(filename) ? basename(filename) : filename;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param {unknown} value
|
|
63
|
+
* @param {number} [offset]
|
|
64
|
+
* @returns {number | undefined}
|
|
65
|
+
*/
|
|
66
|
+
function frameCoordinateFromText(value, offset = NO_OFFSET) {
|
|
67
|
+
const text = String(value);
|
|
68
|
+
if (!FRAME_COORDINATE_PATTERN.test(text)) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
const parsed = Number(text) + offset;
|
|
72
|
+
return Number.isSafeInteger(parsed) && parsed >= MIN_FRAME_COORDINATE ? parsed : undefined;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @param {string} value
|
|
77
|
+
* @param {number} maxLength
|
|
78
|
+
* @param {boolean} rejectLocationText
|
|
79
|
+
* @returns {string | undefined}
|
|
80
|
+
*/
|
|
81
|
+
function frameIdentity(value, maxLength, rejectLocationText) {
|
|
82
|
+
const identity = value.trim();
|
|
83
|
+
if (
|
|
84
|
+
identity === ""
|
|
85
|
+
|| [...identity].length > maxLength
|
|
86
|
+
|| hasControlCharacter(identity)
|
|
87
|
+
|| (rejectLocationText && (identity.includes("?") || identity.includes("#")))
|
|
88
|
+
) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
return identity;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = {
|
|
95
|
+
SAFE_DEBUG_ID_PATTERN,
|
|
96
|
+
basename,
|
|
97
|
+
frameCoordinateFromText,
|
|
98
|
+
frameIdentity,
|
|
99
|
+
hasControlCharacter,
|
|
100
|
+
sanitizeFrameFilename
|
|
101
|
+
};
|