@rf-logger/logger 0.2.0 → 0.3.0

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.
@@ -1,11 +1,30 @@
1
1
  import { Logform } from "winston";
2
- import { Options } from "../types";
3
- /**
4
- * This format accepts:
5
- * - errors in the log message --> src.error(new Error("test"))
6
- * - errors in the second argument --> src.error("Something bad happened", new Error("test"))
7
- * - errors in the log context --> src.error("Something bad happened", { err })
8
- * The error message will be added to the log (either in the context, or in the message depending on the situation).
9
- * The exception be sent to Sentry where the Stacktrace will accessible thanks to its sourcemap.
10
- */
11
- export declare const errorFormat: (options: Options) => Logform.Format;
2
+ import { ErrorForwarder, ErrorMetaGenerator, Options } from "../types";
3
+ type ErrorLog = {
4
+ id: string;
5
+ parentId?: string;
6
+ message: string;
7
+ stack?: string;
8
+ };
9
+ export declare class ErrorFormat {
10
+ protected readonly format: Logform.Format;
11
+ protected readonly errorMetaGenerators: ErrorMetaGenerator[];
12
+ protected readonly errorForwarders: ErrorForwarder[];
13
+ /**
14
+ * This format accepts:
15
+ * - errors in the log message --> src.error(new Error("test"))
16
+ * - errors in the second argument --> src.error("Something bad happened", new Error("test"))
17
+ * - errors in the log context --> src.error("Something bad happened", { err })
18
+ * The error message will be added to the log (either in the context, or in the message depending on the situation).
19
+ * The exception be sent to Sentry where the Stacktrace will accessible thanks to its sourcemap.
20
+ */
21
+ constructor(options: Options);
22
+ getFormat(): Logform.Format;
23
+ protected errorToMessage(error: Error): string;
24
+ protected forwardError(error: Error, errorId: string, info: Logform.TransformableInfo): void;
25
+ protected formatError(error: Error): ErrorLog;
26
+ protected handleCauses(error: Error, errorId: string, causes?: ErrorLog[]): ErrorLog[];
27
+ protected formatMessageWithError(message: string, error: Error, info: Logform.TransformableInfo): Logform.TransformableInfo;
28
+ protected generateWinstonFormat(): Logform.Format;
29
+ }
30
+ export {};
@@ -1,68 +1,97 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.errorFormat = void 0;
3
+ exports.ErrorFormat = void 0;
4
4
  const triple_beam_1 = require("triple-beam");
5
5
  const uuid_1 = require("uuid");
6
6
  const winston_1 = require("winston");
