The denosaurs log module is a tiny, cross-platform, drop-in module for handling logs using streams. It has been tested and works in the browser, Deno, Node and Bun with second-class support for all runtimes and environments which implement web streams.
Log is supported in all runtimes and environments which implement web streams, but installation method may differ between runtimes. It is published to jsr.
Import it directly from JSR using the jsr
protocol.
import { ConsoleReadableStream } from "jsr:@denosaurs/log";
Or add it to your
import map or
deno.json
:
{
"imports": {
"log": "jsr:@denosaurs/log"
}
}
Add this line to the project's .npmrc file or the global one.
@jsr:registry=https://npm.jsr.io
And install the package using npm or the package manager of your choice.
npm install @jsr/denosaurs__log
If you would like a prettier package name I would suggest changing it in the
package.json
file to something like @denosaurs/log
.
{
"dependencies": {
- "@jsr/denosaurs__log": "*"
+ "@denosaurs/log": "npm:@jsr/denosaurs__log"
}
}
Note that we use the JsonStringifyStream
from the deno standard library in the example.
In Node, Bun and other runtimes you can install it from jsr.
Add this line to the project's .npmrc file or the global one.
@jsr:registry=https://npm.jsr.io
And install the package using npm or the package manager of your choice.
npm install @jsr/std__json
If you would like a prettier package name I would suggest changing it in the
package.json
file to something like @std/json
.
{
"dependencies": {
- "@jsr/std__json": "*"
+ "@std/json": "npm:@jsr/std__json"
}
}
The following example demonstrates how to capture and log messages as JSON to stdout.
// Ensure Bun compatibility. [It currently lacks support for TextEncoderStream](https://github.com/oven-sh/bun/issues/5648)
import "@denosaurs/log/transforms/text_encoder_stream";
import { ConsoleReadableStream } from "@denosaurs/log";
import { StdoutWritableStream } from "@denosaurs/log/writables/std";
import { JsonStringifyStream } from "@std/json";
// Capture logs from the console
const stream = new ConsoleReadableStream();
stream
// Stringify the logs to JSON
.pipeThrough(new JsonStringifyStream())
// Encode the output to an UTF-8 byte stream
.pipeThrough(new TextEncoderStream())
// Pipe the output to stdout
.pipeTo(new StdoutWritableStream());
// Log some messages
console.log("Hello, world!");
console.group("Group 1");
console.debug("Debug message");
console.groupEnd();
console.info("Info message");
Sometimes you may want to log messages to multiple destinations. This can be done using teeing.
In the example we also use the OmitLogLevelStream
and PickLogLevelStream
to
filter the logs before they are written to the different destinations.
// Ensure Bun compatibility. [It currently lacks support for TextEncoderStream](https://github.com/oven-sh/bun/issues/5648)
import "@denosaurs/log/transforms/text_encoder_stream";
import { ConsoleReadableStream } from "@denosaurs/log";
import {
StderrWritableStream,
StdoutWritableStream,
} from "@denosaurs/log/writables/std";
import { OmitLogLevelStream } from "@denosaurs/log/transforms/omit";
import { PickLogLevelStream } from "@denosaurs/log/transforms/pick";
import { JsonStringifyStream } from "@std/json";
// Capture logs from the console
const stream = new ConsoleReadableStream();
// Split the stream in two
const [a, b] = stream.tee();
a
// Omit only the error logs
.pipeThrough(new OmitLogLevelStream("error"))
// Stringify the logs to JSON
.pipeThrough(new JsonStringifyStream())
// Encode the output to an UTF-8 byte stream
.pipeThrough(new TextEncoderStream())
// Pipe the output to stdout
.pipeTo(new StdoutWritableStream());
b
// Pick only the error logs
.pipeThrough(new PickLogLevelStream("error"))
// Stringify the logs to JSON
.pipeThrough(new JsonStringifyStream())
// Encode the output to an UTF-8 byte stream
.pipeThrough(new TextEncoderStream())
// Pipe the output to stderr
.pipeTo(new StderrWritableStream());
// Log some messages
console.error("This is going to stderr");
console.trace("This is going to stdout");
console.debug("This is going to stdout");
console.info("This is going to stdout");
console.warn("This is going to stdout");
console.log("This is going to stdout");
The module is still young, with lot's of planned features and improvements. It is far from stable, so expect breaking changes. But anyways, here are some features:
- Add support for more runtimes and environments
- The goal should be to support all WinterCG compatible runtimes
- Deno
- Untested Deno Deploy
- Node.js
- Bun
- Untested Cloudflare Workers
- Untested Vercel Edge Runtime
- Untested Fastly Compute
- Untested LLRT
- Untested Browsers
- Exception and rejection handling
- Add a
fatal
log level, which will be used for unhandled exceptions and rejections. Unreachable from the normalconsole
API.
- Add a
- Metrics/timings using
console.time
andconsole.timeEnd
- Transforms
- Filter
- Omit
- Pick
- JSON (Using
JsonStringifyStream
) - Redaction
-
[Symbol.for("log.secret")]
(This only works when not usingstructuredClone
becausesymbol
s are not cloneable. A future fix for this might be to write our ownstructuredClone
function which keeps symbols.) - Exact match
- Regex
- fast-redact
-
- Request and response metadata
-
[Symbol.for("log.request")]
orinstanceof Request
-
[Symbol.for("log.response")]
orinstanceof Response
-
- Pretty print
- Logfmt
- Destinations
- Console
- Stdout
- Stderr
- File
- Single file
- Rotating file
- Network
- Fetch
- WebSocket
- UDP
- TCP
- Integrations
- First-class support for popular web-frameworks
Some goals of this module are:
- Web Standards - It should to the greatest extent possible follow web
standards and try to emulate (and in the case of
console
extend) the standards we already know and love. - Ease of use - It should be easy to use and understand. It should be
familiar, or dare I say, effortless to anyone who has used the
console
. - Minimal - It should be as small as possible, with minimal dependencies. Logging doesn't have to be complicated.
- Performance - It needs to be fast. It should never noticeably slow down the application. Logging is a critical part of the application, but it should never be the bottleneck.
- Quality - It should be well tested and well documented. It should be reliable and trustworthy.
- Elias SjΓΆgreen (@eliassjogreen)
Pull request, issues and feedback are very welcome. Code style is formatted with
deno fmt
and commit messages are done following Conventional Commits spec.
Please use it! And let us know if you have any issues, feedback or requests.
Copyright 2024, the Denosaurs team. All rights reserved. MIT license.