@rawnodes/logger 2.6.0 → 2.7.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/dist/index.d.mts CHANGED
@@ -227,7 +227,7 @@ declare abstract class BaseHttpTransport extends EventEmitter {
227
227
 
228
228
  declare function matchesContext(storeContext: LoggerContext | undefined, loggerContext: string | undefined, match: Record<string, unknown> & {
229
229
  context?: string;
230
- }): boolean;
230
+ }, logMeta?: Record<string, unknown>): boolean;
231
231
 
232
232
  declare class DiscordTransport extends BaseHttpTransport {
233
233
  private config;
@@ -336,6 +336,54 @@ interface GracefulShutdownOptions {
336
336
  */
337
337
  declare function registerShutdown<TContext extends LoggerContext>(logger: Logger<TContext>, options?: GracefulShutdownOptions): () => Promise<void>;
338
338
 
339
+ /**
340
+ * HTTP error data extracted from axios/fetch errors
341
+ */
342
+ interface HttpErrorData {
343
+ /** HTTP status code (e.g., 400, 500) */
344
+ status?: number;
345
+ /** HTTP status text (e.g., "Bad Request") */
346
+ statusText?: string;
347
+ /** Response body data */
348
+ responseData?: unknown;
349
+ /** Request URL */
350
+ url?: string;
351
+ /** HTTP method (GET, POST, etc.) */
352
+ method?: string;
353
+ /** Error code (e.g., ECONNREFUSED, ETIMEDOUT) */
354
+ code?: string;
355
+ }
356
+ /**
357
+ * Serialized error data for logging
358
+ */
359
+ interface SerializedError {
360
+ /** Error message */
361
+ errorMessage: string;
362
+ /** Stack trace */
363
+ stack?: string;
364
+ /** HTTP-specific data if present */
365
+ http?: HttpErrorData;
366
+ /** Error code for non-HTTP errors */
367
+ code?: string;
368
+ /** Error name/type */
369
+ errorName?: string;
370
+ }
371
+ /**
372
+ * Serializes an Error object for logging, extracting HTTP-specific data
373
+ * from axios/fetch errors while preserving standard error properties.
374
+ *
375
+ * @example
376
+ * // Axios error
377
+ * try {
378
+ * await axios.get('/api/data');
379
+ * } catch (error) {
380
+ * const serialized = serializeError(error);
381
+ * // serialized.http.status = 400
382
+ * // serialized.http.responseData = { error: "invalid input" }
383
+ * }
384
+ */
385
+ declare function serializeError(error: unknown): SerializedError;
386
+
339
387
  declare function flattenObject(obj: Record<string, unknown>, prefix?: string, ancestors?: WeakSet<object>, depth?: number): Record<string, unknown>;
340
388
  declare function formatLogfmtValue(value: unknown): string;
341
389
  declare function formatLogfmt(data: Record<string, unknown>): string;
@@ -381,4 +429,4 @@ declare function safeValidateConfig(config: unknown): z.ZodSafeParseResult<{
381
429
  autoShutdown?: boolean | AutoShutdownConfig | undefined;
382
430
  }>;
383
431
 
384
- export { type AutoShutdownConfig, AutoShutdownConfigSchema, BaseHttpTransport, type BaseHttpTransportOptions, type BufferOptions, type BufferedMessage, type CallerConfig, CallerConfigSchema, type CallerInfo, type CloudWatchConfig, CloudWatchConfigSchema, CloudWatchTransport, type ConsoleConfig, ConsoleConfigSchema, type DiscordConfig, DiscordConfigSchema, DiscordTransport, type FileConfig, FileConfigSchema, type GracefulShutdownOptions, type HttpTransportBaseConfig, HttpTransportBaseConfigSchema, LOG_LEVELS, type LevelConfig, type LevelConfigObject, LevelConfigObjectSchema, LevelConfigSchema, type LevelOverride, type LevelOverrideMatch, type LevelRule, LevelRuleSchema, type LogFormat, LogFormatSchema, type LogLevel, LogLevelSchema, type LogStreamName, LogStreamNameSchema, type LogStreamPattern, type LogStreamPatternConfig, LogStreamPatternConfigSchema, LogStreamPatternSchema, type LogStreamTemplateConfig, LogStreamTemplateConfigSchema, Logger, type LoggerConfig, LoggerConfigSchema, type LoggerContext, LoggerStore, type MaskSecretsOptions, MessageBuffer, type Meta, type RequestIdOptions, type SingletonLogger, type TelegramConfig, TelegramConfigSchema, TelegramTransport, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatCallerInfo, formatLogfmt, formatLogfmtValue, generateRequestId, getCallerInfo, getOrGenerateRequestId, isValidLogLevel, maskSecrets, matchesContext, measureAsync, measureSync, registerShutdown, safeValidateConfig, validateConfig };
432
+ export { type AutoShutdownConfig, AutoShutdownConfigSchema, BaseHttpTransport, type BaseHttpTransportOptions, type BufferOptions, type BufferedMessage, type CallerConfig, CallerConfigSchema, type CallerInfo, type CloudWatchConfig, CloudWatchConfigSchema, CloudWatchTransport, type ConsoleConfig, ConsoleConfigSchema, type DiscordConfig, DiscordConfigSchema, DiscordTransport, type FileConfig, FileConfigSchema, type GracefulShutdownOptions, type HttpErrorData, type HttpTransportBaseConfig, HttpTransportBaseConfigSchema, LOG_LEVELS, type LevelConfig, type LevelConfigObject, LevelConfigObjectSchema, LevelConfigSchema, type LevelOverride, type LevelOverrideMatch, type LevelRule, LevelRuleSchema, type LogFormat, LogFormatSchema, type LogLevel, LogLevelSchema, type LogStreamName, LogStreamNameSchema, type LogStreamPattern, type LogStreamPatternConfig, LogStreamPatternConfigSchema, LogStreamPatternSchema, type LogStreamTemplateConfig, LogStreamTemplateConfigSchema, Logger, type LoggerConfig, LoggerConfigSchema, type LoggerContext, LoggerStore, type MaskSecretsOptions, MessageBuffer, type Meta, type RequestIdOptions, type SerializedError, type SingletonLogger, type TelegramConfig, TelegramConfigSchema, TelegramTransport, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatCallerInfo, formatLogfmt, formatLogfmtValue, generateRequestId, getCallerInfo, getOrGenerateRequestId, isValidLogLevel, maskSecrets, matchesContext, measureAsync, measureSync, registerShutdown, safeValidateConfig, serializeError, validateConfig };
package/dist/index.d.ts CHANGED
@@ -227,7 +227,7 @@ declare abstract class BaseHttpTransport extends EventEmitter {
227
227
 
228
228
  declare function matchesContext(storeContext: LoggerContext | undefined, loggerContext: string | undefined, match: Record<string, unknown> & {
229
229
  context?: string;
230
- }): boolean;
230
+ }, logMeta?: Record<string, unknown>): boolean;
231
231
 
232
232
  declare class DiscordTransport extends BaseHttpTransport {
233
233
  private config;
@@ -336,6 +336,54 @@ interface GracefulShutdownOptions {
336
336
  */
337
337
  declare function registerShutdown<TContext extends LoggerContext>(logger: Logger<TContext>, options?: GracefulShutdownOptions): () => Promise<void>;
338
338
 
339
+ /**
340
+ * HTTP error data extracted from axios/fetch errors
341
+ */
342
+ interface HttpErrorData {
343
+ /** HTTP status code (e.g., 400, 500) */
344
+ status?: number;
345
+ /** HTTP status text (e.g., "Bad Request") */
346
+ statusText?: string;
347
+ /** Response body data */
348
+ responseData?: unknown;
349
+ /** Request URL */
350
+ url?: string;
351
+ /** HTTP method (GET, POST, etc.) */
352
+ method?: string;
353
+ /** Error code (e.g., ECONNREFUSED, ETIMEDOUT) */
354
+ code?: string;
355
+ }
356
+ /**
357
+ * Serialized error data for logging
358
+ */
359
+ interface SerializedError {
360
+ /** Error message */
361
+ errorMessage: string;
362
+ /** Stack trace */
363
+ stack?: string;
364
+ /** HTTP-specific data if present */
365
+ http?: HttpErrorData;
366
+ /** Error code for non-HTTP errors */
367
+ code?: string;
368
+ /** Error name/type */
369
+ errorName?: string;
370
+ }
371
+ /**
372
+ * Serializes an Error object for logging, extracting HTTP-specific data
373
+ * from axios/fetch errors while preserving standard error properties.
374
+ *
375
+ * @example
376
+ * // Axios error
377
+ * try {
378
+ * await axios.get('/api/data');
379
+ * } catch (error) {
380
+ * const serialized = serializeError(error);
381
+ * // serialized.http.status = 400
382
+ * // serialized.http.responseData = { error: "invalid input" }
383
+ * }
384
+ */
385
+ declare function serializeError(error: unknown): SerializedError;
386
+
339
387
  declare function flattenObject(obj: Record<string, unknown>, prefix?: string, ancestors?: WeakSet<object>, depth?: number): Record<string, unknown>;
340
388
  declare function formatLogfmtValue(value: unknown): string;
341
389
  declare function formatLogfmt(data: Record<string, unknown>): string;
@@ -381,4 +429,4 @@ declare function safeValidateConfig(config: unknown): z.ZodSafeParseResult<{
381
429
  autoShutdown?: boolean | AutoShutdownConfig | undefined;
382
430
  }>;
383
431
 
384
- export { type AutoShutdownConfig, AutoShutdownConfigSchema, BaseHttpTransport, type BaseHttpTransportOptions, type BufferOptions, type BufferedMessage, type CallerConfig, CallerConfigSchema, type CallerInfo, type CloudWatchConfig, CloudWatchConfigSchema, CloudWatchTransport, type ConsoleConfig, ConsoleConfigSchema, type DiscordConfig, DiscordConfigSchema, DiscordTransport, type FileConfig, FileConfigSchema, type GracefulShutdownOptions, type HttpTransportBaseConfig, HttpTransportBaseConfigSchema, LOG_LEVELS, type LevelConfig, type LevelConfigObject, LevelConfigObjectSchema, LevelConfigSchema, type LevelOverride, type LevelOverrideMatch, type LevelRule, LevelRuleSchema, type LogFormat, LogFormatSchema, type LogLevel, LogLevelSchema, type LogStreamName, LogStreamNameSchema, type LogStreamPattern, type LogStreamPatternConfig, LogStreamPatternConfigSchema, LogStreamPatternSchema, type LogStreamTemplateConfig, LogStreamTemplateConfigSchema, Logger, type LoggerConfig, LoggerConfigSchema, type LoggerContext, LoggerStore, type MaskSecretsOptions, MessageBuffer, type Meta, type RequestIdOptions, type SingletonLogger, type TelegramConfig, TelegramConfigSchema, TelegramTransport, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatCallerInfo, formatLogfmt, formatLogfmtValue, generateRequestId, getCallerInfo, getOrGenerateRequestId, isValidLogLevel, maskSecrets, matchesContext, measureAsync, measureSync, registerShutdown, safeValidateConfig, validateConfig };
432
+ export { type AutoShutdownConfig, AutoShutdownConfigSchema, BaseHttpTransport, type BaseHttpTransportOptions, type BufferOptions, type BufferedMessage, type CallerConfig, CallerConfigSchema, type CallerInfo, type CloudWatchConfig, CloudWatchConfigSchema, CloudWatchTransport, type ConsoleConfig, ConsoleConfigSchema, type DiscordConfig, DiscordConfigSchema, DiscordTransport, type FileConfig, FileConfigSchema, type GracefulShutdownOptions, type HttpErrorData, type HttpTransportBaseConfig, HttpTransportBaseConfigSchema, LOG_LEVELS, type LevelConfig, type LevelConfigObject, LevelConfigObjectSchema, LevelConfigSchema, type LevelOverride, type LevelOverrideMatch, type LevelRule, LevelRuleSchema, type LogFormat, LogFormatSchema, type LogLevel, LogLevelSchema, type LogStreamName, LogStreamNameSchema, type LogStreamPattern, type LogStreamPatternConfig, LogStreamPatternConfigSchema, LogStreamPatternSchema, type LogStreamTemplateConfig, LogStreamTemplateConfigSchema, Logger, type LoggerConfig, LoggerConfigSchema, type LoggerContext, LoggerStore, type MaskSecretsOptions, MessageBuffer, type Meta, type RequestIdOptions, type SerializedError, type SingletonLogger, type TelegramConfig, TelegramConfigSchema, TelegramTransport, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatCallerInfo, formatLogfmt, formatLogfmtValue, generateRequestId, getCallerInfo, getOrGenerateRequestId, isValidLogLevel, maskSecrets, matchesContext, measureAsync, measureSync, registerShutdown, safeValidateConfig, serializeError, validateConfig };
package/dist/index.js CHANGED
@@ -602,7 +602,13 @@ function shouldPassTransport(log, level, rules, store) {
602
602
  const logLevel = getLevelName(log.level);
603
603
  const context = log.context;
604
604
  const storeContext = store.getStore();
605
- const matchingRule = rules?.find((rule) => matchesContext(storeContext, context, rule.match));
605
+ const logMeta = {};
606
+ for (const [key, value] of Object.entries(log)) {
607
+ if (!["level", "time", "msg", "context"].includes(key)) {
608
+ logMeta[key] = value;
609
+ }
610
+ }
611
+ const matchingRule = rules?.find((rule) => matchesContext(storeContext, context, rule.match, logMeta));
606
612
  const effectiveLevel = matchingRule?.level ?? level ?? "silly";
607
613
  if (effectiveLevel === "off") return false;
608
614
  return LOG_LEVELS[logLevel] <= LOG_LEVELS[effectiveLevel];
@@ -899,8 +905,8 @@ function getEffectiveLevel(state, loggerContext) {
899
905
  }
900
906
  return state.defaultLevel;
901
907
  }
902
- function matchesContext(storeContext, loggerContext, match) {
903
- const combined = { ...storeContext, context: loggerContext };
908
+ function matchesContext(storeContext, loggerContext, match, logMeta) {
909
+ const combined = { ...logMeta, ...storeContext, context: loggerContext };
904
910
  return Object.entries(match).every(([key, value]) => combined[key] === value);
905
911
  }
906
912
  var LogLevelSchema = zod.z.enum([
@@ -1147,6 +1153,129 @@ function registerShutdown(logger, options = {}) {
1147
1153
  return shutdown;
1148
1154
  }
1149
1155
 
1156
+ // src/utils/error.ts
1157
+ function isAxiosError(error) {
1158
+ return error !== null && typeof error === "object" && "isAxiosError" in error && error.isAxiosError === true;
1159
+ }
1160
+ function sanitizeResponseData(data, maxStringLength = 1e4) {
1161
+ if (data === null || data === void 0) {
1162
+ return data;
1163
+ }
1164
+ if (typeof data === "string") {
1165
+ return data.length > maxStringLength ? `${data.slice(0, maxStringLength)}...[truncated]` : data;
1166
+ }
1167
+ if (typeof data === "number" || typeof data === "boolean") {
1168
+ return data;
1169
+ }
1170
+ if (Array.isArray(data)) {
1171
+ return data.slice(0, 100).map((item) => sanitizeResponseData(item, maxStringLength));
1172
+ }
1173
+ if (typeof data === "object") {
1174
+ const result = {};
1175
+ const entries = Object.entries(data);
1176
+ for (const [key, value] of entries.slice(0, 50)) {
1177
+ result[key] = sanitizeResponseData(value, maxStringLength);
1178
+ }
1179
+ return result;
1180
+ }
1181
+ return String(data);
1182
+ }
1183
+ function extractAxiosHttpData(error) {
1184
+ const httpData = {};
1185
+ if (error.code) {
1186
+ httpData.code = error.code;
1187
+ }
1188
+ if (error.response) {
1189
+ httpData.status = error.response.status;
1190
+ httpData.statusText = error.response.statusText;
1191
+ if (error.response.data !== void 0) {
1192
+ httpData.responseData = sanitizeResponseData(error.response.data);
1193
+ }
1194
+ }
1195
+ if (error.config) {
1196
+ const { url, baseURL, method } = error.config;
1197
+ if (url) {
1198
+ httpData.url = baseURL && !url.startsWith("http") ? `${baseURL}${url}` : url;
1199
+ }
1200
+ if (method) {
1201
+ httpData.method = method.toUpperCase();
1202
+ }
1203
+ }
1204
+ return httpData;
1205
+ }
1206
+ function extractGenericHttpData(error) {
1207
+ const httpData = {};
1208
+ let hasData = false;
1209
+ if (typeof error.code === "string") {
1210
+ httpData.code = error.code;
1211
+ hasData = true;
1212
+ }
1213
+ const response = error.response;
1214
+ if (response && typeof response === "object") {
1215
+ if (typeof response.status === "number") {
1216
+ httpData.status = response.status;
1217
+ hasData = true;
1218
+ }
1219
+ if (typeof response.statusText === "string") {
1220
+ httpData.statusText = response.statusText;
1221
+ hasData = true;
1222
+ }
1223
+ if (response.data !== void 0) {
1224
+ httpData.responseData = sanitizeResponseData(response.data);
1225
+ hasData = true;
1226
+ }
1227
+ }
1228
+ const config = error.config;
1229
+ if (config && typeof config === "object") {
1230
+ const url = config.url;
1231
+ const baseURL = config.baseURL;
1232
+ if (typeof url === "string") {
1233
+ httpData.url = baseURL && !url.startsWith("http") ? `${baseURL}${url}` : url;
1234
+ hasData = true;
1235
+ }
1236
+ if (typeof config.method === "string") {
1237
+ httpData.method = config.method.toUpperCase();
1238
+ hasData = true;
1239
+ }
1240
+ }
1241
+ return hasData ? httpData : void 0;
1242
+ }
1243
+ function serializeError(error) {
1244
+ if (!(error instanceof Error)) {
1245
+ if (error === null || error === void 0) {
1246
+ return { errorMessage: "Unknown error" };
1247
+ }
1248
+ if (typeof error === "string") {
1249
+ return { errorMessage: error };
1250
+ }
1251
+ const httpData2 = typeof error === "object" ? extractGenericHttpData(error) : void 0;
1252
+ return {
1253
+ errorMessage: String(error),
1254
+ http: httpData2
1255
+ };
1256
+ }
1257
+ const serialized = {
1258
+ errorMessage: error.message,
1259
+ stack: error.stack
1260
+ };
1261
+ if (error.name && error.name !== "Error") {
1262
+ serialized.errorName = error.name;
1263
+ }
1264
+ if (isAxiosError(error)) {
1265
+ serialized.http = extractAxiosHttpData(error);
1266
+ return serialized;
1267
+ }
1268
+ const errWithCode = error;
1269
+ if (typeof errWithCode.code === "string") {
1270
+ serialized.code = errWithCode.code;
1271
+ }
1272
+ const httpData = extractGenericHttpData(error);
1273
+ if (httpData) {
1274
+ serialized.http = httpData;
1275
+ }
1276
+ return serialized;
1277
+ }
1278
+
1150
1279
  // src/logger.ts
1151
1280
  var Logger = class _Logger {
1152
1281
  constructor(state, context) {
@@ -1275,11 +1404,19 @@ var Logger = class _Logger {
1275
1404
  logMeta.caller = formatCallerInfo(callerInfo);
1276
1405
  }
1277
1406
  }
1278
- if (error instanceof Error) {
1279
- logMeta.errorMessage = error.message;
1280
- logMeta.stack = error.stack;
1281
- } else if (error !== void 0) {
1282
- logMeta.error = error;
1407
+ if (error !== void 0) {
1408
+ const serialized = serializeError(error);
1409
+ logMeta.errorMessage = serialized.errorMessage;
1410
+ logMeta.stack = serialized.stack;
1411
+ if (serialized.errorName) {
1412
+ logMeta.errorName = serialized.errorName;
1413
+ }
1414
+ if (serialized.code) {
1415
+ logMeta.errorCode = serialized.code;
1416
+ }
1417
+ if (serialized.http) {
1418
+ logMeta.http = serialized.http;
1419
+ }
1283
1420
  }
1284
1421
  const pinoMethod = this.getPinoMethod(level);
1285
1422
  pinoMethod.call(this.state.pino, logMeta, message);
@@ -1573,6 +1710,7 @@ exports.measureAsync = measureAsync;
1573
1710
  exports.measureSync = measureSync;
1574
1711
  exports.registerShutdown = registerShutdown;
1575
1712
  exports.safeValidateConfig = safeValidateConfig;
1713
+ exports.serializeError = serializeError;
1576
1714
  exports.validateConfig = validateConfig;
1577
1715
  //# sourceMappingURL=index.js.map
1578
1716
  //# sourceMappingURL=index.js.map