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