Search code examples
node.jslogginggoogle-cloud-logging

How do you pass labels to Google Cloud Logs Explorer through log4js-node?


I have successfully logged messages and their severity from a Node application to Google Cloud Platform's Logs Explorer (k8s with built in logging agent) using log4js npm library and the log4js features below. However, the labels object does not log.

stdout appender

"type": "stdout",
   "layout": {
      "type": "json"
   }

addLayout()

log4js.addLayout('json', () => {
  const foo = 'bar';
  const biz = 'baz';

  return (logEvent) => {
    const severity = logEvent.level.levelStr;

    const labels = {
      foo,
      biz,
    };

    const message = `[${logEvent.categoryName}] ${logEvent.data} [${logEvent.level}]`;

    const logEntry = { severity, message, ['logging.googleapis.com/labels']: labels };

    return JSON.stringify(logEntry);
  };
});

Following the GCP documentation on structured logging, I also tried using labels for the labels key like:

const logEntry = { severity, message, labels };

I could not find anything in log4js documents (or code) about passing a log entry through to cloud logging. How can I pass labels so that GCP will recognize them and log them either in top level labels or labels inside jsonPayload or resource:

{
  "insertId": "r286o2xnfzsq955d",
  "jsonPayload": {
    "labels": {},
    "message": "this is my test message"
  },
  "resource": {
    "type": "k8s_container",
    "labels": {
      "namespace_name": "development",
      "container_name": "myContainer",
      "project_id": "123abc",
    }
  },
  "timestamp": "2022-09-15T18:29:41.020140836Z",
  "severity": "INFO",
  "labels": {
    "compute.googleapis.com/resource_name": "gke-machina...",
    "k8s-pod/app": "myApp",
    "k8s-pod/pod-template-hash": "123..."
  },
  "receiveTimestamp": "2022-09-15T18:30:00.835752120Z"
}

Solution

  • Found the problem; I needed to define the labels inline where as before I was defining them in the addLayout function but above return (logEvent). And for GCP, labels is the correct key name.

    log4js.addLayout('json', () => {
    
      return (logEvent) => {
        const severity = logEvent.level.levelStr;
    
        const labels = {
          foo: 'bar', // define inline here
          biz: 'baz',
        };
    
        const message = `[${logEvent.categoryName}] ${logEvent.data} [${logEvent.level}]`;
    
        const logEntry = { severity, message, labels };
    
        return JSON.stringify(logEntry);
      };
    });