Feature Request: Support for libraries
NfNitLoop opened this issue · 3 comments
So far, all the docs seem to point to instantiating a single Log
object, which is configured with all of its Loggers. And applications just call methods on that.
Are there any plans to support log instrumentation by libraries?
Common features I expect in that space, are:
- Library author creates a named logger, and uses it within their library. By default, the logger isn't necessarily configured to output anything.
- The application author that eventually uses the library configures a root/global/default logger with log levels, which may enable logging for various libraries. They can optionally filter by library, so they might have something like, "library
foo
has log-level info, but librarybar
has log level debug" - Library code that calls log methods has some way to send lazily-evaluated messages, which are only executed/formatted if the log level/filters would result in outputting that message.
Very interesting! The library could have two options,
propagate: Boolean; // <- default: false, set to true in libraries
ingest: Boolean; // <- default: false, set to true in the main application process to ingest propagated logs
... if propagation is enabled, @cross/log would check (for example) globalThis.__crossLogPropagationHandlers_v1
for registered handlers, and call them
... if ingestion is enabled, @cross/log would register a handler on globalThis.__crossLogPropagationHandlers_v1` to receive propagated messages. The handler could expect (and validate) exactly one object, with the interface:
interface PropagatedMessage {
severity: "DEBUG" | "INFO" | "LOG" | "WARN" | "ERROR" | string,
scope: string,
data: unknown,
timestamp: number
}
Thoughts?
Thoughts?
TBH, I haven't implemented something like this in JS before. I don't mind how it's implemented as long as I get an API that lets me instrument my library (with negligible performance impact), and lets someone else decide whether/how to output those logs.
You might want to have a look at the Log4J API docs if you haven't used them before. (Whatever your feelings about Java as a language, Log4J was IMO one of the nice things from that ecosystem.) In particular, the idea of separating the logging API (interface) from the implementation. (see: https://logging.apache.org/log4j/2.x/manual/api-separation.html)
I tried using the Log4js NPM package before I found @cross/log
, and it seems they've followed that pattern and have a separate log4js-api package. It didn't work well for me in Deno. (It immediately asked for permissions to read environment variables and node_modules.) But it might be a good implementation to look at for inspiration for the implementation.
For other similar APIs to draw ideas from, see the tracing_subscriber and tracing crates in Rust. ("tracing" is the interface, "_subscriber" is the output implementation.)