@logbrew/sdk 0.1.4 → 0.1.6
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 +1 -1
- package/core.cjs +2398 -0
- package/index.cjs +3 -2666
- package/log-context.cjs +95 -0
- package/package.json +11 -1
- package/react-native.d.ts +103 -0
- package/react-native.js +34 -0
- package/winston.cjs +273 -0
package/log-context.cjs
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const ZERO_TRACE_ID = "00000000000000000000000000000000";
|
|
2
|
+
const ZERO_SPAN_ID = "0000000000000000";
|
|
3
|
+
|
|
4
|
+
function buildLogContextHelpers({ SdkError }) {
|
|
5
|
+
function compactMetadata(metadata) {
|
|
6
|
+
if (metadata === undefined) {
|
|
7
|
+
return {};
|
|
8
|
+
}
|
|
9
|
+
if (!metadata || Array.isArray(metadata) || typeof metadata !== "object") {
|
|
10
|
+
throw new SdkError("validation_error", "metadata must be an object");
|
|
11
|
+
}
|
|
12
|
+
const safeMetadata = {};
|
|
13
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
14
|
+
if (isMetadataValue(value)) {
|
|
15
|
+
safeMetadata[key] = value;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return safeMetadata;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function traceFromProvider(provider, onError) {
|
|
22
|
+
if (!provider) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
return provider();
|
|
27
|
+
} catch (error) {
|
|
28
|
+
onError(error);
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
compactMetadata,
|
|
35
|
+
isMetadataValue,
|
|
36
|
+
normalizeLogTraceContext,
|
|
37
|
+
traceFromProvider,
|
|
38
|
+
traceMetadataFromLogContext
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function isMetadataValue(value) {
|
|
43
|
+
return (
|
|
44
|
+
value === null
|
|
45
|
+
|| typeof value === "string"
|
|
46
|
+
|| typeof value === "number" && Number.isFinite(value)
|
|
47
|
+
|| typeof value === "boolean"
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function traceMetadataFromLogContext(trace) {
|
|
52
|
+
const normalized = normalizeLogTraceContext(trace);
|
|
53
|
+
if (!normalized) {
|
|
54
|
+
return {};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
traceId: normalized.traceId,
|
|
58
|
+
spanId: normalized.spanId,
|
|
59
|
+
...(normalized.parentSpanId !== undefined ? { parentSpanId: normalized.parentSpanId } : {}),
|
|
60
|
+
...(normalized.sampled !== undefined ? { sampled: normalized.sampled } : {})
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function normalizeLogTraceContext(trace) {
|
|
65
|
+
if (!trace || Array.isArray(trace) || typeof trace !== "object") {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
const traceId = normalizeHexId(trace.traceId, 32, ZERO_TRACE_ID);
|
|
69
|
+
const spanId = normalizeHexId(trace.spanId, 16, ZERO_SPAN_ID);
|
|
70
|
+
if (!traceId || !spanId) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
const parentSpanId = normalizeHexId(trace.parentSpanId, 16, ZERO_SPAN_ID);
|
|
74
|
+
return {
|
|
75
|
+
traceId,
|
|
76
|
+
spanId,
|
|
77
|
+
...(parentSpanId !== undefined ? { parentSpanId } : {}),
|
|
78
|
+
...(typeof trace.sampled === "boolean" ? { sampled: trace.sampled } : {})
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function normalizeHexId(value, length, zeroValue) {
|
|
83
|
+
if (typeof value !== "string") {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
const pattern = length === 32
|
|
87
|
+
? /^[0-9a-fA-F]{32}$/u
|
|
88
|
+
: /^[0-9a-fA-F]{16}$/u;
|
|
89
|
+
if (!pattern.test(value) || value.toLowerCase() === zeroValue) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
return value.toLowerCase();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = { buildLogContextHelpers };
|
package/package.json
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logbrew/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Public LogBrew JavaScript SDK for building, validating, and flushing event batches.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.cjs",
|
|
7
|
+
"react-native": "./react-native.js",
|
|
7
8
|
"types": "./index.d.ts",
|
|
8
9
|
"bin": {
|
|
9
10
|
"logbrew-release-artifacts": "./release-artifacts.js"
|
|
10
11
|
},
|
|
11
12
|
"exports": {
|
|
12
13
|
".": {
|
|
14
|
+
"react-native": {
|
|
15
|
+
"types": "./react-native.d.ts",
|
|
16
|
+
"default": "./react-native.js"
|
|
17
|
+
},
|
|
13
18
|
"import": {
|
|
14
19
|
"types": "./index.d.ts",
|
|
15
20
|
"default": "./index.js"
|
|
@@ -34,13 +39,18 @@
|
|
|
34
39
|
},
|
|
35
40
|
"files": [
|
|
36
41
|
"index.cjs",
|
|
42
|
+
"core.cjs",
|
|
37
43
|
"index.js",
|
|
38
44
|
"index.d.ts",
|
|
39
45
|
"index.d.cts",
|
|
40
46
|
"issue-stack.cjs",
|
|
47
|
+
"log-context.cjs",
|
|
41
48
|
"opentelemetry.cjs",
|
|
49
|
+
"react-native.js",
|
|
50
|
+
"react-native.d.ts",
|
|
42
51
|
"support-ticket.cjs",
|
|
43
52
|
"trace-context.cjs",
|
|
53
|
+
"winston.cjs",
|
|
44
54
|
"release-artifacts-common.js",
|
|
45
55
|
"release-artifacts-build.cjs",
|
|
46
56
|
"release-artifacts.js",
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import * as core from "./index.js";
|
|
2
|
+
|
|
3
|
+
export type {
|
|
4
|
+
ActionAttributes,
|
|
5
|
+
BaggageEntry,
|
|
6
|
+
ConsoleCaptureConfig,
|
|
7
|
+
ConsoleCaptureHandle,
|
|
8
|
+
ConsoleLike,
|
|
9
|
+
ConsoleMethodName,
|
|
10
|
+
CurrentOpenTelemetryTraceContextOptions,
|
|
11
|
+
DeliveryHealthSnapshot,
|
|
12
|
+
DroppedEvent,
|
|
13
|
+
EnvironmentAttributes,
|
|
14
|
+
Event,
|
|
15
|
+
EventFilter,
|
|
16
|
+
EventStore,
|
|
17
|
+
IssueAttributes,
|
|
18
|
+
IssueStackFrame,
|
|
19
|
+
JavaScriptErrorIssueOptions,
|
|
20
|
+
LogAttributes,
|
|
21
|
+
LogCorrelationTraceContext,
|
|
22
|
+
Metadata,
|
|
23
|
+
MetadataValue,
|
|
24
|
+
MetricAttributes,
|
|
25
|
+
NetworkMilestoneInput,
|
|
26
|
+
OpenTelemetryApiLike,
|
|
27
|
+
OpenTelemetryExportResult,
|
|
28
|
+
OpenTelemetryHrTimeLike,
|
|
29
|
+
OpenTelemetryReadableSpanLike,
|
|
30
|
+
OpenTelemetryReadableSpanOptions,
|
|
31
|
+
OpenTelemetrySpanContextLike,
|
|
32
|
+
OpenTelemetrySpanExporterConfig,
|
|
33
|
+
OpenTelemetrySpanExporterHandle,
|
|
34
|
+
OpenTelemetrySpanLike,
|
|
35
|
+
OpenTelemetrySpanLinkLike,
|
|
36
|
+
OpenTelemetrySpanProcessorConfig,
|
|
37
|
+
OpenTelemetrySpanProcessorHandle,
|
|
38
|
+
OpenTelemetryTimedEventLike,
|
|
39
|
+
OpenTelemetryTraceContextOptions,
|
|
40
|
+
PinoDestinationConfig,
|
|
41
|
+
PinoDestinationHandle,
|
|
42
|
+
PinoLogRecord,
|
|
43
|
+
ProductActionInput,
|
|
44
|
+
ReleaseAttributes,
|
|
45
|
+
Severity,
|
|
46
|
+
SeverityAlias,
|
|
47
|
+
SeverityInput,
|
|
48
|
+
SpanAttributes,
|
|
49
|
+
SpanEventSummary,
|
|
50
|
+
SpanLinkSummary,
|
|
51
|
+
StoredEvent,
|
|
52
|
+
SupportDiagnosticsValue,
|
|
53
|
+
SupportTicketCategory,
|
|
54
|
+
SupportTicketDraft,
|
|
55
|
+
SupportTicketDraftInput,
|
|
56
|
+
SupportTicketSource,
|
|
57
|
+
TimelineAttributesOptions,
|
|
58
|
+
TraceContextInput,
|
|
59
|
+
TraceparentContext,
|
|
60
|
+
TraceparentInput,
|
|
61
|
+
TraceparentSpanInput,
|
|
62
|
+
TracestateEntry,
|
|
63
|
+
Transport,
|
|
64
|
+
TransportResponse
|
|
65
|
+
} from "./index.js";
|
|
66
|
+
|
|
67
|
+
export {
|
|
68
|
+
createBaggage,
|
|
69
|
+
createIssueAttributesFromError,
|
|
70
|
+
createLogBrewOpenTelemetrySpanExporter,
|
|
71
|
+
createLogBrewOpenTelemetrySpanProcessor,
|
|
72
|
+
createLogBrewPinoDestination,
|
|
73
|
+
createNetworkMilestoneAttributes,
|
|
74
|
+
createProductActionAttributes,
|
|
75
|
+
createSupportTicketDraft,
|
|
76
|
+
createTraceContextHeaders,
|
|
77
|
+
createTraceparent,
|
|
78
|
+
createTraceparentHeaders,
|
|
79
|
+
createTracestate,
|
|
80
|
+
installLogBrewConsoleCapture,
|
|
81
|
+
LogBrewClient,
|
|
82
|
+
logAttributesFromConsoleArgs,
|
|
83
|
+
logAttributesFromPinoRecord,
|
|
84
|
+
logbrewLevelFromConsoleMethod,
|
|
85
|
+
logbrewTraceContextFromCurrentOpenTelemetrySpan,
|
|
86
|
+
logbrewTraceContextFromOpenTelemetrySpan,
|
|
87
|
+
logbrewTraceContextFromOpenTelemetrySpanContext,
|
|
88
|
+
parseBaggage,
|
|
89
|
+
parseTraceparent,
|
|
90
|
+
parseTracestate,
|
|
91
|
+
RecordingTransport,
|
|
92
|
+
SdkError,
|
|
93
|
+
spanAttributesFromOpenTelemetryReadableSpan,
|
|
94
|
+
spanAttributesFromTraceparent,
|
|
95
|
+
TransportError
|
|
96
|
+
} from "./index.js";
|
|
97
|
+
|
|
98
|
+
declare const sdk: Omit<
|
|
99
|
+
typeof core,
|
|
100
|
+
"createLogBrewWinstonTransport" | "logAttributesFromWinstonInfo"
|
|
101
|
+
>;
|
|
102
|
+
|
|
103
|
+
export default sdk;
|
package/react-native.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import sdk from "./core.cjs";
|
|
2
|
+
|
|
3
|
+
export const {
|
|
4
|
+
createBaggage,
|
|
5
|
+
createIssueAttributesFromError,
|
|
6
|
+
createNetworkMilestoneAttributes,
|
|
7
|
+
createProductActionAttributes,
|
|
8
|
+
createLogBrewOpenTelemetrySpanExporter,
|
|
9
|
+
createLogBrewOpenTelemetrySpanProcessor,
|
|
10
|
+
createSupportTicketDraft,
|
|
11
|
+
createTraceContextHeaders,
|
|
12
|
+
createTraceparent,
|
|
13
|
+
createTraceparentHeaders,
|
|
14
|
+
createTracestate,
|
|
15
|
+
createLogBrewPinoDestination,
|
|
16
|
+
installLogBrewConsoleCapture,
|
|
17
|
+
LogBrewClient,
|
|
18
|
+
logbrewTraceContextFromCurrentOpenTelemetrySpan,
|
|
19
|
+
logbrewTraceContextFromOpenTelemetrySpan,
|
|
20
|
+
logbrewTraceContextFromOpenTelemetrySpanContext,
|
|
21
|
+
logAttributesFromConsoleArgs,
|
|
22
|
+
logAttributesFromPinoRecord,
|
|
23
|
+
logbrewLevelFromConsoleMethod,
|
|
24
|
+
parseBaggage,
|
|
25
|
+
parseTraceparent,
|
|
26
|
+
parseTracestate,
|
|
27
|
+
RecordingTransport,
|
|
28
|
+
SdkError,
|
|
29
|
+
spanAttributesFromOpenTelemetryReadableSpan,
|
|
30
|
+
spanAttributesFromTraceparent,
|
|
31
|
+
TransportError
|
|
32
|
+
} = sdk;
|
|
33
|
+
|
|
34
|
+
export default sdk;
|
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
|
+
};
|