7
- function generateTraceId(error) {
8
- error.traceId = (0, uuid_1.v4)();
9
- }
10
- /**
11
- * This format accepts:
12
- * - errors in the log message --> src.error(new Error("test"))
13
- * - errors in the second argument --> src.error("Something bad happened", new Error("test"))
14
- * - errors in the log context --> src.error("Something bad happened", { err })
15
- * The error message will be added to the log (either in the context, or in the message depending on the situation).
16
- * The exception be sent to Sentry where the Stacktrace will accessible thanks to its sourcemap.
17
- */
18
- const errorFormat = (options) => {
19
- var _a;
20
- const errorMetaGenerators = [];
21
- const errorForwarders = [];
22
- (_a = options.plugins) === null || _a === void 0 ? void 0 : _a.forEach((plugin) => {
23
- plugin.registerErrorMetaGenerators &&
24
- errorMetaGenerators.push(...plugin.registerErrorMetaGenerators());
25
- plugin.registerErrorForwarders &&
26
- errorForwarders.push(...plugin.registerErrorForwarders());
27
- });
28
- function forwardError(error, info) {
29
- generateTraceId(error);
30
- const meta = errorMetaGenerators.reduce((previousMeta, metaGenerator) => (Object.assign(Object.assign({}, previousMeta), metaGenerator(error))), {});
31
- errorForwarders.forEach((forward) => forward(error, info, meta));
7
+ class ErrorFormat {
8
+ format;
9
+ errorMetaGenerators = [];
10
+ errorForwarders = [];
11
+ /**
12
+ * This format accepts:
13
+ * - errors in the log message --> src.error(new Error("test"))
14
+ * - errors in the second argument --> src.error("Something bad happened", new Error("test"))
15
+ * - errors in the log context --> src.error("Something bad happened", { err })
16
+ * The error message will be added to the log (either in the context, or in the message depending on the situation).
17
+ * The exception be sent to Sentry where the Stacktrace will accessible thanks to its sourcemap.
18
+ */
19
+ constructor(options) {
20
+ options.plugins?.forEach((plugin) => {
21
+ plugin.registerErrorMetaGenerators &&
22
+ this.errorMetaGenerators.push(...plugin.registerErrorMetaGenerators());
23
+ plugin.registerErrorForwarders &&
24
+ this.errorForwarders.push(...plugin.registerErrorForwarders());
25
+ });
26
+ this.format = this.generateWinstonFormat();
27
+ }
28
+ getFormat() {
29
+ return this.format;
30
+ }
31
+ errorToMessage(error) {
32
+ return `${error.name}: ${error.message}`;
32
33
  }
33
- return (0, winston_1.format)((info) => {
34
- if (info instanceof Error) {
35
- forwardError(info, info);
36
- const message = `${info.name}: ${info.message}`;
37
- return Object.assign(Object.assign({}, info), { level: info.level, [triple_beam_1.LEVEL]: info.level, message, [triple_beam_1.MESSAGE]: message, stack: errorForwarders.length ? undefined : info.stack });
34
+ forwardError(error, errorId, info) {
35
+ const meta = this.errorMetaGenerators.reduce((previousMeta, metaGenerator) => ({
36
+ ...previousMeta,
37
+ ...metaGenerator(error),
38
+ }), {});
39
+ this.errorForwarders.forEach((forward) => forward(error, errorId, info, meta));
40
+ }
41
+ formatError(error) {
42
+ const errorId = (0, uuid_1.v4)();
43
+ return {
44
+ id: errorId,
45
+ message: this.errorToMessage(error),
46
+ stack: this.errorForwarders.length ? undefined : error.stack,
47
+ };
48
+ }
49
+ handleCauses(error, errorId, causes = []) {
50
+ if (error.cause && error.cause instanceof Error && causes.length < 10) {
51
+ const causeInfo = this.formatError(error.cause);
52
+ causeInfo.parentId = errorId;
53
+ causes.push(causeInfo);
54
+ return this.handleCauses(error.cause, causeInfo.id, causes);
38
55
  }
39
- // case where the error is passed down the log context
40
- let lastTraceId = null;
41
- ["error", "err", "e"].forEach((prop) => {
42
- const value = info[prop];
43
- if (!(info[prop] instanceof Error))
44
- return;
45
- forwardError(value, info);
46
- lastTraceId = value.traceId;
47
- info[prop] = Object.assign(Object.assign({}, value), { message: `${value.name}: ${value.message}`, stack: errorForwarders.length ? undefined : info[prop].stack });
48
- });
49
- if (lastTraceId) {
50
- info.traceId = lastTraceId;
56
+ return causes;
57
+ }
58
+ formatMessageWithError(message, error, info) {
59
+ const errorInfo = this.formatError(error);
60
+ this.forwardError(error, errorInfo.id, info);
61
+ const causes = this.handleCauses(error, errorInfo.id);
62
+ return {
63
+ ...info,
64
+ level: info.level,
65
+ [triple_beam_1.LEVEL]: info.level,
66
+ message,
67
+ [triple_beam_1.MESSAGE]: message,
68
+ e: undefined,
69
+ err: undefined,
70
+ error: {
71
+ ...errorInfo,
72
+ causes: causes.length ? causes : undefined,
73
+ },
74
+ };
75
+ }
76
+ generateWinstonFormat() {
77
+ return (0, winston_1.format)((info) => {
78
+ if (info instanceof Error) {
79
+ return this.formatMessageWithError(this.errorToMessage(info), info, info);
80
+ }
81
+ // case where the error is passed down the log context
82
+ const errorFromContext = info.error || info.err || info.e;
83
+ if (errorFromContext instanceof Error) {
84
+ return this.formatMessageWithError(info.message, errorFromContext, info);
85
+ }
86
+ // case where the error is passed down as second argument
87
+ if (info[triple_beam_1.SPLAT]) {
88
+ const errorFromSplat = info[triple_beam_1.SPLAT]?.find((key) => key instanceof Error);
89
+ if (errorFromSplat) {
90
+ return this.formatMessageWithError(info.message, errorFromSplat, info);
91
+ }
92
+ }
51
93
  return info;
52
- }
53
- // case where the error is passed down as second argument
54
- if (info[triple_beam_1.SPLAT]) {
55
- info[triple_beam_1.SPLAT].forEach((error) => {
56
- if (!(error instanceof Error))
57
- return;
58
- forwardError(error, info);
59
- lastTraceId = error.traceId;
60
- });
61
- if (!lastTraceId)
62
- return info;
63
- return Object.assign(Object.assign({}, info), { traceId: lastTraceId, stack: errorForwarders.length ? undefined : info.stack });
64
- }
65
- return info;
66
- })();
67
- };
68
- exports.errorFormat = errorFormat;
94
+ })();
95
+ }
96
+ }
97
+ exports.ErrorFormat = ErrorFormat;
@@ -1,3 +1,3 @@
1
- export { errorFormat } from "./error.format";
1
+ export { ErrorFormat } from "./error.format";
2
2
  export { gcpFormat } from "./gcp.format";
3
3
  export { simpleFormatWithTimestamp } from "./simple.format";
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.simpleFormatWithTimestamp = exports.gcpFormat = exports.errorFormat = void 0;
3
+ exports.simpleFormatWithTimestamp = exports.gcpFormat = exports.ErrorFormat = void 0;
4
4
  var error_format_1 = require("./error.format");
5
- Object.defineProperty(exports, "errorFormat", { enumerable: true, get: function () { return error_format_1.errorFormat; } });
5
+ Object.defineProperty(exports, "ErrorFormat", { enumerable: true, get: function () { return error_format_1.ErrorFormat; } });
6
6
  var gcp_format_1 = require("./gcp.format");
7
7
  Object.defineProperty(exports, "gcpFormat", { enumerable: true, get: function () { return gcp_format_1.gcpFormat; } });
8
8
  var simple_format_1 = require("./simple.format");
@@ -1,15 +1,4 @@
1
1
  "use strict";
2
- var __rest = (this && this.__rest) || function (s, e) {
3
- var t = {};
4
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
- t[p] = s[p];
6
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
- t[p[i]] = s[p[i]];
10
- }
11
- return t;
12
- };
13
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
14
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
15
4
  };
