Node.js - Google Cloud Stackdriver Logging

Google Stackdriver is a collection of monitoring and management services for applications, containers, and infrastructure. It has some features such as debugger, error reporting, alerts, tracing, and logging. From all the features above, in this tutorial, I'm going to give you examples of how to use the logging feature in Node.js application.

The Stackdriver logging is a log management system. Like oher similar services, it allows users to send logs and find logs with a specific criteria. It offers seamless integration with Google Cloud Platform products and also their main rival, Amazon Web Services. By default when you use certain services in GCP, it will automatically log important events, such as when you enabling an API. Those logs can be viewed in Stackdriver Logging console. But it doesn't mean you've to use GCP or AWS in order to use the logging feature. You can still use it wherever your application is hosted.

Preparation

1. Create or select a Google Cloud project

A Google Cloud project is required to use this service. Open Google Cloud console, then create a new project or select existing project

2. Enable billing for the project

Like other cloud platforms, Google requires you to enable billing for your project. If you haven't set up billing, open billing page.

3. Enable Google Logging API

To use an API, you must enable it first. Open this page to enable Logging API.

4. Set up service account for authentication

As for authentication, you need to create a new service account. Create a new one on the service account management page and download the credentials, or you can use your already created service account.

In your .env file, you have to add a new variable

GOOGLE_APPLICATION_CREDENTIALS=/path/to/the/credentials

Dependencies

This tutorial uses @google-cloud/logging. Add the following dependencies to your package.json and run npm install

  "@google-cloud/logging": "~2.0.0"
  "dotenv": "~4.0.0"
  "lodash": "~4.17.10"

Code Examples

1. Write Logs

Below is an example of sending logs to Stackdriver. The first one is a text and the other is an object.

  require('dotenv').config();
  
  const Logging = require('@google-cloud/logging');
  
  const logging = new Logging();
  
  // The name of the log, you can use it for filtering
  const logName = 'my-log-test';
  // Selects the log name you want to use
  const log = logging.log(logName);
  
  // The metadata associated with the entry
  const metadata = {
    resource: {
      type: 'global',
      labels: {
        firstLabel: 'something',
        secondLabel: 'another value',
      },
    },
  };
  
  // Write Text log
  const text = 'Hello, world!';
  
  // Prepares a log entry
  const entry = log.entry(metadata, text);
  
  // Writes the log entry
  log
    .write(entry)
    .then(() => {
      console.log(`Logged: ${text}`);
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  
  // Write object log
  const object = {
    name: 'Test',
    content: 'Hello world!'
  };
  
  const entry2 = log.entry(metadata, object);
  
  log
    .write(entry2)
    .then(() => {
      console.log(`Logged: ${JSON.stringify(object)}`);
    })
    .catch(err => {
      console.error('ERROR:', err);
    });

After logs succesfully inserted, you can go to Stackdriver Console to view the logs. Each logs has the following properties:

Property Note
insertId A unique indentifer
logName Log name in format projects/${PROJECT_ID}/logs/${LOG_NAME}
receiveTimestamp The time when the log received
resource Containing type and label
payload If you send a text log, it will be in textPayload property. The content of an object log is in protoPayload or jsonPayload property

There are some other properties, but they're optional. For full list of properties. you can read the LogEntry documentation.

Like other logging system, Stackdriver Logging allows users to set logging level. Below is the five supported logging levels, from lowest to highest.

Level Command
Default log.write
Debug log.debug
Info log.info
Notice log.notice
Warning log.warning
Error log.critical
Critical log.critical
Alert log.alert
Emergency log.emergency

2. Get Log Entries

After succesfully sending logs, you may want to view the logs. If you have so many logs, of course you want to apply filters. Here's the basic example of how to filter logs. As examplified below, you can use multiline query and to make it easy, it's recommended to use template literal instead of string concatenation. The example below is for finding logs with resorce type 'gce_instance' and the value of instance_id label '3'. The log must also contain 'world' and 'hello' (case insensitive).

  require('dotenv').config();
  
  const Logging = require('@google-cloud/logging');
  
  const logging = new Logging();
  
  // The name of the log, you can use it for filtering
  const logName = 'my-log-test';
  // Selects the log name you want to use
  const log = logging.log(logName);
  
  const options = {
    filter: `
      resource.type="gce_instance" AND resource.labels.instance_id=3
      "world"
      "hello"
    `
  };
  
  log
    .getEntries(options)
    .then((res) => {
      console.log(JSON.stringify(res[0], null, 2));
    })
    .catch(err => {
      console.error('ERROR:', err);
    });

And here's the result example

  [
    {
      "timestamp": {
        "seconds": 1533570334,
        "nanos": 888999938
      },
      "labels": {},
      "insertId": "..........4mQYLiBXO3A9uktrOqHH9l",
      "httpRequest": null,
      "resource": {
        "labels": {
          "zone": "global",
          "project_id": "gcs-demo-205713",
          "instance_id": "3"
        },
        "type": "gce_instance"
      },
      "severity": "DEFAULT",
      "logName": "projects/gcs-demo-205713/logs/my-log-2",
      "operation": null,
      "trace": "",
      "sourceLocation": null,
      "receiveTimestamp": {
        "seconds": "1533570338",
        "nanos": 231392983
      },
      "metadata": null,
      "spanId": "",
      "textPayload": "Hello, world 2!",
      "payload": "textPayload"
    }
  ]

3. Delete Logs

For some reasons, you may want to delete unused logs. Here's the example of how to delete all logs with a specific log name

  require('dotenv').config();
  
  const Logging = require('@google-cloud/logging');
  
  const logging = new Logging();
  
  // The name of the log, you can use it for filtering
  const logName = 'my-log-test';
  // Selects the log name you want to use
  const log = logging.log(logName);

  log.delete()
    .then(() => {
      console.log('Log successfully deleted');
    });

That's all abot the tutorial of how to use Google Stackdriver Logging in Node.js application.