@autofleet/logger 3.0.0 → 4.0.0-beta-2

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.
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const index_1 = __importDefault(require("./index"));
7
+ const logger = (0, index_1.default)('info');
8
+ logger.info('it is working');
9
+ logger.error('errors displayed in logs/error.log', new Error('test error'));
10
+ logger.debug('debug with object', { a: 5 });
11
+ const loggerMiddleware = () => ({ middleware: Math.random() });
12
+ logger.addContextMiddleware(loggerMiddleware);
13
+ logger.info('middleware added', { a: 5 });
14
+ logger.error('middleware added', new Error('test error'));
package/dist/index.js ADDED
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LogLevel = void 0;
7
+ const pino_1 = __importDefault(require("pino"));
8
+ const pino_cloud_logging_1 = require("pino-cloud-logging");
9
+ const getLevel = (logLevel) => {
10
+ if (logLevel)
11
+ return logLevel;
12
+ if (process.env.LOG_LEVEL)
13
+ return process.env.LOG_LEVEL;
14
+ if (process.env.NODE_ENV && ['production', 'staging', 'test'].includes(process.env.NODE_ENV))
15
+ return 'info';
16
+ if (process.env.NODE_ENV === 'development')
17
+ return 'debug';
18
+ return 'debug';
19
+ };
20
+ const createLoggerInstance = (level, options) => {
21
+ let loggerInstance;
22
+ if (process.env.NODE_ENV === 'production') {
23
+ loggerInstance = (0, pino_1.default)((0, pino_cloud_logging_1.gcpLogOptions)(Object.assign({ level: process.env.PINO_LOG_LEVEL || 'info' }, options)));
24
+ }
25
+ else {
26
+ loggerInstance = (0, pino_1.default)(Object.assign({ level: process.env.PINO_LOG_LEVEL || 'info', transport: {
27
+ target: 'pino-pretty',
28
+ options: {
29
+ colorize: true,
30
+ },
31
+ } }, options));
32
+ }
33
+ loggerInstance.level = level;
34
+ return loggerInstance;
35
+ };
36
+ // eslint-disable-next-line no-shadow
37
+ var LogLevel;
38
+ (function (LogLevel) {
39
+ LogLevel["trace"] = "trace";
40
+ LogLevel["debug"] = "debug";
41
+ LogLevel["info"] = "info";
42
+ LogLevel["warn"] = "warn";
43
+ LogLevel["error"] = "error";
44
+ LogLevel["fatal"] = "fatal";
45
+ })(LogLevel || (exports.LogLevel = LogLevel = {}));
46
+ class LoggerInstanceManager {
47
+ constructor(logLevel) {
48
+ this.contextMiddlewares = [];
49
+ this.logger = createLoggerInstance(getLevel(logLevel), {
50
+ mixin: () => this.addMetadata(),
51
+ });
52
+ }
53
+ // To support winston like logging in pino
54
+ winstonLikeLoggerCall(logLevel, message, meta) {
55
+ if (meta) {
56
+ this.logger[logLevel](meta, message);
57
+ }
58
+ else {
59
+ this.logger[logLevel](message);
60
+ }
61
+ }
62
+ addMetadata() {
63
+ const newMetadata = {};
64
+ this.contextMiddlewares.forEach((middleware) => {
65
+ const metadata = middleware();
66
+ Object.assign(newMetadata, metadata);
67
+ });
68
+ return newMetadata;
69
+ }
70
+ addContextMiddleware(middleware) {
71
+ this.contextMiddlewares.push(middleware);
72
+ }
73
+ trace(message, meta) {
74
+ this.winstonLikeLoggerCall(LogLevel.trace, message, meta);
75
+ }
76
+ debug(message, meta) {
77
+ this.winstonLikeLoggerCall(LogLevel.debug, message, meta);
78
+ }
79
+ info(message, meta) {
80
+ this.winstonLikeLoggerCall(LogLevel.info, message, meta);
81
+ }
82
+ warn(message, meta) {
83
+ this.winstonLikeLoggerCall(LogLevel.warn, message, meta);
84
+ }
85
+ error(message, meta) {
86
+ this.winstonLikeLoggerCall(LogLevel.error, message, meta);
87
+ }
88
+ fatal(message, meta) {
89
+ this.winstonLikeLoggerCall(LogLevel.fatal, message, meta);
90
+ }
91
+ child(metadata) {
92
+ return this.logger.child(metadata);
93
+ }
94
+ get level() {
95
+ return this.logger.level;
96
+ }
97
+ }
98
+ exports.default = (loglevel) => new LoggerInstanceManager(loglevel);
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const index_1 = __importDefault(require("./index"));
7
+ const { env } = process;
8
+ describe('Logger', () => {
9
+ it('it`s default level is info', () => {
10
+ env.NODE_ENV = '';
11
+ const logger = (0, index_1.default)();
12
+ expect(logger).toBeDefined();
13
+ expect(logger.level).toBe('debug');
14
+ logger.info('test');
15
+ });
16
+ it('its default develpment level is debug', () => {
17
+ env.NODE_ENV = 'development';
18
+ const logger = (0, index_1.default)();
19
+ expect(logger.level).toBe('debug');
20
+ });
21
+ it('its default test level is info', () => {
22
+ env.NODE_ENV = 'test';
23
+ const logger = (0, index_1.default)();
24
+ expect(logger.level).toBe('info');
25
+ });
26
+ it('its default production level is info', () => {
27
+ env.NODE_ENV = 'production';
28
+ const logger = (0, index_1.default)();
29
+ expect(logger.level).toBe('info');
30
+ });
31
+ it('its level can be override by LOG_LEVEL env variable', () => {
32
+ env.NODE_ENV = 'development';
33
+ env.LOG_LEVEL = 'warn';
34
+ const logger = (0, index_1.default)();
35
+ expect(logger.level).toBe('warn');
36
+ });
37
+ it('its level can be override by function variable', () => {
38
+ env.NODE_ENV = 'production';
39
+ env.LOG_LEVEL = 'warn';
40
+ const logger = (0, index_1.default)('info');
41
+ expect(logger.level).toBe('info');
42
+ });
43
+ it('its has functions for each level', () => {
44
+ const logger = (0, index_1.default)();
45
+ expect(typeof logger.error).toBe('function');
46
+ expect(typeof logger.warn).toBe('function');
47
+ expect(typeof logger.info).toBe('function');
48
+ expect(typeof logger.debug).toBe('function');
49
+ });
50
+ });
package/example.ts ADDED
@@ -0,0 +1,13 @@
1
+ import Logger from './index';
2
+
3
+ const logger = Logger('info');
4
+
5
+ logger.info('it is working');
6
+ logger.error('errors displayed in logs/error.log', new Error('test error'));
7
+ logger.debug('debug with object', { a: 5 });
8
+
9
+ const loggerMiddleware = () => ({ middleware: Math.random() });
10
+ logger.addContextMiddleware(loggerMiddleware);
11
+
12
+ logger.info('middleware added', { a: 5 });
13
+ logger.error('middleware added', new Error('test error'));
@@ -1,4 +1,4 @@
1
- const Logger = require('./index');
1
+ import Logger from './index';
2
2
 