@@ -29,7 +18,7 @@ const shift = (string, spaces = 2) => string
29
18
  * see https://github.com/winstonjs/logform/blob/master/simple.js
30
19
  */
31
20
  exports.simpleFormatWithTimestamp = winston_1.default.format.printf((info) => {
32
- const { level, message, timestamp, stack, channel, nestContext } = info, rest = __rest(info, ["level", "message", "timestamp", "stack", "channel", "nestContext"]);
21
+ const { level, message, timestamp, stack, channel, nestContext, ...rest } = info;
33
22
  const context = (0, safe_stable_stringify_1.default)(rest, null, 2);
34
23
  let log = `[${timestamp}] ${level}:`;
35
24
  if (info.padding)
package/dist/logger.js CHANGED
@@ -14,28 +14,24 @@ const defaultOptions = {
14
14
  handleWarnings: true,
15
15
  };
16
16
  class Logger {
17
+ options;
17
18
  constructor(inputOptions) {
18
- this.init = () => {
19
- const logger = this.createLogger();
20
- // displays stacktrace for warnings
21
- if (this.options.handleWarnings) {
22
- process.on("warning", (err) => logger.warn(err));
23
- }
24
- return logger;
19
+ this.options = {
20
+ ...defaultOptions,
21
+ ...inputOptions,
25
22
  };
26
- this.options = Object.assign(Object.assign({}, defaultOptions), inputOptions);
27
23
  }
28
24
  createLogger() {
29
- var _a, _b, _c;
30
25
  // register formats
31
- const formats = [(0, formats_1.errorFormat)(this.options)];
32
- (_a = this.options.plugins) === null || _a === void 0 ? void 0 : _a.forEach((plugin) => {
26
+ const errorFormat = new formats_1.ErrorFormat(this.options);
27
+ const formats = [errorFormat.getFormat()];
28
+ this.options.plugins?.forEach((plugin) => {
33
29
  plugin.registerFormats && formats.push(...plugin.registerFormats());
34
30
  });
35
31
  const baseFormat = winston_1.format.combine(...formats);
36
32
  // register exit handlers
37
33
  let exitHandlers = [];
38
- (_b = this.options.plugins) === null || _b === void 0 ? void 0 : _b.forEach((plugin) => {
34
+ this.options.plugins?.forEach((plugin) => {
39
35
  if (!plugin.registerExitHandlers)
40
36
  return;
41
37
  exitHandlers = plugin.registerExitHandlers();
@@ -67,10 +63,18 @@ class Logger {
67
63
  logger.on("finish", exitHandler);
68
64
  }
69
65
  // register interceptors
70
- (_c = this.options.plugins) === null || _c === void 0 ? void 0 : _c.forEach((plugin) => {
66
+ this.options.plugins?.forEach((plugin) => {
71
67
  plugin.registerInterceptors && plugin.registerInterceptors(logger);
72
68
  });
73
69
  return logger;
74
70
  }
71
+ init = () => {
72
+ const logger = this.createLogger();
73
+ // displays stacktrace for warnings
74
+ if (this.options.handleWarnings) {
75
+ process.on("warning", (err) => logger.warn(err));
76
+ }
77
+ return logger;
78
+ };
75
79
  }
76
80
  exports.Logger = Logger;
@@ -11,10 +11,7 @@ const winston_1 = require("winston");
11
11
  * https://github.com/winstonjs/winston/blob/91ec06961d2cc9a522f65c023cd02871aa6d97b2/lib/winston/exception-handler.js#L225C10-L225C11
12
12
  */
13
13
  class CustomConsoleTransport extends winston_1.transports.Console {
14
- constructor() {
15
- super(...arguments);
16
- this._ending = false;
17
- }
14
+ _ending = false;
18
15
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
16
  log(info, next) {
20
17
  // @ts-expect-error The log function is defined for the Console transport
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import { Writable } from "stream";
3
2
  import { transports } from "winston";
4
3
  import { ExitHandler } from "../types";
@@ -8,11 +8,12 @@ const winston_1 = require("winston");
8
8
  * to wait for exit handlers to be processed before emitting a finish event.
9
9
  */
10
10
  class ExceptionHandlerTransport extends winston_1.transports.Stream {
11
+ exitHandlers;
12
+ _ending = false;
13
+ _stream = new stream_1.Writable();
11
14
  constructor(exitHandlers, options) {
12
- super(Object.assign(Object.assign({}, options), { stream: new stream_1.Writable() }));
15
+ super({ ...options, stream: new stream_1.Writable() });
13
16
  this.exitHandlers = exitHandlers;
14
- this._ending = false;
15
- this._stream = new stream_1.Writable();
16
17
  this._stream._write = (chunk, encoding, callback) => {
17
18
  this.finishIfEnding();
18
19
  callback();
package/dist/types.d.ts CHANGED
@@ -11,13 +11,10 @@ export type Options = {
11
11
  plugins?: LoggerPlugin[];
12
12
  transports?: transport[];
13
13
  };
14
- export type ErrorLog = Error & {
15
- traceId: string;
16
- };
17
14
  export type ErrorMetaDeep = Record<string, string>;
18
15
  export type ErrorMeta = Record<string, string | ErrorMetaDeep>;
19
- export type ErrorMetaGenerator = (error: ErrorLog) => ErrorMeta;
20
- export type ErrorForwarder = (error: ErrorLog, info: Logform.TransformableInfo, meta: ErrorMeta) => void;
16
+ export type ErrorMetaGenerator = (error: Error) => ErrorMeta;
17
+ export type ErrorForwarder = (error: Error, errorId: string, info: Logform.TransformableInfo, meta: ErrorMeta) => void;
21
18
  export type ExitHandler = () => Promise<void>;
22
19
  export type LoggerPlugin = {
23
20
  registerFormats?: () => Logform.Format[];
package/package.json CHANGED
@@ -21,7 +21,7 @@
21
21
  "engines": {
22
22
  "node": ">=16.0.0"
23
23
  },
24
- "version": "0.2.0",
24
+ "version": "0.3.0",
25
25
  "scripts": {
26
26
  "test": "jest",
27
27
  "version": "pnpm version --no-git-tag-version"