@superblocksteam/sdk 2.0.114 → 2.0.115-next.1
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/.turbo/turbo-build.log +1 -1
- package/dist/cli-replacement/dev.d.mts.map +1 -1
- package/dist/cli-replacement/dev.mjs +93 -1
- package/dist/cli-replacement/dev.mjs.map +1 -1
- package/dist/dev-utils/dev-server.d.mts.map +1 -1
- package/dist/dev-utils/dev-server.mjs +10 -2
- package/dist/dev-utils/dev-server.mjs.map +1 -1
- package/dist/dev-utils/vite-dev-server-diagnostics.d.mts +61 -0
- package/dist/dev-utils/vite-dev-server-diagnostics.d.mts.map +1 -0
- package/dist/dev-utils/vite-dev-server-diagnostics.mjs +133 -0
- package/dist/dev-utils/vite-dev-server-diagnostics.mjs.map +1 -0
- package/dist/telemetry/logging.d.ts.map +1 -1
- package/dist/telemetry/logging.js +22 -10
- package/dist/telemetry/logging.js.map +1 -1
- package/dist/telemetry/logging.test.d.ts +2 -0
- package/dist/telemetry/logging.test.d.ts.map +1 -0
- package/dist/telemetry/logging.test.js +104 -0
- package/dist/telemetry/logging.test.js.map +1 -0
- package/package.json +7 -7
- package/src/cli-replacement/dev.mts +111 -4
- package/src/dev-utils/dev-server.mts +15 -2
- package/src/dev-utils/vite-dev-server-diagnostics.mts +213 -0
- package/src/telemetry/logging.test.ts +142 -0
- package/src/telemetry/logging.ts +30 -10
- package/test/vite-dev-server-diagnostics.test.mts +336 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/turbo.json +1 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers to classify Vite / esbuild stderr and emit logs that are easy to facet in Datadog
|
|
3
|
+
* (stable tokens: sdk_dev_server_vite_error, category=module_resolve, unresolved_specifier=...).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** Maximum characters of raw Vite/esbuild output stored on the error meta stack field. */
|
|
7
|
+
export const VITE_ERROR_RAW_LOG_MAX_CHARS = 12_000;
|
|
8
|
+
|
|
9
|
+
export type ViteBuildErrorDiagnostic =
|
|
10
|
+
| {
|
|
11
|
+
category: "module_resolve";
|
|
12
|
+
/** Package specifier esbuild could not resolve, when detected. */
|
|
13
|
+
unresolvedSpecifier: string;
|
|
14
|
+
}
|
|
15
|
+
| {
|
|
16
|
+
category: "optimize_deps" | "unknown";
|
|
17
|
+
unresolvedSpecifier?: undefined;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type BuildViteBuildErrorLogDeps = {
|
|
21
|
+
diagnose: typeof diagnoseViteBuildLogMessage;
|
|
22
|
+
formatSummary: typeof formatViteBuildErrorLogSummary;
|
|
23
|
+
errorKind: typeof viteErrorKindForDiagnostic;
|
|
24
|
+
truncate: typeof truncateViteRawLog;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
type BuildViteBuildErrorLogParams = {
|
|
28
|
+
rawMessage: string;
|
|
29
|
+
sdkVersion: string;
|
|
30
|
+
viteRootBasename: string;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function quoteFacetValue(value: string): string {
|
|
34
|
+
if (/^[A-Za-z0-9@._:/-]+$/.test(value)) {
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
return JSON.stringify(value);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Best-effort parse of Vite/esbuild multi-line error text (optimizeDeps, build, etc.).
|
|
42
|
+
*/
|
|
43
|
+
export function diagnoseViteBuildLogMessage(
|
|
44
|
+
msg: string,
|
|
45
|
+
): ViteBuildErrorDiagnostic {
|
|
46
|
+
const resolveMatch = msg.match(/Could not resolve ['"]([^'"]+)['"]/);
|
|
47
|
+
if (resolveMatch?.[1]) {
|
|
48
|
+
return {
|
|
49
|
+
category: "module_resolve",
|
|
50
|
+
unresolvedSpecifier: resolveMatch[1],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (/\boptimizeDeps\b|pre-bundl/i.test(msg)) {
|
|
54
|
+
return { category: "optimize_deps" };
|
|
55
|
+
}
|
|
56
|
+
return { category: "unknown" };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function formatViteDevServerStartedLog(params: {
|
|
60
|
+
sdkVersion: string;
|
|
61
|
+
viteRootBasename: string;
|
|
62
|
+
}): string {
|
|
63
|
+
return `sdk_dev_server_vite_ready sdk_version=${quoteFacetValue(params.sdkVersion)} vite_root=${quoteFacetValue(params.viteRootBasename)}`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function formatViteBuildErrorLogSummary(params: {
|
|
67
|
+
diagnostic: ViteBuildErrorDiagnostic;
|
|
68
|
+
sdkVersion: string;
|
|
69
|
+
viteRootBasename: string;
|
|
70
|
+
}): string {
|
|
71
|
+
const { diagnostic, sdkVersion, viteRootBasename } = params;
|
|
72
|
+
const parts = [
|
|
73
|
+
"sdk_dev_server_vite_error",
|
|
74
|
+
`sdk_version=${quoteFacetValue(sdkVersion)}`,
|
|
75
|
+
`vite_root=${quoteFacetValue(viteRootBasename)}`,
|
|
76
|
+
`category=${diagnostic.category}`,
|
|
77
|
+
];
|
|
78
|
+
if (diagnostic.unresolvedSpecifier) {
|
|
79
|
+
parts.push(
|
|
80
|
+
`unresolved_specifier=${quoteFacetValue(diagnostic.unresolvedSpecifier)}`,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return parts.join(" ");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function viteErrorKindForDiagnostic(
|
|
87
|
+
diagnostic: ViteBuildErrorDiagnostic,
|
|
88
|
+
): string {
|
|
89
|
+
switch (diagnostic.category) {
|
|
90
|
+
case "module_resolve":
|
|
91
|
+
return "ViteModuleResolveError";
|
|
92
|
+
case "optimize_deps":
|
|
93
|
+
return "ViteOptimizeDepsError";
|
|
94
|
+
case "unknown":
|
|
95
|
+
return "ViteBuildError";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
throw new Error(
|
|
99
|
+
`Unhandled Vite build diagnostic category: ${String((diagnostic as { category?: unknown }).category)}`,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function truncateViteRawLog(msg: string): string {
|
|
104
|
+
if (msg.length <= VITE_ERROR_RAW_LOG_MAX_CHARS) {
|
|
105
|
+
return msg;
|
|
106
|
+
}
|
|
107
|
+
return `${msg.slice(0, VITE_ERROR_RAW_LOG_MAX_CHARS)}\n...(truncated)`;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function defaultBuildSummary(params: BuildViteBuildErrorLogParams): string {
|
|
111
|
+
return formatViteBuildErrorLogSummary({
|
|
112
|
+
diagnostic: { category: "unknown" },
|
|
113
|
+
sdkVersion: params.sdkVersion,
|
|
114
|
+
viteRootBasename: params.viteRootBasename,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function diagnosticsFailureMeta(error: unknown, rawMessage: string) {
|
|
119
|
+
return {
|
|
120
|
+
error: {
|
|
121
|
+
kind: "ViteDiagnosticsError",
|
|
122
|
+
message: error instanceof Error ? error.message : "unknown",
|
|
123
|
+
stack: truncateViteRawLog(rawMessage),
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function buildViteBuildErrorLog(
|
|
129
|
+
params: BuildViteBuildErrorLogParams,
|
|
130
|
+
overrides?: Partial<BuildViteBuildErrorLogDeps>,
|
|
131
|
+
): {
|
|
132
|
+
error: {
|
|
133
|
+
kind: string;
|
|
134
|
+
message: string;
|
|
135
|
+
stack: string;
|
|
136
|
+
};
|
|
137
|
+
message: string;
|
|
138
|
+
} {
|
|
139
|
+
const deps: BuildViteBuildErrorLogDeps = {
|
|
140
|
+
diagnose: diagnoseViteBuildLogMessage,
|
|
141
|
+
errorKind: viteErrorKindForDiagnostic,
|
|
142
|
+
formatSummary: formatViteBuildErrorLogSummary,
|
|
143
|
+
truncate: truncateViteRawLog,
|
|
144
|
+
...overrides,
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
const diagnostic = deps.diagnose(params.rawMessage);
|
|
149
|
+
return {
|
|
150
|
+
error: {
|
|
151
|
+
kind: deps.errorKind(diagnostic),
|
|
152
|
+
message:
|
|
153
|
+
diagnostic.category === "module_resolve"
|
|
154
|
+
? `Could not resolve: ${diagnostic.unresolvedSpecifier}`
|
|
155
|
+
: "Vite or esbuild reported an error",
|
|
156
|
+
stack: deps.truncate(params.rawMessage),
|
|
157
|
+
},
|
|
158
|
+
message: deps.formatSummary({
|
|
159
|
+
diagnostic,
|
|
160
|
+
sdkVersion: params.sdkVersion,
|
|
161
|
+
viteRootBasename: params.viteRootBasename,
|
|
162
|
+
}),
|
|
163
|
+
};
|
|
164
|
+
} catch {
|
|
165
|
+
// Keep the final fallback independent from injected helpers so a helper bug
|
|
166
|
+
// cannot prevent us from returning some structured error payload at all.
|
|
167
|
+
return {
|
|
168
|
+
error: {
|
|
169
|
+
kind: "ViteBuildError",
|
|
170
|
+
message: "Vite or esbuild reported an error",
|
|
171
|
+
stack: truncateViteRawLog(params.rawMessage),
|
|
172
|
+
},
|
|
173
|
+
message: defaultBuildSummary(params),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function logViteBuildError(
|
|
179
|
+
logger: {
|
|
180
|
+
error: (
|
|
181
|
+
message: string,
|
|
182
|
+
meta?: {
|
|
183
|
+
error: {
|
|
184
|
+
kind: string;
|
|
185
|
+
message: string;
|
|
186
|
+
stack?: string;
|
|
187
|
+
};
|
|
188
|
+
},
|
|
189
|
+
) => void;
|
|
190
|
+
},
|
|
191
|
+
params: BuildViteBuildErrorLogParams,
|
|
192
|
+
overrides?: {
|
|
193
|
+
build?: typeof buildViteBuildErrorLog;
|
|
194
|
+
},
|
|
195
|
+
): void {
|
|
196
|
+
const build = overrides?.build ?? buildViteBuildErrorLog;
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
const viteErrorLog = build(params);
|
|
200
|
+
logger.error(viteErrorLog.message, {
|
|
201
|
+
error: viteErrorLog.error,
|
|
202
|
+
});
|
|
203
|
+
} catch (error) {
|
|
204
|
+
try {
|
|
205
|
+
logger.error(
|
|
206
|
+
params.rawMessage,
|
|
207
|
+
diagnosticsFailureMeta(error, params.rawMessage),
|
|
208
|
+
);
|
|
209
|
+
} catch {
|
|
210
|
+
// Prevent exceptions from propagating into Vite's logger internals.
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
emitMock,
|
|
5
|
+
winstonErrorMock,
|
|
6
|
+
winstonLoggerMock,
|
|
7
|
+
sanitizeLogMessageMock,
|
|
8
|
+
sanitizeLogErrorMock,
|
|
9
|
+
} = vi.hoisted(() => {
|
|
10
|
+
const emitMock = vi.fn();
|
|
11
|
+
const winstonErrorMock = vi.fn();
|
|
12
|
+
const winstonLoggerMock = {
|
|
13
|
+
debug: vi.fn(),
|
|
14
|
+
info: vi.fn(),
|
|
15
|
+
warn: vi.fn(),
|
|
16
|
+
error: winstonErrorMock,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const sanitizeLogMessageMock = vi.fn(
|
|
20
|
+
(message: string) => `sanitized-message:${message}`,
|
|
21
|
+
);
|
|
22
|
+
const sanitizeLogErrorMock = vi.fn(
|
|
23
|
+
(error: { kind: string; message: string; stack?: string }) => ({
|
|
24
|
+
...error,
|
|
25
|
+
message: `sanitized-error:${error.message}`,
|
|
26
|
+
stack: error.stack ? `sanitized-error:${error.stack}` : undefined,
|
|
27
|
+
}),
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
emitMock,
|
|
32
|
+
winstonErrorMock,
|
|
33
|
+
winstonLoggerMock,
|
|
34
|
+
sanitizeLogMessageMock,
|
|
35
|
+
sanitizeLogErrorMock,
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
vi.mock("@superblocksteam/telemetry", () => ({
|
|
40
|
+
sanitizeLogMessage: sanitizeLogMessageMock,
|
|
41
|
+
sanitizeLogError: sanitizeLogErrorMock,
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
vi.mock("./index.js", () => ({
|
|
45
|
+
getLogger: vi.fn(() => ({
|
|
46
|
+
emit: emitMock,
|
|
47
|
+
})),
|
|
48
|
+
}));
|
|
49
|
+
|
|
50
|
+
vi.mock("winston", () => ({
|
|
51
|
+
createLogger: vi.fn(() => winstonLoggerMock),
|
|
52
|
+
format: {
|
|
53
|
+
combine: vi.fn(() => ({})),
|
|
54
|
+
timestamp: vi.fn(() => ({})),
|
|
55
|
+
json: vi.fn(() => ({})),
|
|
56
|
+
printf: vi.fn(() => ({})),
|
|
57
|
+
colorize: vi.fn(() => ({})),
|
|
58
|
+
},
|
|
59
|
+
transports: {
|
|
60
|
+
File: class {
|
|
61
|
+
constructor() {}
|
|
62
|
+
},
|
|
63
|
+
Console: class {
|
|
64
|
+
constructor() {}
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
}));
|
|
68
|
+
|
|
69
|
+
import { getLogger } from "./logging.js";
|
|
70
|
+
|
|
71
|
+
describe("telemetry logger error sanitization", () => {
|
|
72
|
+
beforeEach(() => {
|
|
73
|
+
vi.clearAllMocks();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it.each(["debug", "info", "warn"] as const)(
|
|
77
|
+
"sanitizes %s-level messages before emit and winston",
|
|
78
|
+
(level) => {
|
|
79
|
+
const logger = getLogger();
|
|
80
|
+
logger[level]("api_key=secret");
|
|
81
|
+
expect(sanitizeLogMessageMock).toHaveBeenCalledWith("api_key=secret");
|
|
82
|
+
},
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
it("sanitizes error meta for traced emit and winston output", () => {
|
|
86
|
+
const logger = getLogger();
|
|
87
|
+
const meta = {
|
|
88
|
+
error: {
|
|
89
|
+
kind: "RuntimeError",
|
|
90
|
+
message: "token=super-secret-token",
|
|
91
|
+
stack: "Error: token=super-secret-token",
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
logger.error("api_key=super-secret-key", meta);
|
|
96
|
+
|
|
97
|
+
expect(sanitizeLogMessageMock).toHaveBeenCalledWith(
|
|
98
|
+
"api_key=super-secret-key",
|
|
99
|
+
);
|
|
100
|
+
expect(sanitizeLogErrorMock).toHaveBeenCalledWith(meta.error);
|
|
101
|
+
expect(emitMock).toHaveBeenCalledWith(
|
|
102
|
+
expect.objectContaining({
|
|
103
|
+
body: "sanitized-message:api_key=super-secret-key",
|
|
104
|
+
attributes: {
|
|
105
|
+
error: {
|
|
106
|
+
kind: "RuntimeError",
|
|
107
|
+
message: "sanitized-error:token=super-secret-token",
|
|
108
|
+
stack: "sanitized-error:Error: token=super-secret-token",
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
}),
|
|
112
|
+
);
|
|
113
|
+
expect(winstonErrorMock).toHaveBeenCalledWith(
|
|
114
|
+
"sanitized-message:api_key=super-secret-key",
|
|
115
|
+
{
|
|
116
|
+
error: {
|
|
117
|
+
kind: "RuntimeError",
|
|
118
|
+
message: "sanitized-error:token=super-secret-token",
|
|
119
|
+
stack: "sanitized-error:Error: token=super-secret-token",
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("does not sanitize or emit error attributes when meta is missing", () => {
|
|
126
|
+
const logger = getLogger();
|
|
127
|
+
|
|
128
|
+
logger.error("plain failure");
|
|
129
|
+
|
|
130
|
+
expect(sanitizeLogMessageMock).toHaveBeenCalledWith("plain failure");
|
|
131
|
+
expect(sanitizeLogErrorMock).not.toHaveBeenCalled();
|
|
132
|
+
expect(emitMock).toHaveBeenCalledWith(
|
|
133
|
+
expect.objectContaining({
|
|
134
|
+
body: "sanitized-message:plain failure",
|
|
135
|
+
attributes: undefined,
|
|
136
|
+
}),
|
|
137
|
+
);
|
|
138
|
+
expect(winstonErrorMock).toHaveBeenCalledWith(
|
|
139
|
+
"sanitized-message:plain failure",
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
});
|
package/src/telemetry/logging.ts
CHANGED
|
@@ -3,20 +3,32 @@ import type { AnyValueMap } from "@opentelemetry/api-logs";
|
|
|
3
3
|
import { createLogger, format, transports } from "winston";
|
|
4
4
|
import type winston from "winston";
|
|
5
5
|
|
|
6
|
+
import {
|
|
7
|
+
sanitizeLogError,
|
|
8
|
+
sanitizeLogMessage,
|
|
9
|
+
} from "@superblocksteam/telemetry";
|
|
10
|
+
|
|
6
11
|
import { getLogger as getTracedLogger } from "./index.js";
|
|
7
12
|
import { safeStringify } from "./safe-stringify.js";
|
|
8
13
|
|
|
9
14
|
const activeTransports: winston.transport[] = [];
|
|
10
15
|
|
|
11
16
|
if (process.env.SUPERBLOCKS_IS_CSB === "true") {
|
|
12
|
-
//
|
|
17
|
+
// info to stdout for cluster log shippers / kubectl logs;
|
|
18
|
+
// debug stays in /tmp/dev-server.log for on-pod triage
|
|
13
19
|
activeTransports.push(
|
|
14
20
|
new transports.File({
|
|
15
|
-
format: format.json(),
|
|
21
|
+
format: format.combine(format.timestamp(), format.json()),
|
|
16
22
|
filename: `/tmp/dev-server.log`,
|
|
17
23
|
level: "debug",
|
|
18
24
|
}),
|
|
19
25
|
);
|
|
26
|
+
activeTransports.push(
|
|
27
|
+
new transports.Console({
|
|
28
|
+
format: format.combine(format.timestamp(), format.json()),
|
|
29
|
+
level: process.env.SUPERBLOCKS_SDK_LOG_LEVEL ?? "info",
|
|
30
|
+
}),
|
|
31
|
+
);
|
|
20
32
|
} else {
|
|
21
33
|
// having no transport increases memory usage
|
|
22
34
|
activeTransports.push(
|
|
@@ -43,6 +55,7 @@ const winstonLogger = createLogger({
|
|
|
43
55
|
level: "debug",
|
|
44
56
|
exitOnError: false,
|
|
45
57
|
format: format.json(),
|
|
58
|
+
defaultMeta: { process: "child" },
|
|
46
59
|
transports: activeTransports,
|
|
47
60
|
});
|
|
48
61
|
|
|
@@ -67,7 +80,7 @@ function formatMessages(messages: unknown[]): string {
|
|
|
67
80
|
|
|
68
81
|
const logger: Logger = Object.freeze({
|
|
69
82
|
debug: (...messages: unknown[]) => {
|
|
70
|
-
const body = formatMessages(messages);
|
|
83
|
+
const body = sanitizeLogMessage(formatMessages(messages));
|
|
71
84
|
getTracedLogger().emit({
|
|
72
85
|
severityNumber: SeverityNumber.DEBUG,
|
|
73
86
|
severityText: "DEBUG",
|
|
@@ -76,7 +89,7 @@ const logger: Logger = Object.freeze({
|
|
|
76
89
|
winstonLogger.debug(body);
|
|
77
90
|
},
|
|
78
91
|
info: (...messages: unknown[]) => {
|
|
79
|
-
const body = formatMessages(messages);
|
|
92
|
+
const body = sanitizeLogMessage(formatMessages(messages));
|
|
80
93
|
getTracedLogger().emit({
|
|
81
94
|
severityNumber: SeverityNumber.INFO,
|
|
82
95
|
severityText: "INFO",
|
|
@@ -85,7 +98,7 @@ const logger: Logger = Object.freeze({
|
|
|
85
98
|
winstonLogger.info(body);
|
|
86
99
|
},
|
|
87
100
|
warn: (...messages: unknown[]) => {
|
|
88
|
-
const body = formatMessages(messages);
|
|
101
|
+
const body = sanitizeLogMessage(formatMessages(messages));
|
|
89
102
|
getTracedLogger().emit({
|
|
90
103
|
severityNumber: SeverityNumber.WARN,
|
|
91
104
|
severityText: "WARN",
|
|
@@ -94,16 +107,23 @@ const logger: Logger = Object.freeze({
|
|
|
94
107
|
winstonLogger.warn(body);
|
|
95
108
|
},
|
|
96
109
|
error: (message: string, meta?: ErrorMeta) => {
|
|
110
|
+
const safeMessage = sanitizeLogMessage(message);
|
|
111
|
+
const safeError = meta?.error
|
|
112
|
+
? (({ kind, message, stack }) => ({ kind, message, stack }))(
|
|
113
|
+
sanitizeLogError(meta.error) as ErrorMeta["error"],
|
|
114
|
+
)
|
|
115
|
+
: undefined;
|
|
116
|
+
const safeMeta = safeError ? { error: safeError } : undefined;
|
|
97
117
|
getTracedLogger().emit({
|
|
98
118
|
severityNumber: SeverityNumber.ERROR,
|
|
99
119
|
severityText: "ERROR",
|
|
100
|
-
body:
|
|
101
|
-
attributes:
|
|
120
|
+
body: safeMessage,
|
|
121
|
+
attributes: safeMeta as unknown as AnyValueMap | undefined,
|
|
102
122
|
});
|
|
103
|
-
if (
|
|
104
|
-
winstonLogger.error(
|
|
123
|
+
if (safeError) {
|
|
124
|
+
winstonLogger.error(safeMessage, { error: safeError });
|
|
105
125
|
} else {
|
|
106
|
-
winstonLogger.error(
|
|
126
|
+
winstonLogger.error(safeMessage);
|
|
107
127
|
}
|
|
108
128
|
},
|
|
109
129
|
});
|