Skip to main content

📜 Dead-simple drop-in logging solution using streams and the native console api

Works with
This package works with Bun
This package works with Cloudflare Workers
This package works with Node.js
This package works with Deno
This package works with Browsers
JSR Score
100%
Published
3 months ago (0.0.13)

Log

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.

Installation

Log is supported in all runtimes and environments which implement web streams, but installation method may differ between runtimes. It is published to jsr.

Deno

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"
  }
}

Node and Bun

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"
  }
}

Examples

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"
  }
}

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");

Teeing

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");

Features

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
  • Exception and rejection handling
    • Add a fatal log level, which will be used for unhandled exceptions and rejections. Unreachable from the normal console API.
  • Metrics/timings using console.time and console.timeEnd
  • Transforms
    • Filter
    • Omit
    • Pick
    • JSON (Using JsonStringifyStream)
    • Redaction
      • [Symbol.for("log.secret")] (This only works when not using structuredClone because symbols are not cloneable. A future fix for this might be to write our own structuredClone function which keeps symbols.)
      • Exact match
      • Regex
      • fast-redact
    • Request and response metadata
      • [Symbol.for("log.request")] or instanceof Request
      • [Symbol.for("log.response")] or instanceof 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

Goals

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.

Maintainers

Contributing

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.

Licence

Copyright 2024, the Denosaurs team. All rights reserved. MIT license.

Built and signed on
GitHub Actions
View transparency log

Add Package

deno add @denosaurs/log

Import symbol

import * as mod from "@denosaurs/log";

Add Package

npx jsr add @denosaurs/log

Import symbol

import * as mod from "@denosaurs/log";

Add Package

yarn dlx jsr add @denosaurs/log

Import symbol

import * as mod from "@denosaurs/log";

Add Package

pnpm dlx jsr add @denosaurs/log

Import symbol

import * as mod from "@denosaurs/log";

Add Package

bunx jsr add @denosaurs/log

Import symbol

import * as mod from "@denosaurs/log";