Skip to content

Commit 6512112

Browse files
committed
fix: use proc-log for all timers
1 parent 7678a3d commit 6512112

File tree

16 files changed

+194
-243
lines changed

16 files changed

+194
-243
lines changed

lib/commands/ci.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const reifyFinish = require('../utils/reify-finish.js')
22
const runScript = require('@npmcli/run-script')
33
const fs = require('fs/promises')
4-
const { log } = require('proc-log')
4+
const { log, time } = require('proc-log')
55
const validateLockfile = require('../utils/validate-lockfile.js')
66

77
const ArboristWorkspaceCmd = require('../arborist-cmd.js')
@@ -79,7 +79,7 @@ class CI extends ArboristWorkspaceCmd {
7979
if (!dryRun) {
8080
// Only remove node_modules after we've successfully loaded the virtual
8181
// tree and validated the lockfile
82-
await this.npm.time('npm-ci:rm', async () => {
82+
await time.start('npm-ci:rm', async () => {
8383
const path = `${where}/node_modules`
8484
// get the list of entries so we can skip the glob for performance
8585
const entries = await fs.readdir(path, null).catch(er => [])

lib/npm.js

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const usage = require('./utils/npm-usage.js')
1111
const LogFile = require('./utils/log-file.js')
1212
const Timers = require('./utils/timers.js')
1313
const Display = require('./utils/display.js')
14-
const { log } = require('proc-log')
14+
const { log, time } = require('proc-log')
1515
const { redactLog: replaceInfo } = require('@npmcli/redact')
1616
const updateNotifier = require('./utils/update-notifier.js')
1717
const pkg = require('../package.json')
@@ -110,7 +110,7 @@ class Npm {
110110
async exec (cmd, args = this.argv) {
111111
const command = this.setCmd(cmd)
112112

113-
const timeEnd = this.time(`command:${cmd}`)
113+
const timeEnd = time.start(`command:${cmd}`)
114114

115115
// this is async but we dont await it, since its ok if it doesnt
116116
// finish before the command finishes running. it uses command and argv
@@ -137,7 +137,7 @@ class Npm {
137137

138138
async load () {
139139
if (!this.#loadPromise) {
140-
this.#loadPromise = this.time('npm:load', () => this.#load().catch((er) => {
140+
this.#loadPromise = time.start('npm:load', () => this.#load().catch((er) => {
141141
this.loadErr = er
142142
throw er
143143
}))
@@ -158,10 +158,6 @@ class Npm {
158158
this.#logFile.off()
159159
}
160160

161-
time (name, fn) {
162-
return this.#timers.time(name, fn)
163-
}
164-
165161
writeTimingFile () {
166162
this.#timers.writeFile({
167163
id: this.#runId,
@@ -181,7 +177,7 @@ class Npm {
181177
}
182178

183179
async #load () {
184-
await this.time('npm:load:whichnode', async () => {
180+
await time.start('npm:load:whichnode', async () => {
185181
// TODO should we throw here?
186182
const node = await which(process.argv[0]).catch(() => {})
187183
if (node && node.toUpperCase() !== process.execPath.toUpperCase()) {
@@ -191,7 +187,7 @@ class Npm {
191187
}
192188
})
193189

194-
await this.time('npm:load:configload', () => this.config.load())
190+
await time.start('npm:load:configload', () => this.config.load())
195191

196192
// get createSupportsColor from chalk directly if this lands
197193
// https://github.com/chalk/chalk/pull/600
@@ -211,21 +207,21 @@ class Npm {
211207
// a different location. if this fails, then we don't have
212208
// a cache dir, but we don't want to fail immediately since
213209
// the command might not need a cache dir (like `npm --version`)
214-
await this.time('npm:load:mkdirpcache', () =>
210+
await time.start('npm:load:mkdirpcache', () =>
215211
fs.mkdir(this.cache, { recursive: true })
216212
.catch((e) => log.verbose('cache', `could not create cache: ${e}`)))
217213

218214
// it's ok if this fails. user might have specified an invalid dir
219215
// which we will tell them about at the end
220216
if (this.config.get('logs-max') > 0) {
221-
await this.time('npm:load:mkdirplogs', () =>
217+
await time.start('npm:load:mkdirplogs', () =>
222218
fs.mkdir(this.logsDir, { recursive: true })
223219
.catch((e) => log.verbose('logfile', `could not create logs-dir: ${e}`)))
224220
}
225221

226222
// note: this MUST be shorter than the actual argv length, because it
227223
// uses the same memory, so node will truncate it if it's too long.
228-
this.time('npm:load:setTitle', () => {
224+
time.start('npm:load:setTitle', () => {
229225
const { parsedArgv: { cooked, remain } } = this.config
230226
this.argv = remain
231227
// Secrets are mostly in configs, so title is set using only the positional args
@@ -241,7 +237,7 @@ class Npm {
241237
log.verbose('argv', this.#argvClean.map(JSON.stringify).join(' '))
242238
})
243239

244-
this.time('npm:load:display', () => {
240+
time.start('npm:load:display', () => {
245241
this.#display.load({
246242
loglevel: this.config.get('loglevel'),
247243
// TODO: only pass in logColor and color and create chalk instances
@@ -260,21 +256,21 @@ class Npm {
260256
process.env.COLOR = this.color ? '1' : '0'
261257
})
262258

263-
this.time('npm:load:logFile', () => {
259+
time.start('npm:load:logFile', () => {
264260
this.#logFile.load({
265261
path: this.logPath,
266262
logsMax: this.config.get('logs-max'),
267263
})
268264
log.verbose('logfile', this.#logFile.files[0] || 'no logfile created')
269265
})
270266

271-
this.time('npm:load:timers', () =>
267+
time.start('npm:load:timers', () =>
272268
this.#timers.load({
273269
path: this.config.get('timing') ? this.logPath : null,
274270
})
275271
)
276272

277-
this.time('npm:load:configScope', () => {
273+
time.start('npm:load:configScope', () => {
278274
const configScope = this.config.get('scope')
279275
if (configScope && !/^@/.test(configScope)) {
280276
this.config.set('scope', `@${configScope}`, this.config.find('scope'))

lib/utils/exit-handler.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const os = require('os')
22
const fs = require('fs')
3-
const { log, output } = require('proc-log')
3+
const { log, output, time } = require('proc-log')
44
const errorMessage = require('./error-message.js')
55
const { redactLog: replaceInfo } = require('@npmcli/redact')
66

@@ -11,14 +11,14 @@ let showLogFileError = false
1111
process.on('exit', code => {
1212
// process.emit is synchronous, so the timeEnd handler will run before the
1313
// unfinished timer check below
14-
process.emit('timeEnd', 'npm')
14+
time.end('npm')
1515

1616
const hasLoadedNpm = npm?.config.loaded
1717

1818
// Unfinished timers can be read before config load
1919
if (npm) {
2020
for (const [name, timer] of npm.unfinishedTimers) {
21-
log.verbose('unfinished npm timer', name, timer)
21+
log.silly('unfinished npm timer', name, timer)
2222
}
2323
}
2424

lib/utils/timers.js

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const EE = require('events')
22
const fs = require('fs')
3-
const { log } = require('proc-log')
3+
const { log, time } = require('proc-log')
44

55
const INITIAL_TIMER = 'npm'
66

@@ -13,7 +13,7 @@ class Timers extends EE {
1313
constructor () {
1414
super()
1515
this.on()
16-
process.emit('time', INITIAL_TIMER)
16+
time.start(INITIAL_TIMER)
1717
this.started = this.#unfinished.get(INITIAL_TIMER)
1818
}
1919

@@ -26,23 +26,11 @@ class Timers extends EE {
2626
}
2727

2828
on () {
29-
process.on('time', this.#timeListener)
30-
process.on('timeEnd', this.#timeEndListener)
29+
process.on('time', this.#timeHandler)
3130
}
3231

3332
off () {
34-
process.off('time', this.#timeListener)
35-
process.off('timeEnd', this.#timeEndListener)
36-
}
37-
38-
time (name, fn) {
39-
process.emit('time', name)
40-
const end = () => process.emit('timeEnd', name)
41-
if (typeof fn === 'function') {
42-
const res = fn()
43-
return res && res.finally ? res.finally(end) : (end(), res)
44-
}
45-
return end
33+
process.off('time', this.#timeHandler)
4634
}
4735

4836
load ({ path } = {}) {
@@ -75,18 +63,22 @@ class Timers extends EE {
7563
}
7664
}
7765

78-
#timeListener = (name) => {
79-
this.#unfinished.set(name, Date.now())
80-
}
81-
82-
#timeEndListener = (name) => {
83-
if (this.#unfinished.has(name)) {
84-
const ms = Date.now() - this.#unfinished.get(name)
85-
this.#finished[name] = ms
86-
this.#unfinished.delete(name)
87-
log.timing(name, `Completed in ${ms}ms`)
88-
} else {
89-
log.silly('timing', "Tried to end timer that doesn't exist:", name)
66+
#timeHandler = (level, name) => {
67+
const now = Date.now()
68+
switch (level) {
69+
case time.KEYS.start:
70+
this.#unfinished.set(name, now)
71+
break
72+
case time.KEYS.end: {
73+
if (this.#unfinished.has(name)) {
74+
const ms = now - this.#unfinished.get(name)
75+
this.#finished[name] = ms
76+
this.#unfinished.delete(name)
77+
log.timing(name, `Completed in ${ms}ms`)
78+
} else {
79+
log.silly('timing', "Tried to end timer that doesn't exist:", name)
80+
}
81+
}
9082
}
9183
}
9284
}

test/lib/npm.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const t = require('tap')
22
const { resolve, dirname, join } = require('path')
33
const fs = require('fs')
4+
const { time } = require('proc-log')
45
const { load: loadMockNpm } = require('../fixtures/mock-npm.js')
56
const mockGlobals = require('@npmcli/mock-globals')
67
const { commands } = require('../../lib/utils/cmd-list.js')
@@ -398,15 +399,15 @@ t.test('timings', async t => {
398399
timing: true,
399400
},
400401
})
401-
process.emit('time', 'foo')
402-
process.emit('time', 'bar')
402+
time.start('foo')
403+
time.start('bar')
403404
t.match(npm.unfinishedTimers.get('foo'), Number, 'foo timer is a number')
404405
t.match(npm.unfinishedTimers.get('bar'), Number, 'foo timer is a number')
405-
process.emit('timeEnd', 'foo')
406-
process.emit('timeEnd', 'bar')
407-
process.emit('timeEnd', 'baz')
406+
time.end('foo')
407+
time.end('bar')
408+
time.end('baz')
408409
// npm timer is started by default
409-
process.emit('timeEnd', 'npm')
410+
time.end('npm')
410411
t.match(logs.timing.byTitle('foo'), [
411412
/Completed in [0-9]+ms/,
412413
])
@@ -428,9 +429,9 @@ t.test('timings', async t => {
428429
const { npm, cache, timingFile } = await loadMockNpm(t, {
429430
config: { timing: true },
430431
})
431-
process.emit('time', 'foo')
432-
process.emit('timeEnd', 'foo')
433-
process.emit('time', 'bar')
432+
time.start('foo')
433+
time.end('foo')
434+
time.start('bar')
434435
npm.writeTimingFile()
435436
t.match(npm.timingFile, cache)
436437
t.match(npm.timingFile, /-timing.json$/)

test/lib/utils/exit-handler.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const fs = require('fs')
33
const fsMiniPass = require('fs-minipass')
44
const { join, resolve } = require('path')
55
const EventEmitter = require('events')
6-
const { output } = require('proc-log')
6+
const { output, time } = require('proc-log')
77
const { load: loadMockNpm } = require('../../fixtures/mock-npm')
88
const mockGlobals = require('@npmcli/mock-globals')
99
const { cleanCwd, cleanDate } = require('../../fixtures/clean-snapshot')
@@ -517,8 +517,8 @@ t.test('unfinished timers', async (t) => {
517517
config: { timing: true },
518518
})
519519

520-
process.emit('time', 'foo')
521-
process.emit('time', 'bar')
520+
time.start('foo')
521+
time.start('bar')
522522

523523
await exitHandler()
524524
const timingFileData = await timingFile()

test/lib/utils/timers.js

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const t = require('tap')
22
const { resolve, join } = require('path')
33
const fs = require('graceful-fs')
4-
const { log } = require('proc-log')
4+
const { log, time } = require('proc-log')
55
const tmock = require('../../fixtures/tmock')
66

77
const mockTimers = (t, options) => {
@@ -24,57 +24,46 @@ const mockTimers = (t, options) => {
2424

2525
t.test('listens/stops on process', async (t) => {
2626
const { timers } = mockTimers(t)
27-
process.emit('time', 'foo')
28-
process.emit('time', 'bar')
29-
process.emit('timeEnd', 'bar')
27+
time.start('foo')
28+
time.start('bar')
29+
time.end('bar')
3030
t.match(timers.unfinished, new Map([['foo', Number]]))
3131
t.match(timers.finished, { bar: Number })
3232
timers.off()
33-
process.emit('time', 'baz')
33+
time.start('baz')
3434
t.notOk(timers.unfinished.get('baz'))
3535
})
3636

37-
t.test('convenience time method', async (t) => {
38-
const { timers } = mockTimers(t)
39-
40-
const end = timers.time('later')
41-
timers.time('sync', () => {})
42-
await timers.time('async', () => new Promise(r => setTimeout(r, 10)))
43-
end()
44-
45-
t.match(timers.finished, { later: Number, sync: Number, async: Number })
46-
})
47-
4837
t.test('initial timer is named npm', async (t) => {
4938
const { timers } = mockTimers(t)
50-
process.emit('timeEnd', 'npm')
39+
time.end('npm')
5140
t.match(timers.finished, { npm: Number })
5241
})
5342

5443
t.test('logs timing events', async (t) => {
5544
const events = []
5645
const listener = (...args) => events.push(args)
5746
const { timers, logs } = mockTimers(t, { listener })
58-
process.emit('time', 'foo')
59-
process.emit('time', 'bar')
60-
process.emit('timeEnd', 'bar')
47+
time.start('foo')
48+
time.start('bar')
49+
time.end('bar')
6150
timers.off(listener)
62-
process.emit('timeEnd', 'foo')
51+
time.end('foo')
6352
t.equal(logs.timing.length, 1)
6453
t.match(logs.timing[0], /^bar Completed in [0-9]ms/)
6554
})
6655

6756
t.test('finish unstarted timer', async (t) => {
6857
const { logs } = mockTimers(t)
69-
process.emit('timeEnd', 'foo')
58+
time.end('foo')
7059
t.match(logs.silly, ["timing Tried to end timer that doesn't exist: foo"])
7160
})
7261

7362
t.test('writes file', async (t) => {
7463
const { timers } = mockTimers(t)
7564
const dir = t.testdir()
76-
process.emit('time', 'foo')
77-
process.emit('timeEnd', 'foo')
65+
time.start('foo')
66+
time.end('foo')
7867
timers.load({ path: resolve(dir, `TIMING_FILE-`) })
7968
timers.writeFile({ some: 'data' })
8069
const data = JSON.parse(fs.readFileSync(resolve(dir, 'TIMING_FILE-timing.json')))

0 commit comments

Comments
 (0)