3
3
  const { env } = process;
4
4
 
@@ -39,17 +39,15 @@ describe('Logger', () => {
39
39
  it('its level can be override by function variable', () => {
40
40
  env.NODE_ENV = 'production';
41
41
  env.LOG_LEVEL = 'warn';
42
- const logger = Logger('silly');
43
- expect(logger.level).toBe('silly');
42
+ const logger = Logger('info');
43
+ expect(logger.level).toBe('info');
44
44
  });
45
45
 
46
46
  it('its has functions for each level', () => {
47
47
  const logger = Logger();
48
- expect(logger.error).toBeFunction();
49
- expect(logger.warn).toBeFunction();
50
- expect(logger.info).toBeFunction();
51
- expect(logger.verbose).toBeFunction();
52
- expect(logger.debug).toBeFunction();
53
- expect(logger.silly).toBeFunction();
48
+ expect(typeof logger.error).toBe('function');
49
+ expect(typeof logger.warn).toBe('function');
50
+ expect(typeof logger.info).toBe('function');
51
+ expect(typeof logger.debug).toBe('function');
54
52
  });
55
53
  });
package/index.ts ADDED
@@ -0,0 +1,113 @@
1
+ import Pino from 'pino';
2
+ import { gcpLogOptions } from 'pino-cloud-logging';
3
+
4
+ const getLevel = (logLevel: string | undefined) => {
5
+ if (logLevel) return logLevel;
6
+ if (process.env.LOG_LEVEL) return process.env.LOG_LEVEL;
7
+ if (process.env.NODE_ENV && ['production', 'staging', 'test'].includes(process.env.NODE_ENV)) return 'info';
8
+ if (process.env.NODE_ENV === 'development') return 'debug';
9
+ return 'debug';
10
+ };
11
+
12
+ const createLoggerInstance = (level: string, options: object) => {
13
+ let loggerInstance;
14
+ if (process.env.NODE_ENV === 'production') {
15
+ loggerInstance = Pino(gcpLogOptions({
16
+ level: process.env.PINO_LOG_LEVEL || 'info',
17
+ ...options,
18
+ }));
19
+ } else {
20
+ loggerInstance = Pino({
21
+ level: process.env.PINO_LOG_LEVEL || 'info',
22
+ transport: {
23
+ target: 'pino-pretty',
24
+ options: {
25
+ colorize: true,
26
+ },
27
+ },
28
+ ...options,
29
+ });
30
+ }
31
+ loggerInstance.level = level;
32
+ return loggerInstance;
33
+ };
34
+
35
+ // eslint-disable-next-line no-shadow
36
+ export enum LogLevel {
37
+ trace = 'trace',
38
+ debug = 'debug',
39
+ info = 'info',
40
+ warn = 'warn',
41
+ error = 'error',
42
+ fatal = 'fatal',
43
+ }
44
+
45
+ type MiddlewareFunction = () => Record<string, unknown>;
46
+
47
+ class LoggerInstanceManager {
48
+ contextMiddlewares: MiddlewareFunction[];
49
+
50
+ logger: Pino.Logger;
51
+
52
+ constructor(logLevel?: string) {
53
+ this.contextMiddlewares = [];
54
+ this.logger = createLoggerInstance(getLevel(logLevel), {
55
+ mixin: () => this.addMetadata(),
56
+ });
57
+ }
58
+
59
+ // To support winston like logging in pino
60
+ winstonLikeLoggerCall(logLevel: LogLevel, message: string, meta: unknown) {
61
+ if (meta) {
62
+ this.logger[logLevel](meta, message);
63
+ } else {
64
+ this.logger[logLevel](message);
65
+ }
66
+ }
67
+
68
+ addMetadata(): Record<string, unknown> {
69
+ const newMetadata = {};
70
+ this.contextMiddlewares.forEach((middleware) => {
71
+ const metadata = middleware();
72
+ Object.assign(newMetadata, metadata);
73
+ });
74
+ return newMetadata;
75
+ }
76
+
77
+ addContextMiddleware(middleware: MiddlewareFunction) {
78
+ this.contextMiddlewares.push(middleware);
79
+ }
80
+
81
+ trace(message: string, meta?: unknown) {
82
+ this.winstonLikeLoggerCall(LogLevel.trace, message, meta);
83
+ }
84
+
85
+ debug(message: string, meta?: unknown) {
86
+ this.winstonLikeLoggerCall(LogLevel.debug, message, meta);
87
+ }
88
+
89
+ info(message: string, meta?: unknown) {
90
+ this.winstonLikeLoggerCall(LogLevel.info, message, meta);
91
+ }
92
+
93
+ warn(message: string, meta?: unknown) {
94
+ this.winstonLikeLoggerCall(LogLevel.warn, message, meta);
95
+ }
96
+
97
+ error(message: string, meta?: unknown) {
98
+ this.winstonLikeLoggerCall(LogLevel.error, message, meta);
99
+ }
100
+
101
+ fatal(message: string, meta?: unknown) {
102
+ this.winstonLikeLoggerCall(LogLevel.fatal, message, meta);
103
+ }
104
+
105
+ child(metadata: Record<string, unknown>) {
106
+ return this.logger.child(metadata);
107
+ }
108
+
109
+ get level() {
110
+ return this.logger.level;
111
+ }
112
+ }
113
+ export default (loglevel?: string) => new LoggerInstanceManager(loglevel);
package/package.json CHANGED
@@ -1,16 +1,20 @@
1
1
  {
2
2
  "name": "@autofleet/logger",
3
- "version": "3.0.0",
3
+ "version": "4.0.0-beta-2",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "coverage": "jest --coverage --forceExit --runInBand",
7
7
  "test": "jest --runInBand",
8
8
  "test-auto": "jest --watch --runInBand",
9
- "linter": "./node_modules/.bin/eslint ."
9
+ "linter": "./node_modules/.bin/eslint .",
10
+ "build": "tsc",
11
+ "prepublishOnly": "npm run build",
12
+ "example": "ts-node example.ts"
10
13
  },
