JavaScript advanced usage

Get started with Better Stack in your JavaScript application using this overview of the Better Stack logger.

Log levels

Logtail JavaScript client instance provides 4 logging methods for the 4 default log levels. The log levels and their methods are:

  • DEBUG - Send debug messages with debug()
  • INFO - Keep track of your app's progress with info()
  • WARN - Report non-critical issues with warn()
  • ERROR - Log serious problems with error()

Logging example

To send a log message of selected log level, use the corresponding method. In this example, we send the DEBUG level log and ERROR level log:

Send logs to Logtail
// Send DEBUG level log using the debug() method
logtail.debug("I am using Logtail!");

// Send ERROR level log using the error() method
logtail.error("Oops! A runtime error occurred!");

The Better Stack client automatically adds context to the logs.
The following JSON output is sent to Better Stack:

Output
{
   "dt":"2022-02-01 12:01:10.127 UTC",
   "context":{
      "runtime":{
         "column_integer":"21",
         "file_string":"node_modules/@logtail/core/dist/cjs/base.js",
         "line_integer":"141",
         "type_string":"Node",
         "function_string":"debug",
         "method_string":"debug"
      },
      "system":{
         "main_file_string":"/mnt/d/js_logtail/index.js",
         "pid_integer":"4193"
      }
   },
   "level_string":"debug",
   "message_string":"I am using Logtail!"
}

{
   "dt":"2022-02-01 12:01:10.127 UTC",
   "context":{
      "runtime":{
         "column_integer":"8",
         "file_string":"index.js",
         "line_integer":"40",
         "type_string":"Object"
      },
      "system":{
         "main_file_string":"/mnt/d/js_logtail/index.js",
         "pid_integer":"4193"
      }
   },
   "level_string":"error",
   "message_string":"Oops! A runtime error occurred!"
}

Logging structured data

Quickly troubleshoot your application by logging structured data. Pass an object as a second argument to any logging method, like in the example below:

Send structured logs to Logtail
logtail.warn("Something is not quite right.", {
    user: {
        username: "John Doe",
        email: "john@example.com"
    },
    additional_info: {
        tried_accessing: "/url/of/error"
    }
});

This creates the following JSON output:

Output
{
   "dt":"2022-02-01 12:01:10.127 UTC",
   "context":{
      "runtime":{
         "column_integer":"8",
         "file_string":"index.js",
         "line_integer":"29",
         "type_string":"Object"
      },
      "system":{
         "main_file_string":"/mnt/d/js_logtail/index.js",
         "pid_integer":"4193"
      }
   },
   "level_string":"warn",
   "message_string":"Something is not quite right.",
   "additional_info":{
      "tried_accessing_string":"/url/of/error"
   },
   "user":{
      "email_string":"john@example.com",
      "username_string":"John Doe"
   }
}

Forwarding console output

Already logging with console.log()? Call replaceConsoleMethods() once after setting up the client.

Every console.debug(), console.log(), console.info(), console.warn() and console.error() call is then sent to Better Stack as well, and the console keeps printing as before:

Forward console output to Better Stack
logtail.replaceConsoleMethods();

console.info("User logged in", { user_id: 42 });
console.error("Payment failed", new Error("Card declined"));

The arguments are mapped the same way as in logtail.info(message, context):

  • Strings and other primitives form the message. A printf-style format string in the first argument is applied, like console.log("%s logged in", user.name).
  • Plain objects become fields of the log.
  • The first Error becomes the error field with its message and stack trace. Every error is also printed in the message.

console.log() is sent with the info level, the other methods with their own. Call restoreConsoleMethods() to put the original console back.

Better Stack JavaScript client 0.5.10 or higher is required

Update @logtail/node, @logtail/browser or @logtail/js first.

Middleware

You can intercept every logged item and modify it before it's pushed to Better Stack. This could be useful, for example, for adding the current user's ID to the log or for filtering:

Enrich logs Filter logs
// Intercept the log and add userId to the content
async function enrichLogs(log) {
    return {
        ...log,
        userId: getCurrentUserId()
    };
}

// Tell Logtail client to use the enriching function
logtail.use(enrichLogs);
// Ignore any log with "[ignore]" in its message
async function filterLogs(log) {
    const shouldIgnore = log.message?.includes("[ignore]");
    return shouldIgnore ? null : log;
}

// Tell Logtail client to use the filtering function
logtail.use(filterLogs);

TypeScript

If you're using Logtail in a TypeScript codebase, you can take advantage of our types. You could write the enriching middleware function with types like this:

Enrich logs in TypeScript
import { ILogtailLog } from "@logtail/types";

async function enrichLogs(log: ILogtailLog): Promise<ILogtailLog> {
    return {
        ...log,
        userId: getCurrentUserId()
    };
}