-
-
Notifications
You must be signed in to change notification settings - Fork 34.6k
[WIP] lib: added logger api in node core #60468
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
mertcanaltin
wants to merge
59
commits into
nodejs:main
Choose a base branch
from
mertcanaltin:mert/create-logger-api/node-core
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
59 commits
Select commit
Hold shift + click to select a range
447341e
lib: added logger api in node core
mertcanaltin 90c12b1
fix: validate log level in LogConsumer.enabled method
mertcanaltin 80d5556
fix: improve error serialization check in serializeErr function
mertcanaltin fc1b7f3
fix: update error serialization check and improve log level validation
mertcanaltin 76a6612
fix: replace ErrorIsError with isNativeError for better error seriali…
mertcanaltin f5b0dbe
fix: remove unused Error import in logger.js
mertcanaltin 8372347
fix: update logger module imports to use 'node:logger' for consistency
mertcanaltin 73186e7
fix: remove unused spawnSyncAndAssert import in test-require-module-t…
mertcanaltin d6a9d6a
fix: add missing commas in spawnSync options for consistency
mertcanaltin b0e6e1e
fix: update consumer end method to use callback for asynchronous log …
mertcanaltin 4dd5954
fix: remove log file empty assertion message for clarity
mertcanaltin d8535fb
fix: refactor test assertions to use common.mustSucceed for consistency
mertcanaltin 7745b7b
docs: add LogConsumer class and enabled method documentation
mertcanaltin a57c8e8
Update lib/internal/logger/serializers.js
mertcanaltin b20fa90
Update lib/internal/logger/serializers.js
mertcanaltin 70f2fcb
Update lib/internal/logger/serializers.js
mertcanaltin a1bf6f2
Update lib/logger.js
mertcanaltin ab8a344
Update lib/logger.js
mertcanaltin 3cbfa7d
Update lib/logger.js
mertcanaltin c06cb20
Enhance JSDoc comments for serializers and logger methods
mertcanaltin 75de15a
Refactor JSDoc for HTTP request serializer and remove unused error code
mertcanaltin fa27eb7
add benchmark utility for isNativeError function
mertcanaltin e1bc224
Remove bytes submodule from commit
mertcanaltin 598bdfb
Remove isNativeError benchmark utility
mertcanaltin 534c14a
enhance logger and serializers: improve error serialization and refac…
mertcanaltin 7fd6250
add logger types to custom types map
mertcanaltin a6eaf8d
add enabled property to logger methods for performance checks
mertcanaltin 79f85d7
update doc
mertcanaltin a4d99b1
dead code delete
mertcanaltin 36e530a
ditto delete
mertcanaltin f688d73
remove redundant parameter documentation from Logger methods
mertcanaltin 52709ef
added rfc5424
mertcanaltin f8b450e
used template literal
mertcanaltin a19b1aa
Update lib/logger.js
mertcanaltin f2c4e4c
Update doc/api/logger.md
mertcanaltin cab1e85
add experimental logger module support
mertcanaltin 5bc27ba
add benchmark utility for isNativeError function
mertcanaltin 10e7d4b
Remove bytes submodule from commit
mertcanaltin 23e78c8
Remove isNativeError benchmark utility
mertcanaltin ea4e3c7
added experimental flag for tests
mertcanaltin 219ac1e
used node:test
mertcanaltin 5883172
refactor logger initialization in benchmark tests to use new Logger c…
mertcanaltin fda687c
refactor logger documentation for clarity and consistency
mertcanaltin 912801b
implemented serialize symbol
mertcanaltin f579e91
add experimental logger module and update related tests
mertcanaltin 7200dd9
added experimental for structured logging
mertcanaltin 28b9b30
fix: update logger module imports to use 'node:logger' for consistency
mertcanaltin a07f953
add benchmark utility for isNativeError function
mertcanaltin 83e37fc
Remove bytes submodule from commit
mertcanaltin b52ec41
Remove isNativeError benchmark utility
mertcanaltin fc77736
add benchmark utility for isNativeError function
mertcanaltin 5a21c34
Remove bytes submodule from commit
mertcanaltin 4c0fa3e
Remove isNativeError benchmark utility
mertcanaltin ea8c753
add experimental logger module and update related tests
mertcanaltin a9371b1
used ObjectKeys
mertcanaltin 57f29b2
review fix
mertcanaltin 87e50d5
refactor(logger): update enabled checks to use property access for lo…
mertcanaltin d2ab9e1
refactor(logger): remove unused ObjectHasOwn import
mertcanaltin c142ab3
remove outdated reference to logger level enabled property
mertcanaltin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,174 @@ | ||
| 'use strict'; | ||
|
|
||
| const common = require('../common'); | ||
| const fs = require('node:fs'); | ||
|
|
||
| const bench = common.createBenchmark(main, { | ||
| n: [1e5], | ||
| scenario: [ | ||
| 'string-short', | ||
| 'string-long', | ||
| 'object-simple', | ||
| 'object-nested', | ||
| 'object-array', | ||
| 'object-mixed', | ||
| 'child-logger', | ||
| 'disabled-level', | ||
| 'error-object', | ||
| ], | ||
| }); | ||
|
|
||
| function main({ n, scenario }) { | ||
| const { Logger, JSONConsumer } = require('node:logger'); | ||
|
|
||
| const nullFd = fs.openSync('/dev/null', 'w'); | ||
| const consumer = new JSONConsumer({ stream: nullFd, level: 'info' }); | ||
| consumer.attach(); | ||
|
|
||
| const logger = new Logger({ level: 'info' }); | ||
|
|
||
| switch (scenario) { | ||
| case 'string-short': { | ||
| // Simple short string message | ||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| logger.info('hello'); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
|
|
||
| case 'string-long': { | ||
| // Long string message (100 chars) | ||
| const longMsg = 'This is a much longer log message that contains ' + | ||
| 'more text to serialize and process during logging operations'; | ||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| logger.info(longMsg); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
|
|
||
| case 'object-simple': { | ||
| // Object with msg and a few string fields | ||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| logger.info({ | ||
| msg: 'user action', | ||
| userId: 'user-123', | ||
| action: 'login', | ||
| }); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
|
|
||
| case 'object-nested': { | ||
| // Object with nested structure | ||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| logger.info({ | ||
| msg: 'request completed', | ||
| request: { | ||
| method: 'POST', | ||
| path: '/api/users', | ||
| headers: { | ||
| 'content-type': 'application/json', | ||
| 'user-agent': 'Mozilla/5.0', | ||
| }, | ||
| }, | ||
| response: { | ||
| statusCode: 200, | ||
| body: { success: true }, | ||
| }, | ||
| }); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
|
|
||
| case 'object-array': { | ||
| // Object with array fields | ||
| const tags = ['web', 'api', 'auth', 'production']; | ||
| const ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; | ||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| logger.info({ | ||
| msg: 'batch operation', | ||
| tags, | ||
| processedIds: ids, | ||
| results: ['success', 'success', 'failed', 'success'], | ||
| }); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
|
|
||
| case 'object-mixed': { | ||
| // Mixed types: strings, numbers, booleans, null | ||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| logger.info({ | ||
| msg: 'mixed data', | ||
| stringField: 'value', | ||
| numberField: 42, | ||
| floatField: 3.14159, | ||
| booleanField: true, | ||
| nullField: null, | ||
| timestamp: 1704067200000, | ||
| }); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
|
|
||
| case 'child-logger': { | ||
| // Child logger with pre-bound context | ||
| const childLogger = logger.child({ | ||
| service: 'api', | ||
| version: '1.0.0', | ||
| env: 'production', | ||
| }); | ||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| childLogger.info({ | ||
| msg: 'request', | ||
| requestId: 'req-123', | ||
| duration: 150, | ||
| }); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
|
|
||
| case 'disabled-level': { | ||
| // Logging at disabled level (debug when level is info) | ||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| logger.debug('this will be skipped'); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
|
|
||
| case 'error-object': { | ||
| // Logging with Error object | ||
| const error = new Error('Something went wrong'); | ||
| error.code = 'ERR_SOMETHING'; | ||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| logger.error({ | ||
| msg: 'operation failed', | ||
| err: error, | ||
| operation: 'database-query', | ||
| }); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| consumer.flushSync(); | ||
| fs.closeSync(nullFd); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| 'use strict'; | ||
|
|
||
| const common = require('../common'); | ||
| const fs = require('node:fs'); | ||
|
|
||
| const bench = common.createBenchmark(main, { | ||
| n: [1e5], | ||
| logger: ['node-logger', 'pino'], | ||
| scenario: ['simple', 'child', 'disabled', 'fields'], | ||
| }); | ||
|
|
||
| function main({ n, logger, scenario }) { | ||
| const nullFd = fs.openSync('/dev/null', 'w'); | ||
| let testLogger; | ||
| let consumer; | ||
|
|
||
| if (logger === 'node-logger') { | ||
| const { Logger, JSONConsumer } = require('node:logger'); | ||
|
|
||
| switch (scenario) { | ||
| case 'simple': { | ||
| consumer = new JSONConsumer({ stream: nullFd, level: 'info' }); | ||
| consumer.attach(); | ||
| testLogger = new Logger({ level: 'info' }); | ||
|
|
||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| testLogger.info('benchmark test message'); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
|
|
||
| case 'child': { | ||
| consumer = new JSONConsumer({ stream: nullFd, level: 'info' }); | ||
| consumer.attach(); | ||
| const baseLogger = new Logger({ level: 'info' }); | ||
| testLogger = baseLogger.child({ requestId: 'req-123', userId: 456 }); | ||
|
|
||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| testLogger.info('benchmark test message'); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
|
|
||
| case 'disabled': { | ||
| consumer = new JSONConsumer({ stream: nullFd, level: 'warn' }); | ||
| consumer.attach(); | ||
| testLogger = new Logger({ level: 'warn' }); | ||
|
|
||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| testLogger.debug('benchmark test message'); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
|
|
||
| case 'fields': { | ||
| consumer = new JSONConsumer({ stream: nullFd, level: 'info' }); | ||
| consumer.attach(); | ||
| testLogger = new Logger({ level: 'info' }); | ||
|
|
||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| testLogger.info('benchmark test message', { | ||
| field1: 'value1', | ||
| field2: 'value2', | ||
| field3: 'value3', | ||
| field4: 'value4', | ||
| field5: 'value5', | ||
| }); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| if (consumer) { | ||
| consumer.flushSync(); | ||
| } | ||
| fs.closeSync(nullFd); | ||
|
|
||
| } else if (logger === 'pino') { | ||
| const pino = require('pino'); | ||
| const destination = pino.destination({ dest: nullFd, sync: false }); | ||
|
|
||
| switch (scenario) { | ||
| case 'simple': { | ||
| testLogger = pino({ level: 'info' }, destination); | ||
|
|
||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| testLogger.info('benchmark test message'); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
|
|
||
| case 'child': { | ||
| const baseLogger = pino({ level: 'info' }, destination); | ||
| testLogger = baseLogger.child({ requestId: 'req-123', userId: 456 }); | ||
|
|
||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| testLogger.info('benchmark test message'); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
|
|
||
| case 'disabled': { | ||
| testLogger = pino({ level: 'warn' }, destination); | ||
|
|
||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| testLogger.debug('benchmark test message'); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
|
|
||
| case 'fields': { | ||
| testLogger = pino({ level: 'info' }, destination); | ||
|
|
||
| bench.start(); | ||
| for (let i = 0; i < n; i++) { | ||
| testLogger.info({ | ||
| msg: 'benchmark test message', | ||
| field1: 'value1', | ||
| field2: 'value2', | ||
| field3: 'value3', | ||
| field4: 'value4', | ||
| field5: 'value5', | ||
| }); | ||
| } | ||
| bench.end(n); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| destination.flushSync(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These object benchmarks would also be measuring the construction time of each object constructed within each loop iteration. Not sure if we care about that for this benchmark, but figured it was worth pointing out.