-
-
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
46
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
46 commits
Select commit
Hold shift + click to select a range
afd452c
lib: added logger api in node core
mertcanaltin ca93100
fix: validate log level in LogConsumer.enabled method
mertcanaltin 2ce155f
fix: improve error serialization check in serializeErr function
mertcanaltin 8d06114
fix: update error serialization check and improve log level validation
mertcanaltin 6135300
fix: replace ErrorIsError with isNativeError for better error seriali…
mertcanaltin a846c4d
fix: remove unused Error import in logger.js
mertcanaltin 1683f9c
fix: update logger module imports to use 'node:logger' for consistency
mertcanaltin ea9afcb
fix: remove unused spawnSyncAndAssert import in test-require-module-t…
mertcanaltin 54a02d3
fix: add missing commas in spawnSync options for consistency
mertcanaltin f9214af
fix: update consumer end method to use callback for asynchronous log …
mertcanaltin 87df951
fix: remove log file empty assertion message for clarity
mertcanaltin 8816f19
fix: refactor test assertions to use common.mustSucceed for consistency
mertcanaltin 92a3108
docs: add LogConsumer class and enabled method documentation
mertcanaltin ea72e34
Update lib/internal/logger/serializers.js
mertcanaltin c859729
Update lib/internal/logger/serializers.js
mertcanaltin 8a43c23
Update lib/internal/logger/serializers.js
mertcanaltin bff1b52
Update lib/logger.js
mertcanaltin 7a8a90f
Update lib/logger.js
mertcanaltin d0b944b
Update lib/logger.js
mertcanaltin 2cf5532
Enhance JSDoc comments for serializers and logger methods
mertcanaltin 9dc3dbf
Refactor JSDoc for HTTP request serializer and remove unused error code
mertcanaltin bd4cdb5
add benchmark utility for isNativeError function
mertcanaltin 2bbda05
Remove bytes submodule from commit
mertcanaltin 680e443
Remove isNativeError benchmark utility
mertcanaltin 3260825
enhance logger and serializers: improve error serialization and refac…
mertcanaltin 565faac
add logger types to custom types map
mertcanaltin fe6c48d
add enabled property to logger methods for performance checks
mertcanaltin eb44686
update doc
mertcanaltin 863c2a6
dead code delete
mertcanaltin 36c05a9
ditto delete
mertcanaltin c1decc6
remove redundant parameter documentation from Logger methods
mertcanaltin d2fed43
added rfc5424
mertcanaltin e398469
used template literal
mertcanaltin 163fa75
Update lib/logger.js
mertcanaltin 108a2c4
Update doc/api/logger.md
mertcanaltin 659b04c
add experimental logger module support
mertcanaltin cfb6a61
add benchmark utility for isNativeError function
mertcanaltin 9ca6d31
Remove bytes submodule from commit
mertcanaltin 8f7bfdd
Remove isNativeError benchmark utility
mertcanaltin 4d432c5
added experimental flag for tests
mertcanaltin 94d24a2
used node:test
mertcanaltin 31a3a70
refactor logger initialization in benchmark tests to use new Logger c…
mertcanaltin 14205c6
refactor logger documentation for clarity and consistency
mertcanaltin b53d408
implemented serialize symbol
mertcanaltin 2aee9d0
add experimental logger module and update related tests
mertcanaltin e14b0bb
added experimental for structured logging
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.