04ddf01a661f7e93d526212c18ffc7d7f7df57e0
[oweals/peertube.git] / server / helpers / logger.ts
1 // Thanks http://tostring.it/2014/06/23/advanced-logging-with-nodejs/
2 import * as mkdirp from 'mkdirp'
3 import * as path from 'path'
4 import * as winston from 'winston'
5 import { CONFIG } from '../initializers'
6
7 const label = CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT
8
9 // Create the directory if it does not exist
10 mkdirp.sync(CONFIG.STORAGE.LOG_DIR)
11
12 // Use object for better performances (~ O(1))
13 const excludedKeys = {
14   level: true,
15   message: true,
16   splat: true,
17   timestamp: true,
18   label: true
19 }
20 function keysExcluder (key, value) {
21   if (excludedKeys[key] === true) return undefined
22
23   if (key === 'err') return value.stack
24
25   return value
26 }
27
28 const consoleLoggerFormat = winston.format.printf(info => {
29   let additionalInfos = JSON.stringify(info, keysExcluder, 2)
30   if (additionalInfos === '{}') additionalInfos = ''
31   else additionalInfos = ' ' + additionalInfos
32
33   return `[${info.label}] ${info.timestamp} ${info.level}: ${info.message}${additionalInfos}`
34 })
35
36 const jsonLoggerFormat = winston.format.printf(infoArg => {
37   let info = infoArg.err
38     ? Object.assign({}, infoArg, { err: infoArg.err.stack })
39     : infoArg
40
41   return JSON.stringify(info)
42 })
43
44 const timestampFormatter = winston.format.timestamp({
45   format: 'YYYY-MM-DD HH:mm:ss.SSS'
46 })
47 const labelFormatter = winston.format.label({
48   label
49 })
50
51 const logger = winston.createLogger({
52   level: CONFIG.LOG.LEVEL,
53   transports: [
54     new winston.transports.File({
55       filename: path.join(CONFIG.STORAGE.LOG_DIR, 'peertube.log'),
56       handleExceptions: true,
57       maxsize: 5242880,
58       maxFiles: 5,
59       format: winston.format.combine(
60         winston.format.timestamp(),
61         labelFormatter,
62         winston.format.splat(),
63         jsonLoggerFormat
64       )
65     }),
66     new winston.transports.Console({
67       handleExceptions: true,
68       format: winston.format.combine(
69         timestampFormatter,
70         winston.format.splat(),
71         labelFormatter,
72         winston.format.colorize(),
73         consoleLoggerFormat
74       )
75     })
76   ],
77   exitOnError: true
78 })
79
80 function bunyanLogFactory (level: string) {
81   return function () {
82     let meta = null
83     let args = [].concat(arguments)
84
85     if (arguments[ 0 ] instanceof Error) {
86       meta = arguments[ 0 ].toString()
87       args = Array.prototype.slice.call(arguments, 1)
88       args.push(meta)
89     } else if (typeof (args[ 0 ]) !== 'string') {
90       meta = arguments[ 0 ]
91       args = Array.prototype.slice.call(arguments, 1)
92       args.push(meta)
93     }
94
95     logger[ level ].apply(logger, args)
96   }
97 }
98 const bunyanLogger = {
99   trace: bunyanLogFactory('debug'),
100   debug: bunyanLogFactory('debug'),
101   info: bunyanLogFactory('info'),
102   warn: bunyanLogFactory('warn'),
103   error: bunyanLogFactory('error'),
104   fatal: bunyanLogFactory('error')
105 }
106
107 // ---------------------------------------------------------------------------
108
109 export {
110   timestampFormatter,
111   labelFormatter,
112   consoleLoggerFormat,
113   logger,
114   bunyanLogger
115 }