@@ -7,18 +7,11 @@ const MiniPass = require('minipass')
7
7
const fsMiniPass = require ( 'fs-minipass' )
8
8
const fs = require ( '@npmcli/fs' )
9
9
const log = require ( './log-shim' )
10
+ const runId = require ( './run-id' )
10
11
11
12
const padZero = ( n , length ) => n . toString ( ) . padStart ( length . toString ( ) . length , '0' )
12
13
const globify = pattern => pattern . split ( '\\' ) . join ( '/' )
13
14
14
- const _logHandler = Symbol ( 'logHandler' )
15
- const _formatLogItem = Symbol ( 'formatLogItem' )
16
- const _getLogFilePath = Symbol ( 'getLogFilePath' )
17
- const _openLogFile = Symbol ( 'openLogFile' )
18
- const _cleanLogs = Symbol ( 'cleanlogs' )
19
- const _endStream = Symbol ( 'endStream' )
20
- const _isBuffered = Symbol ( 'isBuffered' )
21
-
22
15
class LogFiles {
23
16
// If we write multiple log files we want them all to have the same
24
17
// identifier for sorting and matching purposes
@@ -46,19 +39,16 @@ class LogFiles {
46
39
#files = [ ]
47
40
48
41
constructor ( {
42
+ id = runId ( ) ,
49
43
maxLogsPerFile = 50_000 ,
50
44
maxFilesPerProcess = 5 ,
51
45
} = { } ) {
52
- this . #logId = LogFiles . logId ( new Date ( ) )
46
+ this . #logId = id
53
47
this . #MAX_LOGS_PER_FILE = maxLogsPerFile
54
48
this . #MAX_FILES_PER_PROCESS = maxFilesPerProcess
55
49
this . on ( )
56
50
}
57
51
58
- static logId ( d ) {
59
- return d . toISOString ( ) . replace ( / [ . : ] / g, '_' )
60
- }
61
-
62
52
static format ( count , level , title , ...args ) {
63
53
let prefix = `${ count } ${ level } `
64
54
if ( title ) {
@@ -75,12 +65,12 @@ class LogFiles {
75
65
76
66
on ( ) {
77
67
this . #logStream = new MiniPass ( )
78
- process . on ( 'log' , this [ _logHandler ] )
68
+ process . on ( 'log' , this . #logHandler )
79
69
}
80
70
81
71
off ( ) {
82
- process . off ( 'log' , this [ _logHandler ] )
83
- this [ _endStream ] ( )
72
+ process . off ( 'log' , this . #logHandler )
73
+ this . #endStream ( )
84
74
}
85
75
86
76
load ( { dir, logsMax = Infinity } = { } ) {
@@ -100,7 +90,7 @@ class LogFiles {
100
90
// set that as the new log logstream for future writes
101
91
// if logs max is 0 then the user does not want a log file
102
92
if ( this . #logsMax > 0 ) {
103
- const initialFile = this [ _openLogFile ] ( )
93
+ const initialFile = this . #openLogFile ( )
104
94
if ( initialFile ) {
105
95
this . #logStream = this . #logStream. pipe ( initialFile )
106
96
}
@@ -109,29 +99,29 @@ class LogFiles {
109
99
// Kickoff cleaning process, even if we aren't writing a logfile.
110
100
// This is async but it will always ignore the current logfile
111
101
// Return the result so it can be awaited in tests
112
- return this [ _cleanLogs ] ( )
102
+ return this . #cleanLogs ( )
113
103
}
114
104
115
105
log ( ...args ) {
116
- this [ _logHandler ] ( ...args )
106
+ this . #logHandler ( ...args )
117
107
}
118
108
119
109
get files ( ) {
120
110
return this . #files
121
111
}
122
112
123
- get [ _isBuffered ] ( ) {
113
+ get #isBuffered ( ) {
124
114
return this . #logStream instanceof MiniPass
125
115
}
126
116
127
- [ _endStream ] ( output ) {
117
+ #endStream ( output ) {
128
118
if ( this . #logStream) {
129
119
this . #logStream. end ( output )
130
120
this . #logStream = null
131
121
}
132
122
}
133
123
134
- [ _logHandler ] = ( level , ...args ) => {
124
+ #logHandler = ( level , ...args ) => {
135
125
// Ignore pause and resume events since we
136
126
// write everything to the log file
137
127
if ( level === 'pause' || level === 'resume' ) {
@@ -143,9 +133,9 @@ class LogFiles {
143
133
return
144
134
}
145
135
146
- const logOutput = this [ _formatLogItem ] ( level , ...args )
136
+ const logOutput = this . #formatLogItem ( level , ...args )
147
137
148
- if ( this [ _isBuffered ] ) {
138
+ if ( this . #isBuffered ) {
149
139
// Cant do anything but buffer the output if we dont
150
140
// have a file stream yet
151
141
this . #logStream. write ( logOutput )
@@ -155,29 +145,29 @@ class LogFiles {
155
145
// Open a new log file if we've written too many logs to this one
156
146
if ( this . #fileLogCount >= this . #MAX_LOGS_PER_FILE) {
157
147
// Write last chunk to the file and close it
158
- this [ _endStream ] ( logOutput )
148
+ this . #endStream ( logOutput )
159
149
if ( this . #files. length >= this . #MAX_FILES_PER_PROCESS) {
160
150
// but if its way too many then we just stop listening
161
151
this . off ( )
162
152
} else {
163
153
// otherwise we are ready for a new file for the next event
164
- this . #logStream = this [ _openLogFile ] ( )
154
+ this . #logStream = this . #openLogFile ( )
165
155
}
166
156
} else {
167
157
this . #logStream. write ( logOutput )
168
158
}
169
159
}
170
160
171
- [ _formatLogItem ] ( ...args ) {
161
+ #formatLogItem ( ...args ) {
172
162
this . #fileLogCount += 1
173
163
return LogFiles . format ( this . #totalLogCount++ , ...args )
174
164
}
175
165
176
- [ _getLogFilePath ] ( count = '' ) {
166
+ #getLogFilePath ( count = '' ) {
177
167
return path . resolve ( this . #dir, `${ this . #logId} -debug-${ count } .log` )
178
168
}
179
169
180
- [ _openLogFile ] ( ) {
170
+ #openLogFile ( ) {
181
171
// Count in filename will be 0 indexed
182
172
const count = this . #files. length
183
173
@@ -186,7 +176,7 @@ class LogFiles {
186
176
// We never want to write files ending in `-9.log` and `-10.log` because
187
177
// log file cleaning is done by deleting the oldest so in this example
188
178
// `-10.log` would be deleted next
189
- const f = this [ _getLogFilePath ] ( padZero ( count , this . #MAX_FILES_PER_PROCESS) )
179
+ const f = this . #getLogFilePath ( padZero ( count , this . #MAX_FILES_PER_PROCESS) )
190
180
// Some effort was made to make the async, but we need to write logs
191
181
// during process.on('exit') which has to be synchronous. So in order
192
182
// to never drop log messages, it is easiest to make it sync all the time
@@ -210,15 +200,15 @@ class LogFiles {
210
200
}
211
201
}
212
202
213
- async [ _cleanLogs ] ( ) {
203
+ async #cleanLogs ( ) {
214
204
// module to clean out the old log files
215
205
// this is a best-effort attempt. if a rm fails, we just
216
206
// log a message about it and move on. We do return a
217
207
// Promise that succeeds when we've tried to delete everything,
218
208
// just for the benefit of testing this function properly.
219
209
220
210
try {
221
- const logPath = this [ _getLogFilePath ] ( )
211
+ const logPath = this . #getLogFilePath ( )
222
212
const logGlob = path . join ( path . dirname ( logPath ) , path . basename ( logPath )
223
213
// tell glob to only match digits
224
214
. replace ( / \d / g, '[0123456789]' )
0 commit comments