Logging

Producing logs from within your ActyxOS apps and accessing them for monitoring/debugging.

Logs play a key role during the development and production phases of your app. They allow you to debug while you build, and monitor whilst your app runs in production. The ActyxOS Console Service offers functionality for logging. Let’s have a look.

Publishing Logs

ActyxOS allows you to publish structured or unstructured logs. We strongly encourage you to create structured logs and will focus on that in the next sections.

Still interested in unstructured logging?

ActyxOS captures unstructured logs you generate using stdout/stderr (apps running the Docker Runtime) and the console object (apps running in the WebView Runtime). For more information, check out the advanced guide for the Console Service.

With structured logging each log line you generate is actually a JSON object with the following shape:

{
    "insertId": "<automatically-added>",
    "insertTimestamp": "<automatically-added>",
    "labels": {
        "ax.schemas.logging.level": "info",
        "ax.schemas.logging.producer.sourceId": "<automatically-added>",
        "ax.schemas.logging.producer.sourceName": "<automatically-added>",
        "ax.schemas.logging.producer.appId": "<automatically-added>",
        "ax.schemas.logging.producer.appName": "<automatically-added>",
        "ax.schemas.logging.producer.appVersion": "<automatically-added>",
        "ax.schemas.logging.producer.dockerTag": "<automatically-added>"
        // Your labels
        // ...
    },
    // Your log name
    "logName": "<log-name>",
    // Your payload
    "payload": {
        // ...
    }
}

Reserved namespaces ax.* and actyx.*

Both ax.* and actyx.* are reserved namespaces and aliases for com.actyx.*. This is done so save valuable bytes going through the network.

You publish logs by sending POST HTTP requests to the ActyxOS Console Service running locally on the edge device your app is running on. This works for both apps running in the WebView Runtime and apps running in the Docker Runtime.

Let’s have a look at how this works, using an app running in the WebView Runtime as an example.

In order to generate a structured log line, we must perform two steps

  1. build the structured log object; and,
  2. publish the object using the Console Service API.

Consider the following single-page application built for the WebView runtime:

<!DOCTYPE html>
<html>
    <head>
        <script>
            function setColor(newColor) {
                var el = document.getElementById("myText");
                el.style.color = newColor;
            }
        </script>
    </head>
    <body>
        <p id="myText" >Some text</p>
        <button onclick="setColor('green')">Make green</button>
        <button onclick="setColor('red')">Make red</button>
    </body>
</html>

Imagine we wanted to log every time a user sets the color. We could do this by creating a mkLog function that builds the log object, creating a publishLog function that publishes the log and adjusting the setColor function to call these two functions whenever it runs.

Let’s start with the mkLog function, which will take the level we would like to log at, the name of the log we would like to log to and a single string log message. The function returns an object according to the log object specification of the ActyxOS Console Service:

function mkLog(logLevel,logName,logMessage) {
    return {
      "labels": {
        "ax.schemas.logging.level": logLevel,
        // Here we add a custom label (as an example)
        "com.mycompany.event": "colorChange"
      }
      "logName": logName,
      "payload": {
        "message": logMessage,
      }
    }	
}

What about the insert time and all the other labels?

The ActyxOS Console Service automatically adds properties to the log object you publish. Refer to the advanced guide for more information.

Now, we need to write the publishLog function. This function will take a log object and publish it to the Console Service using the HTTP API.

const CONSOLE_SERVICE_LOGS_ENDPOINT = 'http://localhost:4457/api/v1/logs';

function publishLog(logObject) {
  fetch(CONSOLE_SERVICE_LOGS_ENDPOINT, {
    method: 'POST',
    body: JSON.stringify(logObject),
    headers: {'Content-Type': 'application/json'}
  })
}

Finally, we will adjust the setColor function to build and publish the log object whenever it is called.

function setColor(newColor) {
  var el = document.getElementById("myText");
  el.style.color = newColor;

  // Create the log message
  var logMessage = `Color was changed to ${newColor}.`;
  // Create the log object
  var logObject = mkLog('info','ColorChanges',logMessage);
  // Publish the log
  publishLog(logObject);
}

Now, whenever the end-user sets the color, a structured log will automatically be published. How do you now access these logs? Let’s have a look.

Accessing logs

Logs generated by your application can be accessed using the Actyx CLI using the ax logs command.

Imagine your app was running on a device named MyEdgeDevice1. We would be able to access the logs generated by your app using the following command:

$ ax logs --tail --local EdgeDevice1 | jq
> {
    "insertId": "<automatically-added>",
    "insertTimestamp": "<automatically-added>",
    "labels": {
        "ax.schemas.logging.level": "info",
        "ax.schemas.logging.producer.sourceId": "<automatically-added>",
        "ax.schemas.logging.producer.sourceName": "<automatically-added>",
        "ax.schemas.logging.producer.appId": "<automatically-added>",
        "ax.schemas.logging.producer.appName": "<automatically-added>",
        "ax.schemas.logging.producer.appVersion": "<automatically-added>",
        "ax.schemas.logging.producer.dockerTag": "<automatically-added>"
        // Your labels
        // ...
    },
    // Your log name
    "logName": "<log-name>",
    // Your payload
    "payload": {
        // ...
    }
}

Piping to jq

In the above example, we piped the result of the command to the jq tool. We did this to have the returned JSON object pretty-printed for us in the terminal. If you wanted to perform an analysis of your logs, you would not need to do that.

Learn more

Or, jump to the next section and learn about how you should be thinking when building apps for ActyxOS.