zeddemore-logger 1.2.2 → 1.2.3
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/lib/date.js +4 -2
- package/lib/enums.js +22 -1
- package/lib/math.js +3 -3
- package/lib/zeddemore-logger.js +75 -28
- package/package.json +1 -1
package/lib/date.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
// Copyright (c) 2025 by Beardon Services, Inc.
|
|
2
2
|
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
|
|
3
5
|
function convertMilliseconds(milliseconds, options) {
|
|
4
6
|
options = options || { };
|
|
5
|
-
const digits = options.digits
|
|
6
|
-
const spaced = options.
|
|
7
|
+
const digits = _.isInteger(options.digits) ? options.digits : 3;
|
|
8
|
+
const spaced = _.isBoolean(options.spaced) ? options.spaced : false;
|
|
7
9
|
let value = milliseconds || 0;
|
|
8
10
|
let unit = 'ms';
|
|
9
11
|
if (milliseconds) {
|
package/lib/enums.js
CHANGED
|
@@ -119,9 +119,29 @@ const morganFormats = {
|
|
|
119
119
|
COMBINED: 'combined',
|
|
120
120
|
COMMON: 'common',
|
|
121
121
|
DEV: 'dev',
|
|
122
|
-
DEV_ENHANCED: ':method :url :status-colored :response-time-format :content-length-format',
|
|
123
122
|
SHORT: 'short',
|
|
124
123
|
TINY: 'tiny',
|
|
124
|
+
ZEDDEMORE: 'zeddemore', // added for `zeddemore-logger`
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const morganFormatTokens = {
|
|
128
|
+
CONTENT_LENGTH_FORMAT: 'content-length-format', // added for `zeddemore-logger`
|
|
129
|
+
DATE: 'date', // :date[format]
|
|
130
|
+
DECODED_URL: 'decoded-url', // added for `zeddemore-logger`
|
|
131
|
+
HTTP_VERSION: 'http-version',
|
|
132
|
+
METHOD: 'method',
|
|
133
|
+
REFERRER: 'referrer',
|
|
134
|
+
REMOTE_ADDR: 'remote-addr',
|
|
135
|
+
REMOTE_USER: 'remote-user',
|
|
136
|
+
REQ: 'req', // :req[header]
|
|
137
|
+
RES: 'res', // :res[header]
|
|
138
|
+
RESPONSE_TIME: 'response-time', // :response-time[digits]
|
|
139
|
+
RESPONSE_TIME_FORMAT: 'response-time-format', // added for `zeddemore-logger`
|
|
140
|
+
STATUS: 'status',
|
|
141
|
+
STATUS_COLORED: 'status-colored', // added for `zeddemore-logger`
|
|
142
|
+
TOTAL_TIME: 'total-time', // :total-time[digits]
|
|
143
|
+
URL: 'url',
|
|
144
|
+
USER_AGENT: 'user-agent',
|
|
125
145
|
};
|
|
126
146
|
|
|
127
147
|
const winstonLogLevelNames = {
|
|
@@ -158,6 +178,7 @@ module.exports = {
|
|
|
158
178
|
httpRequestHeaders,
|
|
159
179
|
httpResponseHeaders,
|
|
160
180
|
morganFormats,
|
|
181
|
+
morganFormatTokens,
|
|
161
182
|
winstonLogLevelNames,
|
|
162
183
|
winstonLogLevels,
|
|
163
184
|
};
|
package/lib/math.js
CHANGED
|
@@ -5,9 +5,9 @@ const _ = require('lodash');
|
|
|
5
5
|
function convertBytes(bytes, options = { }) {
|
|
6
6
|
options = options || { };
|
|
7
7
|
if (!bytes) return null;
|
|
8
|
-
const useBinaryUnits = options.useBinaryUnits
|
|
9
|
-
const decimals = options.decimals
|
|
10
|
-
const spaced = options.
|
|
8
|
+
const useBinaryUnits = _.isBoolean(options.useBinaryUnits) ? options.useBinaryUnits : false;
|
|
9
|
+
const decimals = _.isInteger(options.decimals) ? options.decimals : 2;
|
|
10
|
+
const spaced = _.isBoolean(options.spaced) ? options.spaced : false;
|
|
11
11
|
const base = useBinaryUnits ? 1024 : 1000;
|
|
12
12
|
const units = useBinaryUnits
|
|
13
13
|
? [ 'B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB' ]
|
package/lib/zeddemore-logger.js
CHANGED
|
@@ -16,10 +16,11 @@ const { extractToken, getRequestResponseTime, isRequestOfMethod, parseRequest }
|
|
|
16
16
|
const { logLevelMap } = require('./mappings/log_mappings');
|
|
17
17
|
|
|
18
18
|
const { colorize, combine, label, metadata, printf, timestamp } = format;
|
|
19
|
-
const { morganFormats: mf, httpMethods: http, httpRequestHeaders: rqh, httpResponseHeaders: rsh,
|
|
20
|
-
winstonLogLevels: wll } = enums;
|
|
19
|
+
const { morganFormats: mf, morganFormatTokens: mft, httpMethods: http, httpRequestHeaders: rqh, httpResponseHeaders: rsh,
|
|
20
|
+
winstonLogLevelNames: wlln, winstonLogLevels: wll } = enums;
|
|
21
21
|
|
|
22
22
|
const COLOR_CONSOLE_WHITE_HEX = '#ECECEC';
|
|
23
|
+
const DEFAULT_MORGAN_FORMAT_TOKENS = [ mft.METHOD, mft.DECODED_URL, mft.STATUS_COLORED, mft.RESPONSE_TIME_FORMAT, mft.CONTENT_LENGTH_FORMAT ];
|
|
23
24
|
const DEFAULT_REQUEST_ID_ATTRIBUTE = 'requestId';
|
|
24
25
|
const DEFAULT_USER_LOG_LEVEL = -1;
|
|
25
26
|
const WINSTON_CONSOLE_TRANSPORT_NAME = 'console';
|
|
@@ -58,6 +59,7 @@ class ZeddemoreLogger {
|
|
|
58
59
|
/** @type {Logger} */
|
|
59
60
|
#logger = null;
|
|
60
61
|
#logLevel = wll.INFO;
|
|
62
|
+
#morganFormat = null;
|
|
61
63
|
|
|
62
64
|
constructor(options) {
|
|
63
65
|
options = options || { };
|
|
@@ -65,21 +67,22 @@ class ZeddemoreLogger {
|
|
|
65
67
|
this.apiRouteCategories = options.apiRouteCategories || [ ];
|
|
66
68
|
this.apiRoutes = options.apiRoutes || [ ];
|
|
67
69
|
this.apiVersion = options.apiVersion || null;
|
|
70
|
+
this.decodeUrls = _.isBoolean(options.decodeUrls) ? options.decodeUrls : true;
|
|
68
71
|
this.defaultLabel = options.defaultLabel || 'zeddemore-logger';
|
|
69
|
-
this.disableApiCallLogging = options.
|
|
70
|
-
this.disableRouteLogging = options.
|
|
71
|
-
this.disableMorganLogging = options.
|
|
72
|
-
this.displayCaller = options.
|
|
73
|
-
this.displayIpAddress = options.
|
|
74
|
-
this.displayRequestId = options.
|
|
72
|
+
this.disableApiCallLogging = _.isBoolean(options.disableApiCallLogging) ? options.disableApiCallLogging : false;
|
|
73
|
+
this.disableRouteLogging = _.isBoolean(options.disableRouteLogging) ? options.disableRouteLogging : false;
|
|
74
|
+
this.disableMorganLogging = _.isBoolean(options.disableMorganLogging) ? options.disableMorganLogging : false;
|
|
75
|
+
this.displayCaller = _.isBoolean(options.displayCaller) ? options.displayCaller : true;
|
|
76
|
+
this.displayIpAddress = _.isBoolean(options.displayIpAddress) ? options.displayIpAddress : true;
|
|
77
|
+
this.displayRequestId = _.isBoolean(options.displayRequestId) ? options.displayRequestId : true;
|
|
75
78
|
this.customCallerSettings = options.customCallerSettings || [ ];
|
|
76
79
|
this.defaultUserLogLevel = options.defaultUserLogLevel || DEFAULT_USER_LOG_LEVEL;
|
|
77
|
-
this.#forceLogLevel = options.
|
|
78
|
-
this.#logLevel = options.
|
|
79
|
-
this.morganFormat = options.morganFormat
|
|
80
|
+
this.#forceLogLevel = _.isBoolean(options.forceLogLevel) ? options.forceLogLevel : false;
|
|
81
|
+
this.#logLevel = _.isInteger(options.logLevel) ? options.logLevel : wll.INFO;
|
|
82
|
+
this.morganFormat = _.isString(options.morganFormat) ? options.morganFormat : null;
|
|
80
83
|
this.routeModel = options.routeModel || null;
|
|
81
|
-
this.suppressNonMutatingRequestApiCallLogging = options.
|
|
82
|
-
this.suppressSuccessfulRequestApiCallLogging = options.
|
|
84
|
+
this.suppressNonMutatingRequestApiCallLogging = _.isBoolean(options.suppressNonMutatingRequestApiCallLogging) ? options.suppressNonMutatingRequestApiCallLogging : false;
|
|
85
|
+
this.suppressSuccessfulRequestApiCallLogging = _.isBoolean(options.suppressSuccessfulRequestApiCallLogging) ? options.suppressSuccessfulRequestApiCallLogging : false;
|
|
83
86
|
this.timestampFormat = options.timestampFormat || 'YYYY-MM-DD HH:mm:ss';
|
|
84
87
|
this.requestIdAttribute = options.requestIdAttribute || DEFAULT_REQUEST_ID_ATTRIBUTE;
|
|
85
88
|
this.userGetFn = options.userGetFn || this.#userGetFn;
|
|
@@ -89,6 +92,15 @@ class ZeddemoreLogger {
|
|
|
89
92
|
return !this.disableApiCallLogging && !!this.apiCallModel;
|
|
90
93
|
}
|
|
91
94
|
|
|
95
|
+
get morganFormat() {
|
|
96
|
+
if (!!this.#morganFormat) return this.#morganFormat;
|
|
97
|
+
return mf.ZEDDEMORE;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
set morganFormat(format) {
|
|
101
|
+
if (_.isString(format) && !!format.length) this.#morganFormat = format;
|
|
102
|
+
}
|
|
103
|
+
|
|
92
104
|
get forceLogLevel() {
|
|
93
105
|
return this.#forceLogLevel;
|
|
94
106
|
}
|
|
@@ -118,6 +130,35 @@ class ZeddemoreLogger {
|
|
|
118
130
|
this.#logLevel = massageLogLevel(level);
|
|
119
131
|
}
|
|
120
132
|
|
|
133
|
+
#buildMorganFormat = (morganTokens = [ ]) => {
|
|
134
|
+
function addArgument(token, argument) {
|
|
135
|
+
if (hasArgument(token)) return token;
|
|
136
|
+
const openBracketIndex = token.indexOf('[');
|
|
137
|
+
const _token = (openBracketIndex > -1) ? token.substring(0, openBracketIndex) : token;
|
|
138
|
+
return `${ _token }[${ argument }]`;
|
|
139
|
+
}
|
|
140
|
+
function hasArgument(token) {
|
|
141
|
+
const openBracketIndex = token.indexOf('[');
|
|
142
|
+
const closeBracketIndex = token.indexOf(']');
|
|
143
|
+
return ((openBracketIndex > -1) && (closeBracketIndex > -1) && (closeBracketIndex > (openBracketIndex + 1)));
|
|
144
|
+
}
|
|
145
|
+
const DEFAULT_CONTENT_LENGTH_FORMAT_DIGITS = 0;
|
|
146
|
+
const DEFAULT_RESPONSE_TIME_DIGITS = 2;
|
|
147
|
+
if (!morganTokens || !_.isArray(morganTokens) || !morganTokens.length) return mf.DEV;
|
|
148
|
+
const _morganTokens = _.map(morganTokens, (token) => {
|
|
149
|
+
if (!_.isString(token) || !token.length) return null;
|
|
150
|
+
let _token = token.trim();
|
|
151
|
+
if (_token[ 0 ] !== ':') _token = `:${ _token }`;
|
|
152
|
+
switch (_token) {
|
|
153
|
+
case mft.CONTENT_LENGTH_FORMAT: return hasArgument(_token) ? _token : addArgument(_token, DEFAULT_CONTENT_LENGTH_FORMAT_DIGITS);
|
|
154
|
+
case mft.RESPONSE_TIME:
|
|
155
|
+
case mft.RESPONSE_TIME_FORMAT: return hasArgument(_token) ? _token : addArgument(_token, DEFAULT_RESPONSE_TIME_DIGITS);
|
|
156
|
+
default: return _token;
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
return (_.compact(_morganTokens)).join(' ');
|
|
160
|
+
}
|
|
161
|
+
|
|
121
162
|
#buildWinstonFormat = (options, additionalFormats = [ ]) => {
|
|
122
163
|
options = options || { };
|
|
123
164
|
const formats = [
|
|
@@ -242,22 +283,28 @@ class ZeddemoreLogger {
|
|
|
242
283
|
}
|
|
243
284
|
|
|
244
285
|
#initializeMorgan() {
|
|
245
|
-
function buildContentLengthFormatToken(res) {
|
|
246
|
-
const contentLength = convertBytes(res.get('content-length'), { digits
|
|
286
|
+
function buildContentLengthFormatToken(res, digits = 2) {
|
|
287
|
+
const contentLength = convertBytes(res.get('content-length'), { digits });
|
|
247
288
|
return contentLength ? ` - ${ contentLength }` : '';
|
|
248
289
|
}
|
|
249
|
-
function
|
|
290
|
+
function buildDecodedUrl(req) {
|
|
291
|
+
const url = req.originalUrl || req.url;
|
|
292
|
+
return decodeURI(url);
|
|
293
|
+
}
|
|
294
|
+
function buildResponseTimeFormatToken(req, res, digits = 0) {
|
|
250
295
|
const responseTime = getRequestResponseTime(req, res);
|
|
251
|
-
return responseTime ? convertMilliseconds(responseTime, { digits
|
|
296
|
+
return responseTime ? convertMilliseconds(responseTime, { digits }) : '-';
|
|
252
297
|
}
|
|
253
298
|
function buildStatusColoredToken(res) {
|
|
254
299
|
const statusCode = areHeadersSent(res) ? res.statusCode : null;
|
|
255
300
|
if (!statusCode) return '-';
|
|
256
301
|
return chalkHttpStatuses(statusCode);
|
|
257
302
|
}
|
|
258
|
-
morgan.token(
|
|
259
|
-
morgan.token(
|
|
260
|
-
morgan.token(
|
|
303
|
+
morgan.token(mft.CONTENT_LENGTH_FORMAT, (req, res, digits) => { return buildContentLengthFormatToken(res, digits); });
|
|
304
|
+
morgan.token(mft.DECODED_URL, (req, res) => { return buildDecodedUrl(req); });
|
|
305
|
+
morgan.token(mft.RESPONSE_TIME_FORMAT, (req, res, digits) => { return buildResponseTimeFormatToken(req, res, digits); });
|
|
306
|
+
morgan.token(mft.STATUS_COLORED, (req, res) => { return buildStatusColoredToken(res); });
|
|
307
|
+
morgan.format(mf.ZEDDEMORE, this.#buildMorganFormat(DEFAULT_MORGAN_FORMAT_TOKENS));
|
|
261
308
|
}
|
|
262
309
|
|
|
263
310
|
log = (logLevel) => {
|
|
@@ -268,7 +315,7 @@ class ZeddemoreLogger {
|
|
|
268
315
|
|
|
269
316
|
#logServerInfo = (options, logLevel = wll.INFO) => {
|
|
270
317
|
options = options || { };
|
|
271
|
-
const showLogLevel = options.
|
|
318
|
+
const showLogLevel = _.isBoolean(options.showLogLevel) ? options.showLogLevel : true;
|
|
272
319
|
const logLevelLabel = chalkLogLevel(this.#logLevel, this.logLevelName.toUpperCase());
|
|
273
320
|
const msgParts = [ `Server is ${ chalk.bold(chalk.yellowBright('⚡live⚡')) }` ];
|
|
274
321
|
if (showLogLevel) msgParts.push(`with log level ${ logLevelLabel }${ this.#forceLogLevel ? ` (${ chalk.italic('forced') })` : '' }`);
|
|
@@ -302,7 +349,7 @@ class ZeddemoreLogger {
|
|
|
302
349
|
|
|
303
350
|
#logServerRoutesAdded = (options, logLevel = wll.INFO) => {
|
|
304
351
|
options = options || { };
|
|
305
|
-
const showCategories = options.
|
|
352
|
+
const showCategories = _.isBoolean(options.showCategories) ? options.showCategories : true;
|
|
306
353
|
const routes = options.routes || this.apiRoutes || [ ];
|
|
307
354
|
const routesLabel = (routes.length === 1) ? 'route' : 'routes';
|
|
308
355
|
const addedLabel = chalk.green('added');
|
|
@@ -316,10 +363,10 @@ class ZeddemoreLogger {
|
|
|
316
363
|
|
|
317
364
|
logServerStartup = (options, logLevel = wll.INFO) => {
|
|
318
365
|
options = options || { };
|
|
319
|
-
const showListening = options.
|
|
320
|
-
const showPackages = options.
|
|
321
|
-
const showRoutes = options.
|
|
322
|
-
const showInfo = options.
|
|
366
|
+
const showListening = _.isBoolean(options.showListening) ? options.showListening : true;
|
|
367
|
+
const showPackages = _.isBoolean(options.showPackages) ? options.showPackages : true;
|
|
368
|
+
const showRoutes = _.isBoolean(options.showRoutes) ? options.showRoutes : true;
|
|
369
|
+
const showInfo = _.isBoolean(options.showInfo) ? options.showInfo : true;
|
|
323
370
|
if (showListening) this.#logServerListening(options, logLevel);
|
|
324
371
|
if (showPackages && options.packages) this.#logServerPackagesInfo(options, options.packages, logLevel);
|
|
325
372
|
if (showRoutes) this.#logServerRoutesAdded(options, logLevel);
|
|
@@ -340,8 +387,8 @@ class ZeddemoreLogger {
|
|
|
340
387
|
|
|
341
388
|
morganMiddleware = (options) => {
|
|
342
389
|
options = options || { };
|
|
343
|
-
const disableMorganLogging = options.
|
|
344
|
-
const morganFormat = options.morganFormat || this
|
|
390
|
+
const disableMorganLogging = _.isBoolean(options.disableMorganLogging) ? options.disableMorganLogging : this.disableMorganLogging;
|
|
391
|
+
const morganFormat = options.morganFormat || this.#buildMorganFormat(DEFAULT_MORGAN_FORMAT_TOKENS);
|
|
345
392
|
const userGetFn = (_.isFunction(options.userGetFn) ? options.userGetFn : null) || this.userGetFn;
|
|
346
393
|
return (req, res, next) => {
|
|
347
394
|
this.#initializeMorgan();
|