1
1
const async = require ( 'async' ) ;
2
2
require ( 'colors' ) ;
3
- const fs = require ( 'fs' ) ;
3
+ const fs = require ( 'fs-extra ' ) ;
4
4
const date = require ( 'date-and-time' ) ;
5
5
const { escapeHtml } = require ( './utils' ) ;
6
6
const util = require ( 'util' ) ;
7
7
8
8
const DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss:SSS' ;
9
+ const DELIM = ' ' ;
9
10
10
11
export const LogLevels = {
11
12
error : 'error' ,
@@ -21,28 +22,45 @@ export class Logger {
21
22
this . logLevel = options . logLevel || 'info' ;
22
23
this . _logFunction = options . logFunction || console . log ;
23
24
this . fs = options . fs || fs ;
24
- this . logFunction = function ( ...args ) {
25
- const color = args [ args . length - 1 ] ;
26
- args . splice ( args . length - 1 , 1 ) ;
27
- this . _logFunction ( ...args . filter ( arg => arg ?? false ) . map ( arg => {
28
- if ( color ) {
29
- return typeof arg === 'object' ? util . inspect ( arg , 2 ) [ color ] : arg [ color ] ;
30
- }
31
- return typeof arg === 'object' ? util . inspect ( arg , 2 ) : arg ;
32
- } ) ) ;
25
+
26
+ this . logFunction = function ( args , color ) {
27
+ args = Array . isArray ( args ) ? args : [ args ] ;
28
+ this . _logFunction ( ...( args . filter ( arg => arg ?? false ) . map ( arg => {
29
+ if ( typeof arg === 'object' ) arg = util . inspect ( arg , 2 ) ;
30
+ return color ? arg [ color ] : arg ;
31
+ } ) ) ) ;
33
32
} ;
33
+
34
34
this . logFile = options . logFile ;
35
+ if ( this . logFile ) {
36
+ this . fs . ensureFileSync ( this . logFile ) ;
37
+ }
35
38
36
- this . writeToFile = async . cargo ( ( tasks , callback ) => {
39
+ const isDebugOrTrace = [ 'debug' , 'trace' ] . includes ( this . logLevel ) ;
40
+ this . isDebugOrTrace = isDebugOrTrace ;
41
+
42
+ const noop = ( ) => { } ;
43
+ this . writeToFile = async . cargo ( ( tasks , callback = noop ) => {
37
44
if ( ! this . logFile ) {
38
45
return callback ( ) ;
39
46
}
40
47
let logs = '' ;
41
- let origin = "[" + ( ( new Error ( ) . stack ) . split ( "at " ) [ 3 ] ) . trim ( ) + "]" ;
42
48
tasks . forEach ( task => {
43
- logs += `[${ date . format ( new Date ( ) , DATE_FORMAT ) } ] ${ task . prefix } ${ task . args } \n` ;
49
+ let message = [ ] . concat ( task . args ) . join ( ' ' ) . trim ( ) ;
50
+ if ( ! message ) return ;
51
+ const dts = `[${ date . format ( new Date ( ) , DATE_FORMAT ) } ]` ;
52
+ message = message . replace ( / \s + / g, ' ' ) ;
53
+ let origin = '' ;
54
+ if ( isDebugOrTrace ) origin = `${ DELIM } ${ task . origin . match ( / ^ a t \s + .* ( \( .* \) ) / ) [ 1 ] || '(unknown)' } ` ;
55
+ const prefix = task . prefix ;
56
+ logs += `${ dts } ${ DELIM } ${ prefix } ${ DELIM } ${ message } ${ origin } \n` ;
44
57
} ) ;
45
- this . fs . appendFile ( this . logFile , `\n${ origin } ${ logs } ` , err => {
58
+
59
+ if ( ! logs ) {
60
+ callback ( ) ;
61
+ }
62
+
63
+ this . fs . appendFile ( this . logFile , logs . stripColors , err => {
46
64
if ( err ) {
47
65
this . logFunction ( `There was an error writing to the log file: ${ err } ` , 'red' ) ;
48
66
return callback ( err ) ;
@@ -71,116 +89,135 @@ export class Logger {
71
89
return ;
72
90
}
73
91
74
- let callback = ( ) => { } ;
75
- if ( typeof args [ args . length - 1 ] === 'function' ) {
76
- callback = args [ args . length - 1 ] ;
77
- args . splice ( args . length - 1 , 1 ) ;
78
- }
79
-
80
92
this . events . emit ( "log" , "error" , args ) ;
81
- this . logFunction ( ...args , 'red' ) ;
82
- this . writeToFile . push ( { prefix : "[error]: " , args } , callback ) ;
93
+ this . logFunction ( args , 'red' ) ;
94
+
95
+ let origin ;
96
+ if ( this . isDebugOrTrace ) {
97
+ try {
98
+ const stack = new Error ( ) . stack ;
99
+ origin = stack . split ( '\n' ) [ 2 ] . trim ( ) ;
100
+ // eslint-disable-next-line no-empty
101
+ } catch ( e ) { }
102
+ }
103
+ this . writeToFile . push ( { args, origin, prefix : "[error]" } ) ;
83
104
}
84
105
85
106
warn ( ...args ) {
86
107
if ( ! args . length || ! ( this . shouldLog ( 'warn' ) ) ) {
87
108
return ;
88
109
}
89
110
90
- let callback = ( ) => { } ;
91
- if ( typeof args [ args . length - 1 ] === 'function' ) {
92
- callback = args [ args . length - 1 ] ;
93
- args . splice ( args . length - 1 , 1 ) ;
94
- }
95
-
96
111
this . events . emit ( "log" , "warn" , args ) ;
97
- this . logFunction ( ...args , 'yellow' ) ;
98
- this . writeToFile . push ( { prefix : "[warning]: " , args } , callback ) ;
112
+ this . logFunction ( args , 'yellow' ) ;
113
+
114
+ let origin ;
115
+ if ( this . isDebugOrTrace ) {
116
+ try {
117
+ const stack = new Error ( ) . stack ;
118
+ origin = stack . split ( '\n' ) [ 2 ] . trim ( ) ;
119
+ // eslint-disable-next-line no-empty
120
+ } catch ( e ) { }
121
+ }
122
+ this . writeToFile . push ( { args, origin, prefix : "[warn]" } ) ;
99
123
}
100
124
101
125
info ( ...args ) {
102
126
if ( ! args . length || ! ( this . shouldLog ( 'info' ) ) ) {
103
127
return ;
104
128
}
105
129
106
- let callback = ( ) => { } ;
107
- if ( typeof args [ args . length - 1 ] === 'function' ) {
108
- callback = args [ args . length - 1 ] ;
109
- args . splice ( args . length - 1 , 1 ) ;
110
- }
111
-
112
130
this . events . emit ( "log" , "info" , args ) ;
113
- this . logFunction ( ...args , 'green' ) ;
114
- this . writeToFile . push ( { prefix : "[info]: " , args } , callback ) ;
131
+ this . logFunction ( args , 'green' ) ;
132
+
133
+ let origin ;
134
+ if ( this . isDebugOrTrace ) {
135
+ try {
136
+ const stack = new Error ( ) . stack ;
137
+ origin = stack . split ( '\n' ) [ 2 ] . trim ( ) ;
138
+ // eslint-disable-next-line no-empty
139
+ } catch ( e ) { }
140
+ }
141
+ this . writeToFile . push ( { args, origin, prefix : "[info]" } ) ;
115
142
}
116
143
117
144
consoleOnly ( ...args ) {
118
145
if ( ! args . length || ! ( this . shouldLog ( 'info' ) ) ) {
119
146
return ;
120
147
}
121
148
122
- let callback = ( ) => { } ;
123
- if ( typeof args [ args . length - 1 ] === 'function' ) {
124
- callback = args [ args . length - 1 ] ;
125
- args . splice ( args . length - 1 , 1 ) ;
126
- }
149
+ this . logFunction ( args , 'green' ) ;
127
150
128
- this . logFunction ( ...args , 'green' ) ;
129
- this . writeToFile . push ( { prefix : "[consoleOnly]: " , args } , callback ) ;
151
+ let origin ;
152
+ if ( this . isDebugOrTrace ) {
153
+ try {
154
+ const stack = new Error ( ) . stack ;
155
+ origin = stack . split ( '\n' ) [ 2 ] . trim ( ) ;
156
+ // eslint-disable-next-line no-empty
157
+ } catch ( e ) { }
158
+ }
159
+ this . writeToFile . push ( { args, origin, prefix : "[consoleOnly]" } ) ;
130
160
}
131
161
132
162
debug ( ...args ) {
133
163
if ( ! args . length || ! ( this . shouldLog ( 'debug' ) ) ) {
134
164
return ;
135
165
}
136
166
137
- let callback = ( ) => { } ;
138
- if ( typeof args [ args . length - 1 ] === 'function' ) {
139
- callback = args [ args . length - 1 ] ;
140
- args . splice ( args . length - 1 , 1 ) ;
141
- }
142
-
143
167
this . events . emit ( "log" , "debug" , args ) ;
144
- this . logFunction ( ...args , null ) ;
145
- this . writeToFile . push ( { prefix : "[debug]: " , args } , callback ) ;
168
+ this . logFunction ( args , null ) ;
169
+
170
+ let origin ;
171
+ if ( this . isDebugOrTrace ) {
172
+ try {
173
+ const stack = new Error ( ) . stack ;
174
+ origin = stack . split ( '\n' ) [ 2 ] . trim ( ) ;
175
+ // eslint-disable-next-line no-empty
176
+ } catch ( e ) { }
177
+ }
178
+ this . writeToFile . push ( { args, origin, prefix : "[debug]" } ) ;
146
179
}
147
180
148
181
trace ( ...args ) {
149
182
if ( ! args . length || ! ( this . shouldLog ( 'trace' ) ) ) {
150
183
return ;
151
184
}
152
185
153
- let callback = ( ) => { } ;
154
- if ( typeof args [ args . length - 1 ] === 'function' ) {
155
- callback = args [ args . length - 1 ] ;
156
- args . splice ( args . length - 1 , 1 ) ;
157
- }
158
-
159
186
this . events . emit ( "log" , "trace" , args ) ;
160
- this . logFunction ( ...args , null ) ;
161
- this . writeToFile . push ( { prefix : "[trace]: " , args } , callback ) ;
187
+ this . logFunction ( args , null ) ;
188
+
189
+ let origin ;
190
+ if ( this . isDebugOrTrace ) {
191
+ try {
192
+ const stack = new Error ( ) . stack ;
193
+ origin = stack . split ( '\n' ) [ 2 ] . trim ( ) ;
194
+ // eslint-disable-next-line no-empty
195
+ } catch ( e ) { }
196
+ }
197
+ this . writeToFile . push ( { args, origin, prefix : "[trace]" } ) ;
162
198
}
163
199
164
- dir ( ...args ) {
165
- const txt = args [ 0 ] ;
166
- if ( ! txt || ! ( this . shouldLog ( 'info' ) ) ) {
200
+ dir ( obj ) {
201
+ if ( ! obj || ! ( this . shouldLog ( 'info' ) ) ) {
167
202
return ;
168
203
}
169
204
170
- let callback = ( ) => { } ;
171
- if ( typeof args [ args . length - 1 ] === 'function' ) {
172
- callback = args [ args . length - 1 ] ;
173
- args . splice ( args . length - 1 , 1 ) ;
174
- }
205
+ this . events . emit ( "log" , "dir" , obj ) ;
206
+ this . logFunction ( obj , null ) ;
175
207
176
- this . events . emit ( "log" , "dir" , txt ) ;
177
- this . logFunction ( txt , null ) ;
178
- this . writeToFile ( { prefix : "[dir]: " , args } , callback ) ;
208
+ let origin ;
209
+ if ( this . isDebugOrTrace ) {
210
+ try {
211
+ const stack = new Error ( ) . stack ;
212
+ origin = stack . split ( '\n' ) [ 2 ] . trim ( ) ;
213
+ // eslint-disable-next-line no-empty
214
+ } catch ( e ) { }
215
+ }
216
+ this . writeToFile ( { args : obj , origin, prefix : "[dir]" } ) ;
179
217
}
180
218
181
219
shouldLog ( level ) {
182
220
const logLevels = Object . keys ( LogLevels ) ;
183
221
return ( logLevels . indexOf ( level ) <= logLevels . indexOf ( this . logLevel ) ) ;
184
222
}
185
223
}
186
-
0 commit comments