zeddemore-logger 1.0.7 → 1.1.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.
package/lib/enums.js CHANGED
@@ -1,5 +1,23 @@
1
1
  // Copyright (c) 2025 by Beardon Services, Inc.
2
2
 
3
+ const ansi256Colors = {
4
+ LOG_LEVEL_DEBUG: 34, // blue
5
+ LOG_LEVEL_ERROR: 31, // red
6
+ LOG_LEVEL_HTTP: 32, // green
7
+ LOG_LEVEL_INFO: 32, // green
8
+ LOG_LEVEL_SILLY: 35, // magenta
9
+ LOG_LEVEL_VERBOSE: 36, // cyan
10
+ LOG_LEVEL_WARNING: 33, // yellow
11
+ };
12
+
13
+ const ansiColors = {
14
+ HTTP_CLIENT_ERROR: 33, // red
15
+ HTTP_INFORMATIONAL: 0,
16
+ HTTP_REDIRECTION: 36, // blue
17
+ HTTP_SERVER_ERROR: 31, // red
18
+ HTTP_SUCCESSFUL: 32, // green
19
+ };
20
+
3
21
  const apiLogLevelCaptions = {
4
22
  DEFAULT: 'Default',
5
23
  ERROR: 'Error',
@@ -42,6 +60,34 @@ const databaseOperations = {
42
60
  UPDATE: 'UPDATE',
43
61
  };
44
62
 
63
+ const hexColors = {
64
+ BLACK: '#000000',
65
+ CONSOLE_WHITE: '#ECECEC',
66
+ DB_DELETE: '#F22613',
67
+ DB_INSERT: '#00B16A',
68
+ DB_SELECT: '#1E90FF',
69
+ DB_TRUNCATE: '#750505',
70
+ DB_UPDATE: '#F9690E',
71
+ HTTP_CONNECT: '#FFFFFF',
72
+ HTTP_DELETE: '#EF968A',
73
+ HTTP_GET: '#67D193',
74
+ HTTP_HEAD: '#68D696',
75
+ HTTP_OPTIONS: '#E55AA8',
76
+ HTTP_PATCH: '#C0A8E1',
77
+ HTTP_POST: '#F4DA7A',
78
+ HTTP_PUT: '#74AEF6',
79
+ HTTP_TRACE: '#FFFFFF',
80
+ OSU_ORANGE: '#FF6600',
81
+ };
82
+
83
+ const httpStatusCodeGroups = {
84
+ INFORMATIONAL: 1,
85
+ SUCCESSFUL: 2,
86
+ REDIRECTION: 3,
87
+ CLIENT_ERROR: 4,
88
+ SERVER_ERROR: 5,
89
+ };
90
+
45
91
  const httpMethods = {
46
92
  GET: 'GET',
47
93
  HEAD: 'HEAD',
@@ -56,9 +102,12 @@ const httpMethods = {
56
102
 
57
103
  const httpRequestHeaders = {
58
104
  ALLOW: 'Allow',
105
+ APP_VERSION: 'App-Version',
59
106
  AUTHORIZATION: 'Authorization',
60
107
  BEARER_PREFIX: 'Bearer',
108
+ FORWARDED_FOR: 'X-Forwarded-For',
61
109
  REQUEST_ID: 'X-Request-Id',
110
+ USER_AGENT: 'User-Agent',
62
111
  };
63
112
 
64
113
  const httpResponseHeaders = {
@@ -96,11 +145,15 @@ const winstonLogLevels = {
96
145
  };
97
146
 
98
147
  module.exports = {
148
+ ansi256Colors,
149
+ ansiColors,
99
150
  apiLogLevelCaptions,
100
151
  apiLogLevels,
101
152
  chalkFormats,
102
153
  chalkLayers,
103
154
  databaseOperations,
155
+ hexColors,
156
+ httpStatusCodeGroups,
104
157
  httpMethods,
105
158
  httpRequestHeaders,
106
159
  httpResponseHeaders,
@@ -3,44 +3,45 @@
3
3
  const _ = require('lodash');
4
4
  const enums = require('../enums');
5
5
 
6
- const { databaseOperations: dbo, chalkFormats: cs, httpMethods: http, winstonLogLevels: wll } = enums;
6
+ const { ansi256Colors: a256c, ansiColors: ac, databaseOperations: dbo, chalkFormats: cs, hexColors: hc,
7
+ httpMethods: http, winstonLogLevels: wll } = enums;
7
8
 
8
9
  const databaseOperationColors = [
9
- { match: dbo.DELETE, style: { format: cs.HEX, fore: '#F22613', back: null } },
10
- { match: dbo.INSERT, style: { format: cs.HEX, fore: '#00B16A', back: null } },
11
- { match: dbo.SELECT, style: { format: cs.HEX, fore: '#1E90FF', back: null } },
12
- { match: dbo.TRUNCATE, style: { format: cs.HEX, fore: '#750505', back: null } },
13
- { match: dbo.UPDATE, style: { format: cs.HEX, fore: '#F9690E', back: null } },
10
+ { match: dbo.DELETE, style: { format: cs.HEX, fore: hc.DB_DELETE, back: null } },
11
+ { match: dbo.INSERT, style: { format: cs.HEX, fore: hc.DB_INSERT, back: null } },
12
+ { match: dbo.SELECT, style: { format: cs.HEX, fore: hc.DB_SELECT, back: null } },
13
+ { match: dbo.TRUNCATE, style: { format: cs.HEX, fore: hc.DB_TRUNCATE, back: null } },
14
+ { match: dbo.UPDATE, style: { format: cs.HEX, fore: hc.DB_UPDATE, back: null } },
14
15
  ];
15
16
 
16
17
  const httpStatusColors = [
17
- { range: _.range(500, 600), style: { format: cs.ANSI, fore: 31, back: null } },
18
- { range: _.range(400, 500), style: { format: cs.ANSI, fore: 33, back: null } },
19
- { range: _.range(300, 400), style: { format: cs.ANSI, fore: 36, back: null } },
20
- { range: _.range(200, 300), style: { format: cs.ANSI, fore: 32, back: null } },
21
- { range: _.range(100, 200), style: { format: cs.ANSI, fore: 0, back: null } },
18
+ { range: _.range(500, 600), style: { format: cs.ANSI, fore: ac.HTTP_SERVER_ERROR, back: null } },
19
+ { range: _.range(400, 500), style: { format: cs.ANSI, fore: ac.HTTP_CLIENT_ERROR, back: null } },
20
+ { range: _.range(300, 400), style: { format: cs.ANSI, fore: ac.HTTP_REDIRECTION, back: null } },
21
+ { range: _.range(200, 300), style: { format: cs.ANSI, fore: ac.HTTP_SUCCESSFUL, back: null } },
22
+ { range: _.range(100, 200), style: { format: cs.ANSI, fore: ac.HTTP_INFORMATIONAL, back: null } },
22
23
  ];
23
24
 
24
25
  const httpVerbColors = [
25
- { match: http.GET, style: { format: cs.HEX, fore: '#000000', back: '#67D193' } },
26
- { match: http.HEAD, style: { format: cs.HEX, fore: '#000000', back: '#68D696' } },
27
- { match: http.POST, style: { format: cs.HEX, fore: '#000000', back: '#F4DA7A' } },
28
- { match: http.PUT, style: { format: cs.HEX, fore: '#000000', back: '#74AEF6' } },
29
- { match: http.DELETE, style: { format: cs.HEX, fore: '#000000', back: '#EF968A' } },
30
- { match: http.CONNECT, style: { format: cs.HEX, fore: '#000000', back: '#FFFFFF' } },
31
- { match: http.OPTIONS, style: { format: cs.HEX, fore: '#000000', back: '#E55AA8' } },
32
- { match: http.TRACE, style: { format: cs.HEX, fore: '#000000', back: '#FFFFFF' } },
33
- { match: http.PATCH, style: { format: cs.HEX, fore: '#000000', back: '#C0A8E1' } },
26
+ { match: http.CONNECT, style: { format: cs.HEX, fore: hc.BLACK, back: hc.HTTP_CONNECT } },
27
+ { match: http.DELETE, style: { format: cs.HEX, fore: hc.BLACK, back: hc.HTTP_DELETE } },
28
+ { match: http.GET, style: { format: cs.HEX, fore: hc.BLACK, back: hc.HTTP_GET } },
29
+ { match: http.HEAD, style: { format: cs.HEX, fore: hc.BLACK, back: hc.HTTP_HEAD } },
30
+ { match: http.OPTIONS, style: { format: cs.HEX, fore: hc.BLACK, back: hc.HTTP_OPTIONS } },
31
+ { match: http.PATCH, style: { format: cs.HEX, fore: hc.BLACK, back: hc.HTTP_PATCH } },
32
+ { match: http.POST, style: { format: cs.HEX, fore: hc.BLACK, back: hc.HTTP_POST } },
33
+ { match: http.PUT, style: { format: cs.HEX, fore: hc.BLACK, back: hc.HTTP_PUT } },
34
+ { match: http.TRACE, style: { format: cs.HEX, fore: hc.BLACK, back: hc.HTTP_TRACE } },
34
35
  ];
35
36
 
36
37
  const logLevelColors = [
37
- { match: wll.ERROR, style: { format: cs.ANSI256, fore: 31, back: null } }, // red
38
- { match: wll.WARNING, style: { format: cs.ANSI256, fore: 33, back: null } }, // yellow
39
- { match: wll.INFO, style: { format: cs.ANSI256, fore: 32, back: null } }, // green
40
- { match: wll.HTTP, style: { format: cs.ANSI256, fore: 32, back: null } },
41
- { match: wll.VERBOSE, style: { format: cs.ANSI256, fore: 36, back: null } }, // cyan
42
- { match: wll.DEBUG, style: { format: cs.ANSI256, fore: 34, back: null } }, // blue
43
- { match: wll.SILLY, style: { format: cs.ANSI256, fore: 35, back: null } }, // magenta
38
+ { match: wll.ERROR, style: { format: cs.ANSI256, fore: a256c.LOG_LEVEL_ERROR, back: null } },
39
+ { match: wll.WARNING, style: { format: cs.ANSI256, fore: a256c.LOG_LEVEL_WARNING, back: null } },
40
+ { match: wll.INFO, style: { format: cs.ANSI256, fore: a256c.LOG_LEVEL_INFO, back: null } },
41
+ { match: wll.HTTP, style: { format: cs.ANSI256, fore: a256c.LOG_LEVEL_HTTP, back: null } },
42
+ { match: wll.VERBOSE, style: { format: cs.ANSI256, fore: a256c.LOG_LEVEL_VERBOSE, back: null } },
43
+ { match: wll.DEBUG, style: { format: cs.ANSI256, fore: a256c.LOG_LEVEL_DEBUG, back: null } },
44
+ { match: wll.SILLY, style: { format: cs.ANSI256, fore: a256c.LOG_LEVEL_SILLY, back: null } },
44
45
  ];
45
46
 
46
47
  module.exports = {
@@ -0,0 +1,18 @@
1
+ // Copyright (c) 2025 by Beardon Services, Inc.
2
+
3
+ const _ = require('lodash');
4
+ const enums = require('../enums');
5
+
6
+ const { httpStatusCodeGroups: hscg } = enums;
7
+
8
+ const httpStatusCodeGroupMap = [
9
+ { group: hscg.INFORMATIONAL, range: _.range(100, 200) },
10
+ { group: hscg.SUCCESSFUL, range: _.range(200, 300) },
11
+ { group: hscg.REDIRECTION, range: _.range(300, 400) },
12
+ { group: hscg.CLIENT_ERROR, range: _.range(400, 500) },
13
+ { group: hscg.SERVER_ERROR, range: _.range(500, 600) },
14
+ ];
15
+
16
+ module.exports = {
17
+ httpStatusCodeGroupMap,
18
+ };
@@ -1,7 +1,20 @@
1
1
  // Copyright (c) 2025 by Beardon Services, Inc.
2
2
 
3
- function areHeadersSent(res) {
4
- return typeof (res.headersSent !== 'boolean') ? Boolean(res._header) : res.headersSent;
3
+ const _ = require('lodash');
4
+
5
+ const enums = require('./enums');
6
+
7
+ const { httpRequestHeaders: rqh } = enums;
8
+
9
+ function extractToken(req) {
10
+ let token;
11
+ const authHeader = req.header(rqh.AUTHORIZATION);
12
+ if (authHeader && authHeader.startsWith(`${ rqh.BEARER_PREFIX } `)) {
13
+ token = req.header(rqh.AUTHORIZATION).split(' ')[ 1 ];
14
+ } else if (req.query && req.query.token) {
15
+ token = req.query.token;
16
+ }
17
+ return token;
5
18
  }
6
19
 
7
20
  function getRequestResponseTime(req, res) {
@@ -9,6 +22,12 @@ function getRequestResponseTime(req, res) {
9
22
  return (res._startAt[ 0 ] - req._startAt[ 0 ]) * 1e3 + (res._startAt[ 1 ] - req._startAt[ 1 ]) * 1e-6;
10
23
  }
11
24
 
25
+ function isRequestOfMethod(req, method) {
26
+ const methods = Array.isArray(method) ? method : [ method ];
27
+ if (!req || !req.method || _.isEmpty(methods)) return false;
28
+ return methods.includes(req.method);
29
+ }
30
+
12
31
  function parseRequest(req) {
13
32
  if (!req) return { };
14
33
  const body = req.body || { };
@@ -41,7 +60,8 @@ function parseRequestUserAgent(req) {
41
60
  }
42
61
 
43
62
  module.exports = {
44
- areHeadersSent,
63
+ extractToken,
45
64
  getRequestResponseTime,
65
+ isRequestOfMethod,
46
66
  parseRequest,
47
67
  };
@@ -0,0 +1,36 @@
1
+ // Copyright (c) 2025 by Beardon Services, Inc.
2
+
3
+ const _ = require('lodash');
4
+
5
+ const enums = require('./enums');
6
+ const { httpStatusCodeGroupMap } = require('./mappings/http_mappings');
7
+
8
+ const { httpStatusCodeGroups: hscg } = enums;
9
+
10
+ function areHeadersSent(res) {
11
+ return typeof (res.headersSent !== 'boolean') ? Boolean(res._header) : res.headersSent;
12
+ }
13
+
14
+ function isResponseStatusCodeInGroup(statusCode, group) {
15
+ if (!statusCode || !group) return false;
16
+ const httpStatusCodeGroupMapEntry = _.find(httpStatusCodeGroupMap, { group });
17
+ if (!httpStatusCodeGroupMapEntry) return false;
18
+ return httpStatusCodeGroupMapEntry.range.includes(+statusCode);
19
+ }
20
+
21
+ function isResponseStatusCodeRedirection(statusCode) {
22
+ return isResponseStatusCodeInGroup(statusCode, hscg.REDIRECTION);
23
+ }
24
+
25
+ function isResponseStatusCodeSuccessful(statusCode) {
26
+ return isResponseStatusCodeInGroup(statusCode, hscg.SUCCESSFUL);
27
+ }
28
+
29
+ function isResponseSuccessful(statusCode) {
30
+ return isResponseStatusCodeSuccessful(statusCode) || isResponseStatusCodeRedirection(statusCode);
31
+ }
32
+
33
+ module.exports = {
34
+ areHeadersSent,
35
+ isResponseSuccessful,
36
+ };
@@ -7,15 +7,16 @@ const morgan = require('morgan');
7
7
  const sizeof = require('object-sizeof');
8
8
  const { v4: uuid } = require('uuid');
9
9
 
10
- const { areHeadersSent, getRequestResponseTime, parseRequest } = require('./http');
10
+ const { areHeadersSent, isResponseSuccessful } = require('./response');
11
11
  const { chalkHttpStatuses, chalkHttpVerbs, stringToIdempotentHexColor } = require('./color');
12
12
  const { convertBytes } = require('./math');
13
13
  const { convertMilliseconds } = require('./date');
14
14
  const enums = require('./enums');
15
+ const { extractToken, getRequestResponseTime, isRequestOfMethod, parseRequest } = require('./request');
15
16
  const { logLevelMap } = require('./mappings/log_mappings');
16
17
 
17
18
  const { colorize, combine, label, metadata, printf, timestamp } = format;
18
- const { morganFormats: mf, httpRequestHeaders: rqh, httpResponseHeaders: rsh, winstonLogLevelNames: wlln,
19
+ const { morganFormats: mf, httpMethods: http, httpRequestHeaders: rqh, httpResponseHeaders: rsh, winstonLogLevelNames: wlln,
19
20
  winstonLogLevels: wll } = enums;
20
21
 
21
22
  const COLOR_CONSOLE_WHITE_HEX = '#ECECEC';
@@ -41,10 +42,14 @@ class ZeddemoreLogger {
41
42
 
42
43
  constructor(options) {
43
44
  options = options || { };
44
- this.additionalWriteFn = options.additionalWriteFn || null;
45
+ this.apiCallModel = options.apiCallModel || null;
46
+ this.apiRoutes = options.apiRoutes || [ ];
47
+ this.apiVersion = options.apiVersion || null;
45
48
  this.defaultLabel = options.defaultLabel || 'zeddemore-logger';
49
+ this.disableApiCallLogging = options.hasOwnProperty('disableApiCallLogging') ? options.disableApiCallLogging : false;
50
+ this.disableRouteLogging = options.hasOwnProperty('disableRouteLogging') ? options.disableRouteLogging : false;
46
51
  this.disableMorganLogging = options.hasOwnProperty('disableMorganLogging') ? options.disableMorganLogging : false;
47
- this.displayCaller = options.hasOwnProperty('displayCaller') ? options.displayUsername : true;
52
+ this.displayCaller = options.hasOwnProperty('displayCaller') ? options.displayCaller : true;
48
53
  this.displayIpAddress = options.hasOwnProperty('displayIpAddress') ? options.displayIpAddress : true;
49
54
  this.displayRequestId = options.hasOwnProperty('displayRequestId') ? options.displayRequestId : true;
50
55
  this.customCallerSettings = options.customCallerSettings || [ ];
@@ -52,11 +57,18 @@ class ZeddemoreLogger {
52
57
  this.#forceLogLevel = options.hasOwnProperty('forceLogLevel') ? options.forceLogLevel : false;
53
58
  this.#logLevel = options.hasOwnProperty('logLevel') ? options.logLevel : wll.INFO;
54
59
  this.morganFormat = options.morganFormat || mf.DEV_ENHANCED;
60
+ this.routeModel = options.routeModel || null;
61
+ this.suppressNonMutatingRequestApiCallLogging = options.hasOwnProperty('suppressNonMutatingRequestApiCallLogging') ? options.suppressNonMutatingRequestApiCallLogging : false;
62
+ this.suppressSuccessfulRequestApiCallLogging = options.hasOwnProperty('suppressSuccessfulRequestApiCallLogging') ? options.suppressSuccessfulRequestApiCallLogging : false;
55
63
  this.timestampFormat = options.timestampFormat || 'YYYY-MM-DD HH:mm:ss';
56
64
  this.requestIdAttribute = options.requestIdAttribute || DEFAULT_REQUEST_ID_ATTRIBUTE;
57
65
  this.userGetFn = options.userGetFn || this.#userGetFn;
58
66
  }
59
67
 
68
+ get apiCallLoggingEnabled() {
69
+ return !this.disableApiCallLogging && !!this.apiCallModel;
70
+ }
71
+
60
72
  get forceLogLevel() {
61
73
  return this.#forceLogLevel;
62
74
  }
@@ -69,6 +81,10 @@ class ZeddemoreLogger {
69
81
  return winstonLogLevelIdToName(this.#logLevel);
70
82
  }
71
83
 
84
+ get routeLoggingEnabled() {
85
+ return !this.disableRouteLogging && !!this.routeModel;
86
+ }
87
+
72
88
  set forceLogLevel(doForce) {
73
89
  this.#forceLogLevel = !!doForce;
74
90
  }
@@ -215,9 +231,20 @@ class ZeddemoreLogger {
215
231
  return zeddemoreLogger.createLogger(options);
216
232
  }
217
233
 
234
+ #matchPathToRoute = (path) => {
235
+ if (!path) return null;
236
+ let matchedRoute = null;
237
+ for (const route of this.apiRoutes) {
238
+ if (path.match(route.regexp)) {
239
+ matchedRoute = route.path;
240
+ break;
241
+ }
242
+ }
243
+ return matchedRoute;
244
+ }
245
+
218
246
  morganMiddleware = (options) => {
219
247
  options = options || { };
220
- const additionalWriteFn = (_.isFunction(options.additionalWriteFn) ? options.additionalWriteFn : null) || this.additionalWriteFn;
221
248
  const disableMorganLogging = options.hasOwnProperty('disableMorganLogging') ? options.disableMorganLogging : this.disableMorganLogging;
222
249
  const morganFormat = options.morganFormat || this.morganFormat;
223
250
  const userGetFn = (_.isFunction(options.userGetFn) ? options.userGetFn : null) || this.userGetFn;
@@ -227,7 +254,7 @@ class ZeddemoreLogger {
227
254
  skip: () => disableMorganLogging,
228
255
  stream: {
229
256
  write: (message) => {
230
- if (additionalWriteFn) additionalWriteFn(req, res);
257
+ if (this.apiCallLoggingEnabled) this.#writeApiCallToDatabase(req, res, options);
231
258
  const logOptions = { };
232
259
  const user = userGetFn ? userGetFn(req, res) : null;
233
260
  if (user) logOptions.user = user;
@@ -250,6 +277,21 @@ class ZeddemoreLogger {
250
277
  return next();
251
278
  }
252
279
 
280
+ routeLoggingMiddleware = (req, res, next) => {
281
+ if (!this.routeLoggingEnabled) return next();
282
+ try {
283
+ const routeValues = {
284
+ route: req.path,
285
+ method: req.method,
286
+ lastCalled: new Date().toISOString(),
287
+ };
288
+ this.#writeRouteToDatabase(routeValues);
289
+ } catch (e) {
290
+ } finally {
291
+ next();
292
+ }
293
+ }
294
+
253
295
  #userGetFn(req, res) {
254
296
  return ((res && res.locals) ? res.locals.user : null)
255
297
  || ((req && req.locals) ? req.locals.user : null)
@@ -260,7 +302,7 @@ class ZeddemoreLogger {
260
302
  const requestId = this.#getRequestId(req);
261
303
  const user = this.userGetFn(req, res) || { };
262
304
  if (!requestId) return next();
263
- const username = user.login || null;
305
+ const username = user.login || user.username || null;
264
306
  let ipAddress = user.ipAddress || null;
265
307
  if (!ipAddress) {
266
308
  const requestValues = parseRequest(req);
@@ -275,6 +317,66 @@ class ZeddemoreLogger {
275
317
  return next();
276
318
  }
277
319
 
320
+ #writeApiCallToDatabase = async (req, res, options) => {
321
+ options = options || { };
322
+ if (!req) return;
323
+ const user = this.userGetFn ? this.userGetFn(req, res) : null;
324
+ const statusCode = options.statusCode || (res ? res.statusCode : null);
325
+ if (isResponseSuccessful(statusCode) && this.suppressSuccessfulRequestApiCallLogging) return;
326
+ if (!isRequestOfMethod(req, [ http.DELETE, http.PUT ]) && this.suppressNonMutatingRequestApiCallLogging) return;
327
+ const matchedRoute = this.#matchPathToRoute(req.path);
328
+ let metadataDefaults = Object.assign({ }, user);
329
+ delete(metadataDefaults.id);
330
+ delete(metadataDefaults.logger);
331
+ const _metadata = _.defaults({ }, (options.metadata || { }), metadataDefaults);
332
+ if (matchedRoute) {
333
+ try {
334
+ const appCallValues = {
335
+ apiVersion: this.apiVersion,
336
+ client: user ? user.clientId : null,
337
+ clientVersion: req.header(rqh.APP_VERSION),
338
+ httpStatusCode: statusCode,
339
+ ipAddress: req.header(rqh.FORWARDED_FOR) || req.socket.remoteAddress,
340
+ metadata: _metadata,
341
+ method: req.method,
342
+ route: matchedRoute,
343
+ token: extractToken(req),
344
+ userAgent: req.header(rqh.USER_AGENT),
345
+ userId: user ? user.id : null,
346
+ };
347
+ await this.apiCallModel.create(appCallValues);
348
+ } catch (e) {
349
+ console.error(e);
350
+ ZeddemoreLogger.log({ user }).error('Api call logging failed, moving on');
351
+ }
352
+ }
353
+ }
354
+
355
+ #writeRouteToDatabase = async (routeValues) => {
356
+ if (!this.routeLoggingEnabled || !routeValues) return;
357
+ const matchedRoute = this.#matchPathToRoute(routeValues.route);
358
+ if (matchedRoute) {
359
+ try {
360
+ const route = await this.routeModel.findOne({ where: { route: matchedRoute }, logging: false });
361
+ if (route) {
362
+ route.count++;
363
+ route.lastCalledAt = new Date();
364
+ route.save();
365
+ } else {
366
+ this.routeModel.create({
367
+ count: 1,
368
+ lastCalledAt: new Date(),
369
+ method: routeValues.method,
370
+ route: matchedRoute,
371
+ });
372
+ }
373
+ } catch (e) {
374
+ console.error(e);
375
+ console.error('Route logging failed, moving on');
376
+ }
377
+ }
378
+ }
379
+
278
380
  static writeAxiosErrorLog(axiosError, logOptions, options) {
279
381
  logOptions = logOptions || { };
280
382
  options = options || { };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zeddemore-logger",
3
- "version": "1.0.7",
3
+ "version": "1.1.0",
4
4
  "description": "Node.js Express logger using Morgan and Winston for thread and caller info tracking",
5
5
  "repository": {
6
6
  "type": "git",