Skip to content

Application Logging

Application Log Format

A log collector, called Fluent Bit, is used within the HCC2. It expects logs in a particular format to be processed fully.

Currently only text logs are supported.

In general, an application running on the HCC2 must log the log message in the following format:

[version][YYYY-MM-DDThh:mm:ss.sssZ][loggerName][logLevel]log message

Example:

[0][2024-02-14T19:43:00.999Z][SR_CSAPP][error]Failed to connect to Modbus Server 127.0.0.1:502

Where:

  • version: version number for the log format. This format is version 0.

  • [YYYY-MM-DDThh🇲🇲ss.sssZ] is timestamp. It specifies the time when the log message is generated. It is in UTC time, not local time.

Info

To see the message with local time for easy debugging, add a compile-time switch to use a separate implementation of the logger functionality.

  • loggerName: Free text to identify your application or application sub function. It can be the module / application name e.g. configurationManager or RPC etc. or if it is deemed fit it can be a functionality name within the single application. E.g. a developer may want to log a message for a file access failure. Now they can use this section to differentiate from where this error is generated within the same application. E.g initConfig, initConnection, runtimeCommsCallbackup, diagsPollTime...

Warning

It is strongly recommended to keep the logger names relatively short (12 characters maximum, or risk formatting issues) and to use camelCase.

  • logLevel: Valid levels (in words) are

    • critical: The application cannot perform and requires user intervention: for example, memory allocation or port binding failed.
    • error: The application may not work correctly or might produce the wrong result: for example, continuous Modbus timeouts resulting in the connection being closed.
    • warning: A warning to the user, with this present the application, it can perform properly but this may require user attention to avoid future errors or damage. E.g. disk 80% full.
    • info: Informative message. Normally, the info level is disabled in the system. When enabled, it provides information about the application's working state and status. For example, the web server is working on port 3000, or the application is in auto mode.
    • debug: Debugging information that can be used in the field. Using debug mode, the field engineer can gain insight into the system and correct errors.
    • trace: The lowest log level. Debug should be used only be developers when working on the application. It can be used in place of printf or the console log and should not usually be left in production code
  • log message: Concise, appropriate text to include any values that warranted a message

Rules for logging

DO

  • Make sure each log is self contained and informative.
  • Use the lowest appropriate log level.
  • Consider using a less severe log level if something can happen often such as timeouts.
  • In the event of a repeated timeout leading to a “failed” state and a single warning or error, consider a programmatic mechanism to transition the application back into a retry state.
  • Log its version upon startup, and if it started up successfully as warning.
  • Set the application's log level via an environment variable called LOGLEVEL at startup using the levels defined above (in lowercase) ie LOGLEVEL=info. Use the value in the application.
  • Strive to have the application output a total of 3 logs during their lifecycle higher than info when working normally:
    • Startup & version, Configuration success, Shutdown.
  • Adhere to the above defined format, every new line shall contain one complete, self contained log in the above format.

DO NOT

  • Output separators, headers or other attempts to grab attention or delineate logs:
    • Logs are parsed/interpreted line by line, these multi-line outputs appear as garbage/clutter for the user.
    • If they are of such great value to the developer, then they can be enabled through a compile option or environment variable, but must be off by default.
  • Output the entirety of your configuration as info logs. If this is useful/necessary, put it as debug or trace:
    • It is acceptable to output unexpected failures to parse as info or warning.
  • Output unexpected but ‘normal’ behavior as a warning, this is info or debug. For example, a Modbus client experiencing a timeout. There are other mechanisms for conveying to the user this info (diagnostic tags).
  • Output logs that depend on the previous log for context, refer to “self contained and informative” rule:
    • For example, “attempting to connect to server” followed by “ok”.
  • Override log level rules set via the environment variable. If a log is deemed “info” do not output it when the log level is set higher than info:
    • It is tempting to set a log level based on if the name ‘feels right’, but they have a job to do - filter information to the user. If a user absolutely needs to see a log under normal conditions, even if it is ‘informative’, set it as a warning, not a ‘special info'. For example, put the startup message/version as a warning.
  • Generate logs continuously at the info level or higher when operating normally:
    • Info will be seen by end users and is intended to convey information about ‘useful information’.
    • Use debug for things that happen occasionally but do repeat.
    • Use trace for things that happen continuously.