infront-logger 1.0.0 → 1.0.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/README.MD CHANGED
@@ -6,11 +6,113 @@ The logger supports both writhing to file and to console.
6
6
  npm i @infront/logger
7
7
 
8
8
  ## Usage
9
- const {BaseLogger} = require('@infront/logger');
9
+
10
+ ### BaseLogger
11
+ const {BaseLogger} = require('infront-logger');
10
12
  let options = {};
11
13
  let logger = new BaseLogger("component1", options);
12
14
  logger.log("this is a test message");
13
15
 
16
+ ### HttpLogger
17
+ const {HttpLogger} = require('infront-logger');
18
+
19
+ const responseInterceptor = (req, res, next) => {
20
+ // Save the original response method
21
+
22
+ const originalSend = res.send;
23
+ const originalJSON = res.json;
24
+ const originalSendStatus = res.sendStatus;
25
+
26
+ let responseSent = false;
27
+ let startTime = Date.now();
28
+
29
+ // Override the response method
30
+ res.sendStatus = function(status){
31
+ try{
32
+ const httpLogger = new HttpLogger();
33
+ if (!responseSent) {
34
+ res.statusCode = status;
35
+ httpLogger.request(req);
36
+ httpLogger.response(res);
37
+
38
+
39
+ if (status < 400) {
40
+ httpLogger.success();
41
+ } else {
42
+ httpLogger.error("req.sendStatus with error status");
43
+ }
44
+ responseSent = true;
45
+ }
46
+ } catch (err){
47
+ console.error(err);
48
+
49
+ }
50
+ return originalSendStatus.call(this, status);
51
+ };
52
+
53
+ res.send = function (body){
54
+ try{
55
+ const httpLogger = new HttpLogger();
56
+ if (!responseSent) {
57
+ httpLogger.request(req);
58
+ httpLogger.response(res);
59
+ httpLogger.body(body);
60
+ if (res.statusCode < 400) {
61
+ httpLogger.success();
62
+ } else {
63
+ httpLogger.error(body.message);
64
+ }
65
+ responseSent = true;
66
+ }
67
+ } catch (err){
68
+ console.error(err);
69
+ }
70
+
71
+ // Call the original response method
72
+ return originalSend.call(this, body);
73
+ };
74
+
75
+
76
+ res.json = function (body){
77
+ try{
78
+ const httpLogger = new HttpLogger();
79
+ if (!responseSent) {
80
+ httpLogger.request(req).response(res).body(body);
81
+
82
+ if (res.statusCode < 400) {
83
+ httpLogger.success();
84
+ } else {
85
+ httpLogger.error(body.message);
86
+ }
87
+ responseSent = true;
88
+ }
89
+
90
+
91
+ } catch (err){
92
+ console.error(err);
93
+ }
94
+
95
+ // Call the original response method
96
+ return originalJSON.call(this, body);
97
+ };
98
+
99
+ // Continue processing the request
100
+ next();
101
+ }
102
+
103
+ app.use(responseInterceptor);
104
+
105
+
106
+
107
+
108
+ ### MongooseLoggerPlugin
109
+ Make sure to use before defining schemas;
110
+
111
+ const {MongooseLoggerPlugin} = require('infront-logger');
112
+ const mongoose = require('mongoose');
113
+ let plugin = MongooseLoggerPlugin({console : false, filename : 'db.log'});
114
+ mongoose.plugin(plugin);
115
+
14
116
  ## Loggers
15
117
 
16
118
  ### BaseLogger
@@ -36,8 +138,10 @@ The logger supports both writhing to file and to console.
36
138
  - levels - An object of "level name : hierarchical value"
37
139
  - level - default level (default: info)
38
140
  - dateFormat : default "YYYY-MM-DD HH:mm:ss:ms"
141
+ - file - boolean - should log to file (default : true)
39
142
  - maxFileSize: The maximum file size for a rotating file strategy (default: "30m")
40
143
  - maxFiles: The maximum number of files for a rotating file strategy (default: 2)
41
144
  - filename - name of the default log file (default: "logs.log")
42
145
  - errorFilename - name of the default error log file (default: "error.log")
43
146
  - console - boolean - should log to console (default: true)
147
+ - consoleJSON - boolean - print full json to console (default : false)
package/dist/index.es.js CHANGED
@@ -1,6 +1,6 @@
1
1
  require("winston-daily-rotate-file");
2
2
  const { format: format$1, createLogger, transports, addColors } = require("winston");
