lib: added logger api in node core#60468
Conversation
|
Review requested:
|
|
thats my first performance results: I think need improvement for child logger area, but ı'm so happy because other results it looks nice. node:logger vs pino ➜ node git:(mert/create-logger-api/node-core) ✗ ./node benchmark/logger/vs-pino.js n=100000
logger/vs-pino.js scenario="simple" logger="node-logger" n=100000: 5,240,540.823813018
logger/vs-pino.js scenario="child" logger="node-logger" n=100000: 2,635,847.7027229806
logger/vs-pino.js scenario="disabled" logger="node-logger" n=100000: 159,436,487.67795104
logger/vs-pino.js scenario="fields" logger="node-logger" n=100000: 3,619,336.304205216
logger/vs-pino.js scenario="simple" logger="pino" n=100000: 3,398,489.9761368227
logger/vs-pino.js scenario="child" logger="pino" n=100000: 4,489,799.803418606
logger/vs-pino.js scenario="disabled" logger="pino" n=100000: 119,772,384.56038144
logger/vs-pino.js scenario="fields" logger="pino" n=100000: 1,257,930.8609750536 |
|
I now learn this feat in Pino I will try add in node:logger |
|
This will require support for serializers |
I wonder, should we name them like Pino does (built-in serializers), or go with something like standardSerializers ? |
Follow pino and we’ll change it |
I tryed serializer implement for logger, and some bench result repaired and fields and simple are experiencing a decline; I will try to resolve these fields: 3.62M → 2.16M (-40%) previously, the results for the child logger were quite slow at around 70%, but the new results have dropped to 18% and have actually improved significantly. I continue to try new methods. |
I inspected pino and I learn some patterns, than I applied this commit and new results! 1ededc7 I used this patterns removed the cost of serializing bindings in each log for the child logger, simple: 6.06M vs 3.48M ops/s (+74% faster) |
|
hello @mcollina do you any comments or suggestions for this end commits, I'm curious 🙏 . |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #60468 +/- ##
==========================================
+ Coverage 89.73% 89.75% +0.02%
==========================================
Files 676 678 +2
Lines 206069 206715 +646
Branches 39517 39605 +88
==========================================
+ Hits 184909 185531 +622
- Misses 13310 13330 +20
- Partials 7850 7854 +4
🚀 New features to boost your workflow:
|
f5b0108 to
429359b
Compare
|
@RafaelGSS please take a look. 7 days passed since your review has been requested. |
It's a 2.5k lines PR, it's hard to concilate time to review it properly. |
The design is inspired by pino but intentionally minimal the diagnostics_channel consumer model is different from pino's streaming architecture. It's not a copy, it's a reimplementation of the same ideas adapted to Node.js internals Core code must use primordials and internal APIs pino is written for userland. Using it directly in core would require either patching it or losing the prototype pollution protection that I'll also add the missing test coverage for the uncovered, Happy to hear @mcollina and @jsumners thoughts on the vendoring question, Btw I edited your suggestion @RafaelGSS , thanks for reviews |
Both statements are incorrect. Core code doesn't must use primordials, and |
5bc71ae to
5d2e1ef
Compare
You're right, primordials aren't strictly required, I should have said they're a common convention in core modules rather than a hard requirement. The main reason for reimplementing rather than vendoring is the architectural difference: node:logger uses The current implementation also outperforms pino in benchmarks:
This is largely possible because of the |
6dcd89d to
f7ef124
Compare
|
On vedoring pino in core: IMHO it’s too opinionated to be in core. It works for me, but it uses some historical/non-standard conventions that makes it hard for some users to use it. An option we could follow is to follow the same path of undici and create something new with the goal of bringing it in the fold. |
As Matteo said, Pino has baggage that we can't realistically remove. I have provided a few tips along the way of this PR, but I really don't have the energy to devote to an actual review of it. So I can't speak to the implementation as it is today. The last time I looked at it, it was going in the right direction and I assume that has continued. If we are at the "go or no-go" point, I can attempt to use it and provide feedback on if it works as I would expect or not. |
Co-authored-by: Yagiz Nizipli <[email protected]>
|
@mertcanaltin Can you update the description of this pull-request? Please provide a full description of all the changes you're bringing, the performance characteristics of this new module etc. |
I Updated PR description |
I don't think there's any need to rush into this must land immediately. We can provide people the time to review it properly if anyone wants to do so. Personally, I think it's in good shape at this point, but it's also a somewhat big and critical system so it makes sense that we might want to wait a bit for deeper review to ensure we're fully confident in the architecture. |
I don't understand this reply. I am not trying to rush anything. I am stating that the best I can do for a review is to try out the "done" product and provide feedback at that point. I have no idea if that point has been reached. |
Description
Adds an experimental
node:loggermodule that provides a structured, high-performance logging API for Node.js. Available behind the--experimental-loggerflag.Refs: #49296
Architecture
diagnostics_channelas the dispatch mechanism — loggers publish log records to level-specific channels, consumers subscribe to receive themnoopfunctions, eliminating runtime level checksUtf8Stream(SonicBoom port) for high-throughput writesAPI Surface
Logger— Producer class withtrace,debug,info,warn,error,fatalmethodsLogConsumer— Base consumer class for custom log handlingJSONConsumer— Built-in consumer that outputs structured JSON viaUtf8Streamchild(bindings, options)— Child loggers with inherited context and serializerslogger.<level>.enabled— Getter for conditional logging (typo-safe)stdSerializers— Built-in serializers forerr,req,resserializesymbol —Symbol.for('nodejs.logger.serialize')— custom object serialization hook (stacked with field serializers)Log levels follow RFC 5424 numerical ordering internally (
trace: 10, debug: 20, info: 30, warn: 40, error: 50, fatal: 60). The API accepts string level names.diagnostics_channelchannel names (log:trace,log:debug,log:info,log:warn,log:error,log:fatal) are used internally and can be subscribed to directly viadiagnostics_channelif needed.Performance
Benchmarked against Pino (output to
/dev/null, n=100000):New files
lib/logger.js— Main module (Logger,LogConsumer,JSONConsumer)lib/internal/logger/serializers.js— Standarderr/req/resserializersdoc/api/logger.md— Full API documentationbenchmark/logger/basic-json.js— Benchmarkstest/parallel/test-log-basic.js— Core logger teststest/parallel/test-logger-serializers.js— Serializer testsModified files
src/node_options.h/src/node_options.cc—--experimental-loggerflaglib/internal/process/pre_execution.js—setupLogger()to allow module loading when flag is setlib/internal/bootstrap/realm.js— Module registrationdoc/api/cli.md— Flag documentationdoc/api/index.md/doc/node.1— Index updatestest/parallel/test-code-cache.js/test-process-get-builtin.mjs/test-require-resolve.js— Test adjustments for new module