@logbrew/sdk 0.1.3 → 0.1.5
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 +336 -2
- package/core.cjs +2338 -0
- package/examples/real-user-smoke.cjs +15 -1
- package/examples/real-user-smoke.mjs +15 -1
- package/index.cjs +3 -1336
- package/index.d.cts +461 -6
- package/index.d.ts +461 -6
- package/index.js +13 -0
- package/issue-stack.cjs +149 -0
- package/log-context.cjs +95 -0
- package/opentelemetry.cjs +1080 -0
- package/package.json +38 -1
- package/react-native.d.ts +103 -0
- package/react-native.js +34 -0
- package/release-artifacts-build.cjs +227 -0
- package/release-artifacts-common.js +82 -0
- package/release-artifacts-symbolication.js +550 -0
- package/release-artifacts-upload.js +380 -0
- package/release-artifacts.js +766 -0
- package/support-ticket.cjs +175 -0
- package/trace-context.cjs +217 -0
- package/vite-release-artifacts.cjs +152 -0
- package/vite-release-artifacts.d.cts +44 -0
- package/vite-release-artifacts.d.ts +44 -0
- package/vite-release-artifacts.js +6 -0
- package/winston.cjs +273 -0
package/winston.cjs
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
const { Writable } = require("node:stream");
|
|
2
|
+
|
|
3
|
+
const { LogBrewClient, SdkError } = require("./core.cjs");
|
|
4
|
+
const { buildLogContextHelpers } = require("./log-context.cjs");
|
|
5
|
+
|
|
6
|
+
const WINSTON_RESERVED_FIELDS = new Set([
|
|
7
|
+
"level",
|
|
8
|
+
"message",
|
|
9
|
+
"timestamp",
|
|
10
|
+
"time",
|
|
11
|
+
"err",
|
|
12
|
+
"error",
|
|
13
|
+
"stack"
|
|
14
|
+
]);
|
|
15
|
+
const {
|
|
16
|
+
compactMetadata,
|
|
17
|
+
isMetadataValue,
|
|
18
|
+
traceFromProvider,
|
|
19
|
+
traceMetadataFromLogContext
|
|
20
|
+
} = buildLogContextHelpers({ SdkError });
|
|
21
|
+
|
|
22
|
+
function createLogBrewWinstonTransport(config) {
|
|
23
|
+
if (!config || typeof config !== "object") {
|
|
24
|
+
throw new SdkError("validation_error", "Winston transport config must be an object");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const client = config.client;
|
|
28
|
+
if (!(client instanceof LogBrewClient)) {
|
|
29
|
+
throw new SdkError("validation_error", "Winston transport client must be a LogBrewClient");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const transport = config.transport;
|
|
33
|
+
const flushOnWrite = config.flushOnWrite === true;
|
|
34
|
+
const includeErrorStack = config.includeErrorStack === true;
|
|
35
|
+
const logger = config.logger ?? "winston";
|
|
36
|
+
const metadata = compactMetadata(config.metadata);
|
|
37
|
+
const timestamp = typeof config.timestamp === "function"
|
|
38
|
+
? config.timestamp
|
|
39
|
+
: () => new Date().toISOString();
|
|
40
|
+
const eventIdPrefix = config.eventIdPrefix ?? "winston";
|
|
41
|
+
const onError = typeof config.onError === "function" ? config.onError : () => {};
|
|
42
|
+
const traceProvider = typeof config.traceProvider === "function" ? config.traceProvider : null;
|
|
43
|
+
const state = {
|
|
44
|
+
captured: 0,
|
|
45
|
+
pendingFlush: Promise.resolve(null)
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const winstonTransport = new Writable({
|
|
49
|
+
objectMode: true,
|
|
50
|
+
write(info, _encoding, callback) {
|
|
51
|
+
try {
|
|
52
|
+
captureWinstonInfo({
|
|
53
|
+
client,
|
|
54
|
+
eventIdPrefix,
|
|
55
|
+
flushOnWrite,
|
|
56
|
+
includeErrorStack,
|
|
57
|
+
info,
|
|
58
|
+
logger,
|
|
59
|
+
metadata,
|
|
60
|
+
onError,
|
|
61
|
+
state,
|
|
62
|
+
timestamp,
|
|
63
|
+
traceProvider,
|
|
64
|
+
transport
|
|
65
|
+
});
|
|
66
|
+
} catch (error) {
|
|
67
|
+
onError(error);
|
|
68
|
+
} finally {
|
|
69
|
+
callback();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
winstonTransport.log = function log(info, callback) {
|
|
75
|
+
this.write(info);
|
|
76
|
+
if (typeof callback === "function") {
|
|
77
|
+
callback();
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
winstonTransport.flush = async () => {
|
|
81
|
+
if (transport && client.pendingEvents() > 0) {
|
|
82
|
+
state.pendingFlush = Promise.resolve(client.flush(transport)).catch((error) => {
|
|
83
|
+
onError(error);
|
|
84
|
+
return null;
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return state.pendingFlush;
|
|
88
|
+
};
|
|
89
|
+
if (typeof config.level === "string" && config.level.trim() !== "") {
|
|
90
|
+
winstonTransport.level = config.level;
|
|
91
|
+
}
|
|
92
|
+
if (config.name !== undefined) {
|
|
93
|
+
winstonTransport.name = String(config.name);
|
|
94
|
+
}
|
|
95
|
+
if (config.silent === true) {
|
|
96
|
+
winstonTransport.silent = true;
|
|
97
|
+
}
|
|
98
|
+
if (config.handleExceptions === true) {
|
|
99
|
+
winstonTransport.handleExceptions = true;
|
|
100
|
+
}
|
|
101
|
+
if (config.handleRejections === true) {
|
|
102
|
+
winstonTransport.handleRejections = true;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return winstonTransport;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function captureWinstonInfo(config) {
|
|
109
|
+
if (config.info?.silent === true) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
config.state.captured += 1;
|
|
113
|
+
config.client.log(
|
|
114
|
+
`${config.eventIdPrefix}_${config.state.captured}`,
|
|
115
|
+
timestampFromWinstonInfo(config.info, config.timestamp),
|
|
116
|
+
logAttributesFromWinstonInfo(config.info, {
|
|
117
|
+
includeErrorStack: config.includeErrorStack,
|
|
118
|
+
logger: config.logger,
|
|
119
|
+
metadata: config.metadata,
|
|
120
|
+
trace: traceFromProvider(config.traceProvider, config.onError)
|
|
121
|
+
})
|
|
122
|
+
);
|
|
123
|
+
if (config.flushOnWrite && config.transport) {
|
|
124
|
+
config.state.pendingFlush = Promise.resolve(config.client.flush(config.transport)).catch((error) => {
|
|
125
|
+
config.onError(error);
|
|
126
|
+
return null;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function logAttributesFromWinstonInfo(info, options = {}) {
|
|
132
|
+
if (!info || Array.isArray(info) || typeof info !== "object") {
|
|
133
|
+
throw new SdkError("validation_error", "Winston info must be an object");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const level = logbrewLevelFromWinstonLevel(info.level);
|
|
137
|
+
const metadata = {
|
|
138
|
+
...compactMetadata(options.metadata),
|
|
139
|
+
winstonLevel: winstonLevelLabel(info.level),
|
|
140
|
+
...winstonContextMetadata(info),
|
|
141
|
+
...traceMetadataFromLogContext(options.trace)
|
|
142
|
+
};
|
|
143
|
+
addWinstonErrorMetadata(metadata, info, options.includeErrorStack === true);
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
message: winstonMessage(info),
|
|
147
|
+
level,
|
|
148
|
+
...(options.logger ? { logger: options.logger } : {}),
|
|
149
|
+
metadata
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function timestampFromWinstonInfo(info, fallbackTimestamp) {
|
|
154
|
+
const value = info?.timestamp ?? info?.time;
|
|
155
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
156
|
+
return new Date(value).toISOString();
|
|
157
|
+
}
|
|
158
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
159
|
+
const parsed = new Date(value);
|
|
160
|
+
if (!Number.isNaN(parsed.valueOf())) {
|
|
161
|
+
return parsed.toISOString();
|
|
162
|
+
}
|
|
163
|
+
return value;
|
|
164
|
+
}
|
|
165
|
+
if (value instanceof Date && !Number.isNaN(value.valueOf())) {
|
|
166
|
+
return value.toISOString();
|
|
167
|
+
}
|
|
168
|
+
return fallbackTimestamp();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function logbrewLevelFromWinstonLevel(level) {
|
|
172
|
+
switch (String(level).toLowerCase()) {
|
|
173
|
+
case "debug":
|
|
174
|
+
case "silly":
|
|
175
|
+
return "info";
|
|
176
|
+
case "warn":
|
|
177
|
+
case "warning":
|
|
178
|
+
return "warning";
|
|
179
|
+
case "error":
|
|
180
|
+
return "error";
|
|
181
|
+
case "crit":
|
|
182
|
+
case "critical":
|
|
183
|
+
case "fatal":
|
|
184
|
+
return "critical";
|
|
185
|
+
case "http":
|
|
186
|
+
case "verbose":
|
|
187
|
+
case "info":
|
|
188
|
+
default:
|
|
189
|
+
return "info";
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function winstonLevelLabel(level) {
|
|
194
|
+
return typeof level === "string" && level.trim() !== "" ? level : "info";
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function winstonMessage(info) {
|
|
198
|
+
if (typeof info.message === "string" && info.message.trim() !== "") {
|
|
199
|
+
return info.message;
|
|
200
|
+
}
|
|
201
|
+
const error = info.err ?? info.error;
|
|
202
|
+
if (error && typeof error === "object" && typeof error.message === "string" && error.message.trim() !== "") {
|
|
203
|
+
return error.message;
|
|
204
|
+
}
|
|
205
|
+
return "winston event";
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function winstonContextMetadata(info) {
|
|
209
|
+
const metadata = {};
|
|
210
|
+
for (const [key, value] of Object.entries(info)) {
|
|
211
|
+
if (!WINSTON_RESERVED_FIELDS.has(key) && isMetadataValue(value)) {
|
|
212
|
+
metadata[`context.${key}`] = value;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return metadata;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function addWinstonErrorMetadata(metadata, info, includeErrorStack) {
|
|
219
|
+
const error = info.err ?? info.error;
|
|
220
|
+
addWinstonNestedErrorMetadata(metadata, error, includeErrorStack);
|
|
221
|
+
if (typeof info.stack === "string" && info.stack.trim() !== "") {
|
|
222
|
+
const firstLine = info.stack.split(/\r?\n/u)[0] ?? "";
|
|
223
|
+
const match = /^([A-Za-z][A-Za-z0-9_.]*(?:Error|Exception)?):\s*(.*)$/u.exec(firstLine);
|
|
224
|
+
if (match && metadata.errorName === undefined) {
|
|
225
|
+
metadata.errorName = match[1];
|
|
226
|
+
}
|
|
227
|
+
if (match && match[2] && metadata.errorMessage === undefined) {
|
|
228
|
+
metadata.errorMessage = match[2];
|
|
229
|
+
}
|
|
230
|
+
if (includeErrorStack) {
|
|
231
|
+
metadata.errorStack = info.stack;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function addWinstonNestedErrorMetadata(metadata, error, includeErrorStack) {
|
|
237
|
+
if (!error) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (error instanceof Error) {
|
|
241
|
+
metadata.errorName = error.name || "Error";
|
|
242
|
+
if (error.message) {
|
|
243
|
+
metadata.errorMessage = error.message;
|
|
244
|
+
}
|
|
245
|
+
if (includeErrorStack && error.stack) {
|
|
246
|
+
metadata.errorStack = error.stack;
|
|
247
|
+
}
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (typeof error === "object") {
|
|
251
|
+
const name = error.type ?? error.name;
|
|
252
|
+
const message = error.message;
|
|
253
|
+
const stack = error.stack;
|
|
254
|
+
if (typeof name === "string" && name.trim() !== "") {
|
|
255
|
+
metadata.errorName = name;
|
|
256
|
+
}
|
|
257
|
+
if (typeof message === "string" && message.trim() !== "") {
|
|
258
|
+
metadata.errorMessage = message;
|
|
259
|
+
}
|
|
260
|
+
if (includeErrorStack && typeof stack === "string" && stack.trim() !== "") {
|
|
261
|
+
metadata.errorStack = stack;
|
|
262
|
+
}
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (typeof error === "string" && error.trim() !== "") {
|
|
266
|
+
metadata.errorMessage = error;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
module.exports = {
|
|
271
|
+
createLogBrewWinstonTransport,
|
|
272
|
+
logAttributesFromWinstonInfo
|
|
273
|
+
};
|