GeezerVison is showing github.com — lib: support dynamic trace events on debugWithTimer · nodejs/node@744df0b
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: lib/internal/util/debuglog.js +42-16Lines changed: 42 additions & 16 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -20,7 +20,7 @@ const { | 20 | 20 | CHAR_LOWERCASE_N: kTraceInstant, | 21 | 21 | } = require('internal/constants'); | 22 | 22 | const { inspect, format, formatWithOptions } = require('internal/util/inspect'); | 23 | | -const { isTraceCategoryEnabled, trace } = internalBinding('trace_events'); | | 23 | +const { getCategoryEnabledBuffer, trace } = internalBinding('trace_events'); | 24 | 24 |
| 25 | 25 | // `debugImpls` and `testEnabled` are deliberately not initialized so any call | 26 | 26 | // to `debuglog()` before `initializeDebugEnv()` is called will throw. | @@ -372,18 +372,34 @@ function debugWithTimer(set, cb) { | 372 | 372 | ); | 373 | 373 | } | 374 | 374 |
| 375 | | - const kTraceCategory = `node,node.${StringPrototypeToLowerCase(set)}`; | | 375 | + const traceCategory = `node,node.${StringPrototypeToLowerCase(set)}`; | | 376 | + let traceCategoryBuffer; | 376 | 377 | let debugLogCategoryEnabled = false; | 377 | | - let traceCategoryEnabled = false; | 378 | 378 | let timerFlags = kNone; | 379 | 379 |
| | 380 | + const skipAll = kSkipLog | kSkipTrace; | | 381 | + | | 382 | + function ensureTimerFlagsAreUpdated() { | | 383 | + timerFlags &= ~kSkipTrace; | | 384 | + | | 385 | + if (traceCategoryBuffer[0] === 0) { | | 386 | + timerFlags |= kSkipTrace; | | 387 | + } | | 388 | + } | | 389 | + | 380 | 390 | /** | 381 | 391 | * @type {TimerStart} | 382 | 392 | */ | 383 | 393 | function internalStartTimer(logLabel, traceLabel) { | | 394 | + ensureTimerFlagsAreUpdated(); | | 395 | + | | 396 | + if (timerFlags === skipAll) { | | 397 | + return; | | 398 | + } | | 399 | + | 384 | 400 | time( | 385 | 401 | tracesStores[set], | 386 | | - kTraceCategory, | | 402 | + traceCategory, | 387 | 403 | 'debuglog.time', | 388 | 404 | timerFlags, | 389 | 405 | logLabel, | @@ -395,9 +411,15 @@ function debugWithTimer(set, cb) { | 395 | 411 | * @type {TimerEnd} | 396 | 412 | */ | 397 | 413 | function internalEndTimer(logLabel, traceLabel) { | | 414 | + ensureTimerFlagsAreUpdated(); | | 415 | + | | 416 | + if (timerFlags === skipAll) { | | 417 | + return; | | 418 | + } | | 419 | + | 398 | 420 | timeEnd( | 399 | 421 | tracesStores[set], | 400 | | - kTraceCategory, | | 422 | + traceCategory, | 401 | 423 | 'debuglog.timeEnd', | 402 | 424 | timerFlags, | 403 | 425 | logImpl, | @@ -410,9 +432,15 @@ function debugWithTimer(set, cb) { | 410 | 432 | * @type {TimerLog} | 411 | 433 | */ | 412 | 434 | function internalLogTimer(logLabel, traceLabel, args) { | | 435 | + ensureTimerFlagsAreUpdated(); | | 436 | + | | 437 | + if (timerFlags === skipAll) { | | 438 | + return; | | 439 | + } | | 440 | + | 413 | 441 | timeLog( | 414 | 442 | tracesStores[set], | 415 | | - kTraceCategory, | | 443 | + traceCategory, | 416 | 444 | 'debuglog.timeLog', | 417 | 445 | timerFlags, | 418 | 446 | logImpl, | @@ -428,21 +456,19 @@ function debugWithTimer(set, cb) { | 428 | 456 | } | 429 | 457 | emitWarningIfNeeded(set); | 430 | 458 | debugLogCategoryEnabled = testEnabled(set); | 431 | | - traceCategoryEnabled = isTraceCategoryEnabled(kTraceCategory); | | 459 | + traceCategoryBuffer = getCategoryEnabledBuffer(traceCategory); | | 460 | + | | 461 | + timerFlags = kNone; | 432 | 462 |
| 433 | 463 | if (!debugLogCategoryEnabled) { | 434 | 464 | timerFlags |= kSkipLog; | 435 | 465 | } | 436 | 466 |
| 437 | | - if (!traceCategoryEnabled) { | | 467 | + if (traceCategoryBuffer[0] === 0) { | 438 | 468 | timerFlags |= kSkipTrace; | 439 | 469 | } | 440 | 470 |
| 441 | | - // TODO(H4ad): support traceCategory being enabled dynamically | 442 | | - if (debugLogCategoryEnabled || traceCategoryEnabled) | 443 | | - cb(internalStartTimer, internalEndTimer, internalLogTimer); | 444 | | - else | 445 | | - cb(noop, noop, noop); | | 471 | + cb(internalStartTimer, internalEndTimer, internalLogTimer); | 446 | 472 | } | 447 | 473 |
| 448 | 474 | /** | @@ -451,7 +477,7 @@ function debugWithTimer(set, cb) { | 451 | 477 | const startTimer = (logLabel, traceLabel) => { | 452 | 478 | init(); | 453 | 479 |
| 454 | | - if (debugLogCategoryEnabled || traceCategoryEnabled) | | 480 | + if (timerFlags !== skipAll) | 455 | 481 | internalStartTimer(logLabel, traceLabel); | 456 | 482 | }; | 457 | 483 |
| @@ -461,7 +487,7 @@ function debugWithTimer(set, cb) { | 461 | 487 | const endTimer = (logLabel, traceLabel) => { | 462 | 488 | init(); | 463 | 489 |
| 464 | | - if (debugLogCategoryEnabled || traceCategoryEnabled) | | 490 | + if (timerFlags !== skipAll) | 465 | 491 | internalEndTimer(logLabel, traceLabel); | 466 | 492 | }; | 467 | 493 |
| @@ -471,7 +497,7 @@ function debugWithTimer(set, cb) { | 471 | 497 | const logTimer = (logLabel, traceLabel, args) => { | 472 | 498 | init(); | 473 | 499 |
| 474 | | - if (debugLogCategoryEnabled || traceCategoryEnabled) | | 500 | + if (timerFlags !== skipAll) | 475 | 501 | internalLogTimer(logLabel, traceLabel, args); | 476 | 502 | }; | 477 | 503 |
| |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-module-print-timing.mjs +62-2Lines changed: 62 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -16,7 +16,7 @@ it('should print the timing information for cjs', () => { | 16 | 16 | }, | 17 | 17 | }, { | 18 | 18 | stdout: '', | 19 | | - stderr: (result) => result.includes('MODULE_TIMER'), | | 19 | + stderr: /MODULE_TIMER/g, | 20 | 20 | }); | 21 | 21 |
| 22 | 22 | const firstLine = result.stderr.split('\n').find((line) => line.includes('[url]')); | @@ -74,7 +74,7 @@ it('should write tracing & print logs for cjs', async () => { | 74 | 74 | }, | 75 | 75 | }, { | 76 | 76 | stdout: '', | 77 | | - stderr: (result) => result.includes('MODULE_TIMER'), | | 77 | + stderr: /MODULE_TIMER/g, | 78 | 78 | }); | 79 | 79 |
| 80 | 80 | const firstLine = result.stderr.split('\n').find((line) => line.includes('[url]')); | @@ -89,7 +89,67 @@ it('should write tracing & print logs for cjs', async () => { | 89 | 89 | const outputFileJson = JSON.parse(outputFileContent).traceEvents; | 90 | 90 | const urlTraces = outputFileJson.filter((trace) => trace.name === "require('url')"); | 91 | 91 |
| | 92 | + assert.ok(urlTraces.length > 0, 'Not found url traces'); | | 93 | + | 92 | 94 | for (const trace of urlTraces) { | 93 | 95 | assert.strictEqual(trace.ph, expectedMimeTypes.shift()); | 94 | 96 | } | 95 | 97 | }); | | 98 | + | | 99 | +it('should support enable tracing dynamically', async () => { | | 100 | + try { | | 101 | + spawnSyncAndAssert(process.execPath, [ | | 102 | + '--eval', | | 103 | + 'require("trace_events")', | | 104 | + ], { | | 105 | + stdout: '', | | 106 | + stderr: '', | | 107 | + }); | | 108 | + } catch { | | 109 | + // Skip this test if the trace_events module is not available | | 110 | + return; | | 111 | + } | | 112 | + | | 113 | + | | 114 | + const outputFile = tmpdir.resolve('output-dynamic-trace.log'); | | 115 | + const jsScript = ` | | 116 | + const traceEvents = require("trace_events"); | | 117 | + const tracing = traceEvents.createTracing({ categories: ["node.module_timer"] }); | | 118 | +
| | 119 | + tracing.enable(); | | 120 | + require("http"); | | 121 | + tracing.disable(); | | 122 | +
| | 123 | + require("vm"); | | 124 | + `; | | 125 | + | | 126 | + spawnSyncAndAssert(process.execPath, [ | | 127 | + '--trace-event-file-pattern', | | 128 | + outputFile, | | 129 | + '--eval', | | 130 | + jsScript, | | 131 | + ], { | | 132 | + cwd: tmpdir.path, | | 133 | + env: { | | 134 | + ...process.env, | | 135 | + }, | | 136 | + }, { | | 137 | + stdout: '', | | 138 | + stderr: '', | | 139 | + }); | | 140 | + | | 141 | + const expectedMimeTypes = ['b', 'e']; | | 142 | + const outputFileContent = await readFile(outputFile, 'utf-8'); | | 143 | + | | 144 | + const outputFileJson = JSON.parse(outputFileContent).traceEvents; | | 145 | + const httpTraces = outputFileJson.filter((trace) => trace.name === "require('http')"); | | 146 | + | | 147 | + assert.ok(httpTraces.length > 0, 'Not found http traces'); | | 148 | + | | 149 | + for (const trace of httpTraces) { | | 150 | + assert.strictEqual(trace.ph, expectedMimeTypes.shift()); | | 151 | + } | | 152 | + | | 153 | + const vmTraces = outputFileJson.filter((trace) => trace.name === "require('vm')"); | | 154 | + assert.strictEqual(vmTraces.length, 0); | | 155 | +}); |
|