Skip to main content

npm

Source

See the Plugins guide for how plugins from wolfstar-project/plugins fit alongside the core framework.

Description

@wolfstar/plugin-logger replaces the built-in console logger of @wolfstar/http-framework with one that fans every entry out to a list of transports. It implements the same ILogger contract, so code that already writes through container.logger keeps working. It replaces @wolfstar/logger, which has been removed. Every logging backend is an optional peer dependency. Install only the ones you use:
SentryTransport takes the Sentry client you already use (@sentry/node, @sentry/bun, and so on) through its constructor, so it needs no extra dependency.

Usage

Import the register entry point before you create your Client:
Without further configuration the logger writes to console, like the framework’s built-in one.

Activating with modules

On framework 6.1 and later, list the ./module entry in modules in stars.config instead of importing register. It needs the optional @wolfstar/kit peer dependency, at ^0.2.0 || ^0.3.0.
The module reads its options from the logger key of stars.config. The [specifier, options] tuple of modules still works. Its options are merged over the logger key, so they win. The optional @wolfstar/schema peer dependency types the logger key in defineConfig. TypeScript only loads that type once the module is imported, so import @wolfstar/plugin-logger/module in stars.config.ts. Module options must be JSON-serialisable. Transports are objects, so set them through ClientOptions.logger.transports. The one exception is evlog, which the module can set up for you through its evlog option. Without the stars CLI, pass the ./plugin definePlugin factory to the plugins client option:
Use only one of the module, the ./plugin factory, and register. Combining them installs the plugin’s hooks twice.

Transports

A transport is any object implementing Transport:
A LogPayload carries the raw values the caller passed, plus three fields derived from them. Every transport reads an entry the same way through these fields:
The fields are computed the first time a transport reads them, then cached. To build a payload for a custom transport or a test, use createLogPayload():
level filters on top of the logger’s own level, so a Sentry sink can take only errors while the console keeps everything:
A transport that throws, or returns a rejecting promise, never interrupts the caller. The error is caught and reported to console.error.

Sentry

SentryTransport takes its Sentry client through the constructor, so the package has no runtime dependency on a Sentry SDK. Pass the module namespace of the SDK you use. What Sentry receives depends on the entry’s level:
When an entry has an Error, the transport reports it with captureException and keeps the entry’s message and context in extra. Breadcrumbs are off by default because Sentry’s default console integration already records them for console.*. Turning them on next to a ConsoleTransport duplicates them. Closing the logger flushes the client, so the last fatal entry before an exit is delivered.

Backend adapters

Each adapter wraps a third-party logger as a transport and lives behind its own subpath, so the dependency is only resolved when you import it:

evlog

EvlogTransport hands each entry to evlog as a structured event. The event holds message, the context fields, tag, and the error with its cause chain. The transport does not format or deliver anything itself. evlog owns the pipeline, so drains, enrichers, sampling, and redaction configured in initLogger apply to your bot’s logs. All six levels map to the evlog method of the same name.
Pass the drain pipeline so closing the logger flushes it. Otherwise, events still buffered are lost when the process exits. evlog also ships a Sentry drain, which makes SentryTransport redundant when evlog is already your sink.

winston

WinstonTransport writes the message and the context fields, and serialises an Error into an error field with name, message, and stack. winston’s default npm levels have no fatal, so a fatal entry is written as error with a fatal: true field. Closing the logger more than once is safe.
Create the winston logger with level: 'silly'. winston’s own level (info by default) filters on top of the plugin’s and silently drops lower entries.

evlog plugin

The @wolfstar/plugin-logger/evlog/plugin entry sets up evlog for you. It runs evlog’s initLogger, adds an EvlogTransport to the logger, and emits one wide event per interaction. Use it when evlog is your logging backend and you want per-interaction events without wiring initLogger yourself.

evlog through the module

With the Stars module, set the evlog option. Use evlog: true for evlog’s defaults, or write the options inline:
Every other option (env, pretty, silent, minLevel, sampling, redact, and so on) goes to evlog’s initLogger. The options must be JSON-serialisable, since they are written into the built entry. The drain is a function, so it comes from a file that Stars bundles with your bot. evlog: true, or options without drain, need no file. A drain that already has a flush method is used as is. Either way, closing the logger flushes it. evlog prints to the console itself, so the module adds no ConsoleTransport next to it. Set silent: true when the drain should be the only output. Without the stars CLI, pass the drain to the evlogPlugin factory directly, before the logger plugin:

Wide events per interaction

The evlog plugin follows the client’s interaction lifecycle and drains one wide event per interaction. The event is created when a command, component, or modal starts, filled with its outcome, and emitted when it finishes. It goes through the same drain, sampling, redaction, and plugins as every other evlog event. interactions accepts true, false, or an object with commands, handlers, and autocomplete flags. Commands and handlers are on by default. Autocomplete is off by default, since Discord sends a request for every keystroke.
From a command, autocomplete, or handler, useInteractionLogger() returns the interaction’s evlog request logger so you can add fields to its wide event. It throws when called outside an interaction.

Upgrading the transports

The transport rework changes what some backends receive and which peer dependencies the package declares:
  • Custom transports: LogPayload now has message, error, and context. Read those instead of parsing values, and build test payloads with createLogPayload().
  • Sentry: the @sentry/node peer dependency is gone. Keep installing the Sentry SDK you pass as client. Issues created from an Error now carry the message and context in extra instead of the raw values.
  • evlog: the evlog peer requires ^2.30.0. Entries are structured events instead of flattened strings, and trace and fatal no longer collapse into debug and error. Update queries or dashboards that relied on the old string output.
  • winston: entries now spread the context fields at the top level instead of a values array. An Error is written as an error field with name, message, and stack (JSON used to turn it into {}). fatal entries are still written as error, now with a fatal: true field.

Migration from @wolfstar/logger

The trace, debug, info, warn, error, and fatal methods behave the same. LogLevel keeps its ordering and is now imported from @wolfstar/http-framework. version downloads license