11
14
  "jest": {
12
15
  "setupTestFrameworkScriptFile": "jest-extended",
13
- "testURL": "http://localhost:8085/"
16
+ "testURL": "http://localhost:8085/",
17
+ "preset": "ts-jest"
14
18
  },
15
19
  "repository": {
16
20
  "type": "git",
@@ -25,15 +29,25 @@
25
29
  "dependencies": {
26
30
  "@google-cloud/logging-winston": "^6.0.0",
27
31
  "dotenv": "^5.0.1",
28
- "jest": "^22.4.4",
29
32
  "object-sizeof": "^1.6.1",
33
+ "pino": "^9.2.0",
34
+ "pino-cloud-logging": "^1.0.6",
35
+ "pino-pretty": "^11.2.1",
30
36
  "winston": "^3.11.0"
31
37
  },
32
38
  "devDependencies": {
33
- "eslint": "^4.19.1",
34
- "eslint-config-airbnb": "^16.1.0",
35
- "eslint-plugin-import": "^2.11.0",
39
+ "@types/jest": "^29.5.12",
40
+ "@types/node": "^20.14.7",
41
+ "@typescript-eslint/eslint-plugin": "^6.21.0",
42
+ "@typescript-eslint/parser": "^6.21.0",
43
+ "eslint": "^7.32.0",
44
+ "eslint-config-airbnb": "^19.0.4",
45
+ "eslint-plugin-import": "^2.29.1",
46
+ "jest": "^29.7.0",
36
47
  "jest-extended": "^0.7.1",
37
- "nock": "^10.0.2"
48
+ "nock": "^10.0.2",
49
+ "ts-jest": "^29.1.5",
50
+ "ts-node": "^10.9.2",
51
+ "typescript": "^5.3.2"
38
52
  }
39
53
  }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
