Universal Logging for Typescript/JavaScript
Getting Started
Reference Manual
Plugins
FAQ's
v1.x
GitHub
Getting Started
Reference Manual
Plugins
FAQ's
v1.x
GitHub
  • Reference Manual
    • Introduction & Lifecycle
    • Log Class
    • Data Getters
    • Modifiers
    • Terminators
    • Global Store
    • Tools
    • Configuration
    • Middleware
    • Formatters
    • Unit Testing

Middleware

Adze is able to be extended through middleware classes. Adze exports a Middleware Class that can be extended to hook into various points in a log's lifecycle.

Look for Adze middleware libraries for extending the functionality of your logs or for transporting your log data to various targets.

The Middleware Class is meant to be used as a base class that is extended for creating middleware components for Adze to use.

Because Adze is isomorphic, all middleware MUST also be isomorphic.

Environment Targeting

When creating middleware, sometimes you care about browser and backend environments, and sometimes you only care about one of them.

The Middleware Class requires that you specify your target if you only care about a single environment. If you don't specify your target environment, it will default to assuming your middleware cares about 'both'. You can specify your target by providing your value as the first parameter to the super() call in your middleware constructor.

The options are:

  • "both" - (Default) This middleware will operate in both server and browser environments.
  • "browser" - This middleware only operates in the browser.
  • "server" - This middleware only operates in backend environments.

Example

import { Middleware } from 'adze';

export class HelloMiddleware extends Middleware {
  constructor() {
    // Let's target the server environment for our middleware.
    super('server');
  }
}

Loading Dependencies

Middleware dependencies may function in one or both types of environments. To support all of the various situations, the Middleware Class provides simple hooks for conditionally loading dependencies.

These hooks are called when the consumer of the middleware calls the load method on the middleware instance. This is required because we must await our conditionally loaded dependencies.

The methods that are called for each environment are:

  • protected async loadServerDependencies() - Hook for loading server side dependencies.
  • protected async loadBrowserDependencies() - Hook for loading browser side dependencies.

Example

import { Middleware } from 'adze';
// Make sure to include the "type" value here! Otherwise your code will try to import the function!
import type { writeFile } from 'node:fs';

export class HelloMiddleware extends Middleware {
  private writeFile: typeof writeFile;

  constructor() {
    super('server');
  }

  /**
   * Load dependencies for the server environment.
   */
  protected async loadServerDependencies() {
    // We'll load the fs.readFile function so we can write data to our file system.
    const fs = await import('node:fs');
    // Save our dependency to the private writeFile property to be used elsewhere in our middleware.
    this.writeFile = fs.writeFile;
  }
  /**
   * Load dependencies for the browser environment.
   */
  protected async loadBrowserDependencies() {
    // We won't put anything here because we're only targeting the server.
  }
}

Using the Middleware

To use our middleware, we'll need to make sure we instantiate it and await a call to the load method before passing it in to the setup function.

import adze, { setup } from 'adze';
import HelloMiddleware from './hello-middleware';

const helloMw = new HelloMiddleware();
await helloMw.load();

setup({
  middleware: [helloMw],
});

Using Lifecycle Hooks

To hook into various points in the Adze log lifecycle, we can define hooks in our middleware. The hooks listed below are in order of when they are called in the lifecycle.

constructed

This hook is called during construction of a log instance.

interface Middleware {
  constructed?(log: Log): void;
}
OrderParameterDescription
1logThe instance of the log. This can be used to access its data.

beforeModifierApplied

This hook is called just before a modifier is applied to a log instance.

interface Middleware {
  beforeModifierApplied?(log: Log, name: ModifierName, data: ModifierData): void;
}
OrderParameterDescription
1logThe instance of the log. This can be used to access its data.
2nameThe name of the modifier that was called (ie. "withEmoji")
3dataThe cumulative modifier data object from all modifier calls.

afterModifierApplied

This hook is called just after a modifier is applied to a log instance.

interface Middleware {
  afterModifierApplied?(log: Log, name: ModifierName, data: ModifierData): void;
}
OrderParameterDescription
1logThe instance of the log. This can be used to access its data.
2nameThe name of the modifier that was called (ie. "withEmoji")
3dataThe cumulative modifier data object from all modifier calls.

beforeFormatApplied

This hook is called just before a formatter is applied to a log instance to format a message. The hook must return a message (unknown[]). It can return the message parameter mutated or unchanged. Whatever is returned will be the new log message.

interface Middleware {
  beforeFormatApplied?(log: Log, format: string, message: unknown[]): unknown[];
}
OrderParameterDescription
1logThe instance of the log. This can be used to access its data.
2formatThe name of the log formatter that will be used.
3messageArray of arguments to be printed to the console.

afterFormatApplied

This hook is called just after a formatter is applied to a log instance to format a message.

interface Middleware {
  afterFormatApplied?(log: Log, format: string, message: unknown[]): void;
}
OrderParameterDescription
1logThe instance of the log. This can be used to access its data.
2formatThe name of the log formatter that was used.
3messageArray of formatted arguments to be printed to the console.

beforePrint

This hook is called just before a log instance message is printed to the browser or console.

interface Middleware {
  beforePrint?(log: Log): void;
}
OrderParameterDescription
1logThe instance of the log. This can be used to access its data.

beforeTerminated

This hook is called just before a log is terminated.

interface Middleware {
  beforeTerminated?(log: Log, terminator: string, args: unknown[]): void;
}
OrderParameterDescription
1logThe instance of the log. This can be used to access its data.
2terminatorThe name of the terminator that is being called to print the log.
3argsThe log arguments prior to formatting.

afterTerminated

This hook is called just when a log instance has completed termination.

interface Middleware {
  afterTerminated?(log: Log, terminator: string, args: unknown[]): void;
}
OrderParameterDescription
1logThe instance of the log. This can be used to access its data.
2terminatorThe name of the terminator that is being called to print the log.
3argsThe formatted arguments that will be printed.
Edit this page
Last Updated:
Contributors: Andrew Stacy, Andrew Stacy
Prev
Configuration
Next
Formatters