Skip to main content.

Log HandlerChoose where your logs are written.

By default, log messages are written using the various methods available in the Console API. LambdaLog gives you the ability to use your own custom handler for writing log messages to any place you wish including a third-party service. To create your own log handler, you only need to create an object or class in which implements the various methods used by LambdaLog in the console API.

There are a couple of different ways to do this, but most commonly:

  • Create a new Console class.
  • Create a class or object that implements the methods of console.

Either way you go, the class or object must, at minimum, implement the following methods:

  • log
  • debug
  • info
  • warn
  • error

Note: Due to the nature of console, all methods must be synchronous. If you need asynchronous functionality, you may either use streams or understand the risk of logs not making it to their destination if the process was to end prior to all asynchronous code executing.

Console Class

The first method is by creating a new instance of the Console class. One example would be to write logs to a file versus the terminal.

1const { LambdaLog } = require('lambda-log');
2const fs = require('fs');
3const { Console } = require('console');
4 
5// Create write streams for standard log messages and error messages.
6const logFile = fs.createWriteStream('./out.log');
7const errorLogFile = fs.createWriteStream('./errors.log');
8 
9// Set logHandler to a new instance of the Console class.
10const log = new LambdaLog({
11 logHandler: new Console({ stdout: logFile, stderr: errorLogFile })
12});

With this example, your logs will now be written to a file instead of the terminal.

Custom Class or Object

The second method is by creating a custom class or object that implements some of the functions as console. If you want a more complete custom log handler, you may also extend the Console class and only override the methods you need to. Let's look at some examples.

Custom log handler object

1const myConsole = {
2 log(message) {
3 // write a file, send to a third-party service, etc.
4 // and you can still log the message to the terminal:
5 console.log(message);
6 },
7 debug(message) {
8 // ...
9 },
10 info(message) {
11 // ...
12 },
13 warn(message) {
14 // ...
15 },
16 error(message) {
17 // ...
18 }
19};
20 
21// Set logHandler to custom console
22log.options.logHandler = myConsole;

Custom log handler class

1class MyConsole {
2 log(message) {
3 // write a file, send to a third-party service, etc.
4 // and you can still log the message to the terminal:
5 console.log(message);
6 }
7 
8 debug(message) {
9 // ...
10 }
11 
12 info(message) {
13 // ...
14 }
15 
16 warn(message) {
17 // ...
18 }
19 
20 error(message) {
21 // ...
22 }
23};
24 
25// Set logHandler to custom console
26log.options.logHandler = new MyConsole();

Extend Console class with custom functionality

1const { Console } = require('console');
2const ddEvents = require('datadog-events');
3 
4class MyConsole extends Console {
5 constructor() {
6 // Call parent constructor
7 super({ stdout: process.stdout, stderr: process.stderr });
8 }
9 
10 // Override error to send logs to a third-party, such as DataDog
11 async error(message) {
12 // Call the parent method so it's still logged to the terminal:
13 super(message);
14 
15 // Parse message back into an object:
16 const data = JSON.parse(message);
17 
18 // Send error event to DataDog:
19 await ddEvents.error(data.msg, data.stack, {
20 tags: data._tags
21 });
22 }
23};
24 
25// Set logHandler to custom console
26log.options.logHandler = new MyConsole();

While this is a viable way of sending data to a third-party, it's recommended to use the log event instead:

1const log = require('lambda-log');
2const ddEvents = require('datadog-events');
3 
4log.on('log', async msg => {
5 if(msg.level === 'error') {
6 await ddEvents.error(msg.msg, JSON.stringify(msg.meta, null, 4), {
7 tags: msg.tags
8 });
9 }
10});