Skip to content

Logging Configuration

Nishant Aanjaney Jalan edited this page Apr 7, 2024 · 6 revisions

Installing the logger in the Elysia app

The simplest logger

The simplest way to add the logger to Elysia is with the build function. This decorates your instance with a logestic object that gives you access to 4 useful methods: info, debug, warn, and error. In this application, I term this as explicitLogging. For example,

import { Logestic } from 'logestic';

const logger = new Logestic().build();

const app = new Elysia()
  .use(logger)
  .get('/', ({ logestic }) => {
    logestic.warn("This route does nothing")
    return ''
  })
  .listen(3000)

You can log to a specific file by specifying the dest property in the options. This defaults to Bun.stdout.

const logger = new Logestic({
  dest: Bun.file('server.log')
}).build();

The HTTPLogger

You are required 3 steps to log every incoming request to your server, termed httpLogging.

  1. Create a Logestic instance.
  2. Define the parameters you wish to use.
  3. Format the string given the parameters.

Putting the 3 steps together, you get:

import { Logestic } from 'logestic';

const plugin = new Logestic()
  .use(['method', 'path']) 
  .format({
    onSuccess({ method, path }) {
      return `${method} ${path} was called and handled without server error.`;
    },
    onFailure({ request, error, code }) {
      return `Oops, ${error} was thrown with code: ${code}`;
    }
  });

plugin is now an instance of Elysia with a logestic object decorated in Elysia's context for explicit logging. This is great when you want consistency in your log messages.

const app = new Elysia()
  .use(plugin)
  .get('/', ({ logestic }) => {
    logestic.debug('Why is it not working?');
    return 'you didn't call listen(3000)';
  });

Optionally: You can define an onRequest function if you wish to enable logging as soon as the request arrives. This function only provides you with a request object from PreContext.

/* ... */
  .format({
    onRequest(request) {
      return `${request.method} has been requested`
    },
    onSuccess({ method, path }) {
      return `${method} ${path} was called and handled without server error.`;
    },
    onFailure({ request, error, code }) {
      return `Oops, ${error} was thrown with code: ${code}`;
    }
  });

Configuration

Options

You can pass multiple options to your Logestic object:

constructor(options: LogesticOptions = {});

export type LogesticOptions = {
  dest?: BunFile;
  httpLogging?: boolean;
  explicitLogging?: boolean;

  showLevel?: boolean;
  logLevelColour?: LogLevelColour;
};
  1. dest - The logging destination. Logestic will throw an error if Bun.stdin is passed. Defaults to Bun.stdout.
  2. httpLogging - Whether to log all incoming HTTP requests. Defaults to true.
  3. explicitLogging - Whether to allow logs that were made explicitly. Defaults to true.

Log Level

There are 5 types of log level: HTTP, INFO, DEBUG, WARN and ERROR. If you enable showLevel in the options, either of the 5 will be prefixed before your format string. Furthermore, you can override the background colour by extending logLevelColour object.

Formatting

type FormatObj = {
  onSuccess: (attr: Attribute) => string;
  onFailure: (attr: ErrorAttribute) => string;
};

format(this: Logestic, formatAttrs: FormatObj) => Elysia

Elysia's lifecycle dictates we have different functions to format successful requests and requests that throw some error. Logestic uses chalk as a dependency for its presets and also re-exports this class. The parameters you chose to use via .use() are passed to onSuccess for formatting.

The attributes specified in .use() only alter the attributes passed inside onSuccess. For onFailure, all destructured variables are fixed, defined, and uncustomisable.

  .use(['method', 'status'])
  .format({
    onSuccess({ method, status }) {
      // method - GET, POST
      // status - 200, 402, Unauthorized
    },
    onFailure({ request, error, code, datetime }) { 
      // All of the above are defined. 
      // You cannot customise these arguments
    }
  })

Here is the list of all attributes:

  1. ip - The IP address of the client making the request
  2. method - The HTTP method used in the request
  3. path - The path of the request
  4. body - The body of the request
  5. query - The query parameters of the request
  6. time - The time when the request was made
  7. contentLength - The length of the response content
  8. status - The status code of the response
  9. referer - The referer URL of the request
  10. userAgent - The user agent string of the client making the request
  11. duration - Time taken from after receiving a request to before sending the response.