3
- const { inspect } = require("util");
3
+ require("util");
4
4
  const colors = {
5
5
  error: "red",
6
6
  warn: "yellow",
@@ -26,47 +26,57 @@ const OPTIONS = {
26
26
  filename: "logs.log",
27
27
  errorFilename: "error.log",
28
28
  console: true,
29
+ file: true,
29
30
  exclude: [],
30
31
  createSymlink: true,
31
- symlinkName: "logs.log"
32
+ symlinkName: "logs.log",
33
+ consoleJSON: false
32
34
  };
33
- function errorToJSON(error) {
34
- const { message, name, stack } = error;
35
- return {
36
- message,
37
- name,
38
- stack
39
- };
40
- }
41
35
  function fileFormatter(options) {
42
36
  return format$1.combine(
43
- // format.errors({stack: true}),
44
- {
45
- transform: (info) => {
46
- const args = [info.message, ...info[Symbol.for("splat")] || []];
47
- info.message = args.filter(Boolean).map((arg) => {
48
- if (arg instanceof Error) {
49
- return errorToJSON(arg);
50
- }
51
- return arg;
52
- });
53
- const msg = args.map((arg) => {
54
- if (typeof arg == "object")
55
- return inspect(arg, { compact: false, depth: Infinity });
56
- return arg;
57
- }).join(" ");
58
- info[Symbol.for("message")] = `${info[Symbol.for("level")]}: ${msg}${info.stack ? " " + info.stack : ""}`;
59
- if (options.exclude.some((string) => msg.includes(string)))
60
- return null;
61
- return info;
62
- }
63
- },
37
+ format$1.errors({ stack: true }),
38
+ // {
39
+ // transform: (info) => {
40
+ // const args = [info.message, ...(info[Symbol.for('splat')] || [])];
41
+ // info.message = args.filter(Boolean).map(arg => {
42
+ // if(arg instanceof Error){
43
+ // return errorToJSON(arg);
44
+ // }
45
+ // return arg;
46
+ // });
47
+ //
48
+ // const msg = args.map(arg => {
49
+ // if (typeof arg == 'object')
50
+ // return inspect(arg, {compact: false, depth: Infinity});
51
+ // return arg;
52
+ // }).join(' ');
53
+ //
54
+ // info[Symbol.for('message')] = `${info[Symbol.for('level')]}: ${msg}${info.stack ? ' ' + info.stack : ''}`;
55
+ //
56
+ // if(options.exclude.some(string => msg.includes(string))) return null;
57
+ //
58
+ // return info;
59
+ // }
60
+ // },
64
61
  format$1.timestamp({ format: options.dateFormat }),
65
62
  format$1.json()
66
63
  );
67
64
  }
68
65
  function consoleFormatter(options) {
69
- return format$1.timestamp({ format: options.dateFormat }), format$1.colorize({ all: true });
66
+ return format$1.combine(
67
+ format$1.errors({ stack: true }),
68
+ format$1.printf((info) => {
69
+ if ((info == null ? void 0 : info.level) === "error" && info.stack) {
70
+ return `${info.stack}`;
71
+ } else {
72
+ return info.message;
73
+ }
74
+ }),
75
+ // options.consoleJSON? format.json() : {transform : (info)=>info},
76
+ // options.consoleJSON? format.json() :format.prettyPrint(),
77
+ options.consoleJSON ? format$1.json() : format$1.splat(),
78
+ format$1.colorize({ all: true })
79
+ );
70
80
  }
71
81
  function getFormatter(type, options) {
72
82
  switch (type) {
@@ -90,19 +100,32 @@ function createTransport(options) {
90
100
  class Logger {
91
101
  constructor(options = {}) {
92
102
  this.options = { ...OPTIONS, ...options };
93
- let trans = [
94
- createTransport({
103
+ if (!this.options.filename.includes("."))
104
+ this.options.filename += ".log";
105
+ if (!this.options.errorFilename.includes("."))
106
+ this.options.errorFilename += ".log";
107
+ let trans = [];
108
+ let exceptionHandlers = [new transports.Console({
109
+ format: getFormatter("console", this.options)
110
+ })];
111
+ if (this.options.file) {
112
+ trans.push(createTransport({
95
113
  ...this.options,
114
+ format: "file",
96
115
  filename: this.options.filename,
97
116
  symlinkName: this.options.filename
98
- }),
99
- createTransport({
117
+ }));
118
+ trans.push(createTransport({
100
119
  ...this.options,
120
+ format: "file",
101
121
  filename: this.options.errorFilename,
102
122
  symlinkName: this.options.errorFilename,
103
123
  level: "error"
104
- })
105
- ];
124
+ }));
125
+ exceptionHandlers.push(
126
+ new transports.File({ filename: `${this.options.dirname}/${this.options.errorFilename}` })
127
+ );
128
+ }
106
129
  if (this.options.console) {
107
130
  trans.push(new transports.Console({
108
131
  format: getFormatter("console", this.options)
@@ -114,10 +137,7 @@ class Logger {
114
137
  exitOnError: false,
115
138
  // format,
116
139
  transports: trans,
117
- exceptionHandlers: [
118
- new transports.Console(),
119
- new transports.File({ filename: `${this.options.dirname}/${this.options.errorFilename}` })
120
- ]
140
+ exceptionHandlers
121
141
  });
122
142
  }
123
143
  }
@@ -349,7 +369,83 @@ class HTTPLogger extends BaseLogger {
349
369
  super.error(this._message(err));
350
370
  }
351
371
  }
372
+ const ops = [
373
+ "find",
374
+ "findOne",
375
+ "findById",
376
+ "findOneAndUpdate",
377
+ "updateOne",
378
+ "updateMany",
379
+ "countDocuments",
380
+ "estimatedDocumentCount",
381
+ "findOneAndRemove",
382
+ "findOneAndDelete",
383
+ "deleteOne",
384
+ "deleteMany",
385
+ "aggregate",
386
+ "save"
387
+ ];
388
+ const MAX_RESULT_BYTES = 100 * 1024;
389
+ class MongooseLogger extends BaseLogger {
390
+ constructor(options = {}) {
391
+ super("database", options);
392
+ }
393
+ operation(o) {
394
+ this.ctx.operation = o;
395
+ return this;
396
+ }
397
+ collection(c) {
398
+ this.ctx.collection = c;
399
+ return this;
400
+ }
401
+ query(q) {
402
+ this.ctx.query = q;
403
+ return this;
404
+ }
405
+ update(u) {
406
+ this.ctx.update = u;
407
+ return this;
408
+ }
409
+ pipeline(p) {
410
+ this.ctx.pipeline = p;
411
+ return this;
412
+ }
413
+ result(res) {
414
+ try {
415
+ this.ctx.resultSizeBytes = JSON.stringify(res).length;
416
+ } catch (err) {
417
+ }
418
+ if (Array.isArray(res)) {
419
+ this.ctx.documentCount = res.length;
420
+ } else if (this.ctx.resultSizeBytes < MAX_RESULT_BYTES) {
421
+ this.ctx.result = res;
422
+ } else {
423
+ this.ctx.result = `Result too long (more then ${MAX_RESULT_BYTES} bytes)`;
424
+ }
425
+ return this;
426
+ }
427
+ }
428
+ function postHook(target, res) {
429
+ var _a, _b, _c, _d, _e;
430
+ const op = target.constructor.name === "Aggregate" ? "aggregate" : target.op || target.$op;
431
+ const collection = ((_a = target == null ? void 0 : target._collection) == null ? void 0 : _a.collectionName) || ((_b = target == null ? void 0 : target.collection) == null ? void 0 : _b.name) || ((_d = (_c = target == null ? void 0 : target._model) == null ? void 0 : _c.collection) == null ? void 0 : _d.collectionName);
432
+ (_e = target == null ? void 0 : target.logger) == null ? void 0 : _e.operation(op).collection(collection).query(target._conditions).update(target._update).pipeline(target._pipeline).profile().result(res).info(`DB query: ${op} - ${collection}`);
433
+ }
434
+ function plugin(options = {}) {
435
+ return (schema) => {
436
+ ops.forEach((op) => {
437
+ schema.pre(op, function(next) {
438
+ this.logger = new MongooseLogger(options);
439
+ next();
440
+ });
441
+ schema.post(op, function(res) {
442
+ postHook(this, res);
443
+ });
444
+ });
445
+ };
446
+ }
352
447
  export {
353
448
  BaseLogger,
354
- HTTPLogger as HttpLogger
449
+ HTTPLogger as HttpLogger,
450
+ plugin as MongooseLoggerPlugin
355
451
  };
package/dist/index.umd.js CHANGED
@@ -4,7 +4,7 @@
4
4
  "use strict";
5
5
  require("winston-daily-rotate-file");
6
6
  const { format: format$1, createLogger, transports, addColors } = require("winston");
7
- const { inspect } = require("util");
7
+ require("util");
8
8
  const colors = {
9
9
  error: "red",
10
10
  warn: "yellow",
@@ -30,47 +30,57 @@
30
30
  filename: "logs.log",
31
31
  errorFilename: "error.log",
32
32
  console: true,
33
+ file: true,
33
34
  exclude: [],
34
35
  createSymlink: true,
35
- symlinkName: "logs.log"
36
+ symlinkName: "logs.log",
37
+ consoleJSON: false
36
38
  };
37
- function errorToJSON(error) {
38
- const { message, name, stack } = error;
39
- return {
40
- message,
41
- name,
42
- stack
43
- };
44
- }
45
39
  function fileFormatter(options) {
46
40
  return format$1.combine(
47
- // format.errors({stack: true}),
48
- {
49
- transform: (info) => {
50
- const args = [info.message, ...info[Symbol.for("splat")] || []];
51
- info.message = args.filter(Boolean).map((arg) => {
52
- if (arg instanceof Error) {
53
- return errorToJSON(arg);
54
- }
55
- return arg;
56
- });
57
- const msg = args.map((arg) => {
58
- if (typeof arg == "object")
59
- return inspect(arg, { compact: false, depth: Infinity });
60
- return arg;
61
- }).join(" ");
62
- info[Symbol.for("message")] = `${info[Symbol.for("level")]}: ${msg}${info.stack ? " " + info.stack : ""}`;
63
- if (options.exclude.some((string) => msg.includes(string)))
64
- return null;
65
- return info;
66
- }
67
- },
41
+ format$1.errors({ stack: true }),
42
+ // {
43
+ // transform: (info) => {
44
+ // const args = [info.message, ...(info[Symbol.for('splat')] || [])];
45
+ // info.message = args.filter(Boolean).map(arg => {
46
+ // if(arg instanceof Error){
47
+ // return errorToJSON(arg);
48
+ // }
49
+ // return arg;
50
+ // });
51
+ //
52
+ // const msg = args.map(arg => {
53
+ // if (typeof arg == 'object')
54
+ // return inspect(arg, {compact: false, depth: Infinity});
55
+ // return arg;
56
+ // }).join(' ');
57
+ //
58
+ // info[Symbol.for('message')] = `${info[Symbol.for('level')]}: ${msg}${info.stack ? ' ' + info.stack : ''}`;
59
+ //
60
+ // if(options.exclude.some(string => msg.includes(string))) return null;
61
+ //
62
+ // return info;
63
+ // }
64
+ // },
68
65
  format$1.timestamp({ format: options.dateFormat }),
69
66
  format$1.json()
70
67
  );
71
68
  }
72
69
  function consoleFormatter(options) {
73
- return format$1.timestamp({ format: options.dateFormat }), format$1.colorize({ all: true });
70
+ return format$1.combine(
71
+ format$1.errors({ stack: true }),
72
+ format$1.printf((info) => {
73
+ if ((info == null ? void 0 : info.level) === "error" && info.stack) {
74
+ return `${info.stack}`;
75
+ } else {
76
+ return info.message;
77
+ }
78
+ }),
79
+ // options.consoleJSON? format.json() : {transform : (info)=>info},
80
+ // options.consoleJSON? format.json() :format.prettyPrint(),
81
+ options.consoleJSON ? format$1.json() : format$1.splat(),
82
+ format$1.colorize({ all: true })
83
+ );
74
84
  }
75
85
  function getFormatter(type, options) {
76
86
  switch (type) {
@@ -94,19 +104,32 @@
94
104
  class Logger {
95
105
  constructor(options = {}) {
96
106
  this.options = { ...OPTIONS, ...options };
97
- let trans = [
98
- createTransport({
107
+ if (!this.options.filename.includes("."))
108
+ this.options.filename += ".log";
109
+ if (!this.options.errorFilename.includes("."))
110
+ this.options.errorFilename += ".log";
111
+ let trans = [];
112
+ let exceptionHandlers = [new transports.Console({
113
+ format: getFormatter("console", this.options)
114
+ })];
115
+ if (this.options.file) {
116
+ trans.push(createTransport({
99
117
  ...this.options,
118
+ format: "file",
100
119
  filename: this.options.filename,
101
120
  symlinkName: this.options.filename
102
- }),
103
- createTransport({
121
+ }));
122
+ trans.push(createTransport({
104
123
  ...this.options,
124
+ format: "file",
105
125
  filename: this.options.errorFilename,
106
126
  symlinkName: this.options.errorFilename,
107
127
  level: "error"
108
- })
109
- ];
128
+ }));
129
+ exceptionHandlers.push(
130
+ new transports.File({ filename: `${this.options.dirname}/${this.options.errorFilename}` })
131
+ );
132
+ }
110
133
  if (this.options.console) {
111
134
  trans.push(new transports.Console({
112
135
  format: getFormatter("console", this.options)
@@ -118,10 +141,7 @@
118
141
  exitOnError: false,
119
142
  // format,
120
143
  transports: trans,
121
- exceptionHandlers: [
122
- new transports.Console(),
123
- new transports.File({ filename: `${this.options.dirname}/${this.options.errorFilename}` })
124
- ]
144
+ exceptionHandlers
125
145
  });
126
146
  }
127
147
  }
@@ -353,7 +373,83 @@
353
373
  super.error(this._message(err));
354
374
  }
355
375
  }
376
+ const ops = [
377
+ "find",
378
+ "findOne",
379
+ "findById",
380
+ "findOneAndUpdate",
381
+ "updateOne",
382
+ "updateMany",
383
+ "countDocuments",
384
+ "estimatedDocumentCount",
385
+ "findOneAndRemove",
386
+ "findOneAndDelete",
387
+ "deleteOne",
388
+ "deleteMany",
389
+ "aggregate",
390
+ "save"
391
+ ];
392
+ const MAX_RESULT_BYTES = 100 * 1024;
393
+ class MongooseLogger extends BaseLogger {
394
+ constructor(options = {}) {
395
+ super("database", options);
396
+ }
397
+ operation(o) {
398
+ this.ctx.operation = o;
399
+ return this;
400
+ }
401
+ collection(c) {
402
+ this.ctx.collection = c;
403
+ return this;
404
+ }
405
+ query(q) {
406
+ this.ctx.query = q;
407
+ return this;
408
+ }
409
+ update(u) {
410
+ this.ctx.update = u;
411
+ return this;
412
+ }
413
+ pipeline(p) {
414
+ this.ctx.pipeline = p;
415
+ return this;
416
+ }
417
+ result(res) {
418
+ try {
419
+ this.ctx.resultSizeBytes = JSON.stringify(res).length;
420
+ } catch (err) {
421
+ }
422
+ if (Array.isArray(res)) {
423
+ this.ctx.documentCount = res.length;
424
+ } else if (this.ctx.resultSizeBytes < MAX_RESULT_BYTES) {
425
+ this.ctx.result = res;
426
+ } else {
427
+ this.ctx.result = `Result too long (more then ${MAX_RESULT_BYTES} bytes)`;
428
+ }
429
+ return this;
430
+ }
431
+ }
432
+ function postHook(target, res) {
433
+ var _a, _b, _c, _d, _e;
434
+ const op = target.constructor.name === "Aggregate" ? "aggregate" : target.op || target.$op;
435
+ const collection = ((_a = target == null ? void 0 : target._collection) == null ? void 0 : _a.collectionName) || ((_b = target == null ? void 0 : target.collection) == null ? void 0 : _b.name) || ((_d = (_c = target == null ? void 0 : target._model) == null ? void 0 : _c.collection) == null ? void 0 : _d.collectionName);
436
+ (_e = target == null ? void 0 : target.logger) == null ? void 0 : _e.operation(op).collection(collection).query(target._conditions).update(target._update).pipeline(target._pipeline).profile().result(res).info(`DB query: ${op} - ${collection}`);
437
+ }
438
+ function plugin(options = {}) {
439
+ return (schema) => {
440
+ ops.forEach((op) => {
441
+ schema.pre(op, function(next) {
442
+ this.logger = new MongooseLogger(options);
443
+ next();
444
+ });
445
+ schema.post(op, function(res) {
446
+ postHook(this, res);
447
+ });
448
+ });
449
+ };
450
+ }
356
451
  exports2.BaseLogger = BaseLogger;
357
452
  exports2.HttpLogger = HTTPLogger;
453
+ exports2.MongooseLoggerPlugin = plugin;
358
454
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
359
455
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "infront-logger",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "description": "",
5
5
  "files": [
6
6
  "dist"