4
+ "module": "commonjs", /* Specify what module code is generated. */ /* Allow 'import x from y' when a module doesn't have a default export. */
5
+ "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
6
+ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
7
+ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
8
+
9
+ /* Type Checking */
10
+ "strict": true, /* Enable all strict type-checking options. */
11
+ "outDir": "./dist"
12
+ }
13
+ }
package/example.js DELETED
@@ -1,5 +0,0 @@
1
- const logger = require('./index')();
2
-
3
- logger.info('it is working');
4
- logger.error('errors displayed in logs/error.log', { e: new Error('test error') });
5
- logger.debug('debug with object', { a: 5 });
package/index.d.ts DELETED
@@ -1,7 +0,0 @@
1
- import { Logger } from 'winston';
2
-
3
- declare const logger: Logger;
4
-
5
- declare const _exported: (_logLevel: any) => Logger
6
-
7
- export default _exported;
package/index.js DELETED
@@ -1,143 +0,0 @@
1
- const winston = require('winston');
2
- const sizeof = require('object-sizeof');
3
-
4
- const { createLogger } = winston;
5
- require('dotenv').config();
6
-
7
- const { env } = process;
8
-
9
- const isProd = env.NODE_ENV === 'production';
10
-
11
- const infoEnvNmaes = [
12
- 'production',
13
- 'staging',
14
- 'test',
15
- ];
16
-
17
- const serializeError = (error) => {
18
- const fields = ['code', 'status', 'statusCode', 'message', 'messageData', 'name', 'stack', 'stackTrace'];
19
- return fields.reduce((v, field) => ({ ...v, [field]: error[field] }), {});
20
- };
21
-
22
- const getLevel = (logLevel) => {
23
- if (logLevel) return logLevel;
24
- if (env.LOG_LEVEL) return env.LOG_LEVEL;
25
- if (infoEnvNmaes.includes(env.NODE_ENV)) return 'info';
26
- if (env.NODE_ENV === 'development') return 'debug';
27
- return 'debug';
28
- };
29
-
30
- const addLogsSize = winston.format((info) => {
31
- let logSize = 0;
32
- try {
33
- logSize = sizeof(JSON.stringify(info));
34
- if (logSize > 256000) {
35
- console.log(`[WARNING] Found Oversized log with message "${info.message}"`);
36
- return {
37
- message: info.message,
38
- stack: info.stack,
39
- level: info.level,
40
- logSize,
41
- };
42
- }
43
- } catch (e) {
44
- console.log(`[WARNING] Failed to calculate log size with message "${info.message}"`);
45
- }
46
-
47
- return { ...info, logSize };
48
- });
49
-
50
- const enumerateErrorFormat = winston.format((info) => {
51
- // fix for this crap: https://github.com/googleapis/nodejs-logging-winston/issues/285
52
- // eslint-disable-next-line no-param-reassign
53
- info.severity = info.level.toUpperCase();
54
-
55
- if (info.message instanceof Error) {
56
- info.message = Object.assign({ // eslint-disable-line
57
- message: info.message.message,
58
- stack: info.message.stack,
59
- }, info.message);
60
- }
61
- if (info instanceof Error) {
62
- return Object.assign({
63
- message: info.message,
64
- stack: info.stack,
65
- }, info);
66
- }
67
-
68
- // eslint-disable-next-line array-callback-return
69
- Object.keys(info).map((k) => {
70
- if (info[k] instanceof Error) {
71
- // eslint-disable-next-line no-param-reassign
72
- info[k] = serializeError(info[k]);
73
- }
74
- });
75
-
76
- return info;
77
- });
78
-
79
- const getFormat = () => {
80
- if (isProd) {
81
- return winston.format.combine(
82
- addLogsSize(),
83
- enumerateErrorFormat(),
84
- winston.format.json(),
85
- );
86
- }
87
-
88
- return winston.format.combine(
89
- addLogsSize(),
90
- enumerateErrorFormat(),
91
- winston.format.splat(),
92
- winston.format.simple(),
93
- );
94
- };
95
-
96
- const createLoggerInstance = (level, exceptionHandlers) => {
97
- const logger = createLogger({
98
- level,
99
- format: getFormat(),
100
- transports: [
101
- new winston.transports.Console(),
102
- ],
103
- exceptionHandlers,
104
- exitOnError: false,
105
- });
106
-
107
- logger.httpMorganInfo = (options) => {
108
- logger.info(options.url, {
109
- httpRequest: {
110
- status: options.status,
111
- requestUrl: options.url,
112
- requestMethod: options.method,
113
- responseSize: options['content-length'],
114
- latency: {
115
- seconds: parseInt(options['response-time'], 10) / 1000,
116
- nanos: parseInt(options['response-time'], 10) * 1000000,
117
- },
118
- userAgent: options['user-agent'],
119
- },
120
- });
121
- };
122
- if (env.NODE_ENV !== 'production') {
123
- logger.httpMorganInfo = undefined;
124
- }
125
-
126
- return logger;
127
- };
128
-
129
- class LoggerInstanceManager {
130
- static getLoggerInstance(logLevel) {
131
- if (!LoggerInstanceManager.instances) {
132
- LoggerInstanceManager.instances = {};
133
- }
134
- const level = getLevel(logLevel);
135
- if (!LoggerInstanceManager.instances[level]) {
136
- LoggerInstanceManager.instances[level] = createLoggerInstance(level);
137
- }
138
- return LoggerInstanceManager.instances[level];
139
- }
140
- }
141
-
142
-
143
- module.exports = LoggerInstanceManager.getLoggerInstance;