Skip to content

DS_CAP_APP_LOG

Denis Stepanov edited this page Sep 4, 2023 · 17 revisions

DS_CAP_APP_ID — Application Log and Log Browser

Description

This capability adds support for an application log stored on a file system. Application log, as opposed to syslog, is designed to report events of importance for end user (like the fact that a door has been opened), not internals like the fact that controller time was synchronized, or some debug output.

The following user-settable parameters are supported:

Field Description Default Value
size_t System::app_log_size_max Maximum size of the log (B) 1048576

The log is implemented as a pair of files named /applog.txt and /applog2.txt. /applog.txt is the log currently being written; /applog2.txt is an older rotated copy. The log file is allowed to grow up to System::app_log_size_max / 2 bytes; after that it gets rotated. Setting System::app_log_size_max to 0 at run-time stops the logging.

It is usually not a good practice to fill up the file system, so some space on disk (50 kiB) is reserved. This also permits storing some small files along with the log, such as a configuration file, or a favicon for the web server. The reserved space value is harcoded in the library, and may be changed manually before compilation. The library checks the actually available file system size on startup, so if the file system minus reserved space happens to be less than the configured maximum log size, the latter is adjusted accordingly.

To avoid overhead on file opening and closing, the currently written log is held constantly open; flush() is executed every time a new line is written in the log. Some guidelines discourage this practice, however, no specific problem was observed with either SPIFFS or LittleFS. Currently open file handle is available as File System::app_log; however, care should be taken if manipulating it directly, as it may confuse the rest of the logger logic.

There is only one method available to write to the log, which takes a String object:

bool System::appLogWriteLn(const String& line, bool copy_to_syslog = false);

This method will trim the line, prefix the log entry with time (if enabled), add a final newline and write the resulting line to the log file. Set copy_to_syslog to true to send the same line to syslog. Direct writes to the log, like System::app_log.println(...), are possible, but discouraged, since the log rotation logic will not work correctly (this may change in future). You would also need to take care of timestamping yourself.

line is generally expected to be a single line. If you need to log multiple lines, call the method several times. It is not uncommon, however, to send to the log a message originating from elsewhere (e.g., from a third-party library), which could be potentially multi-line. This is supported transparently: multiple lines with proper prefixes will be logged. Windows newlines (CR+LF) will be converted to Unix style (LF) before writing.

Log rotation is done as a part of System::update() method. Internal counter is used, so the check is very light; no interaction with file system happens unless there is a need to rotate the file. If log rotation fails for some reason, the logging gets disabled.

One important feature of this capability is a built-in log browser (requires web server to be turned on). The browser shows the latest entries by default and allows navigation to earlier records. Logs are displayed by small pages of a size which more or less conveniently fits smartphone screen (roughly 1 kiB). Rotated part of the log is transparently supported.

Application Log on Web

Requires

Cooperates With

  • DS_CAP_SYS_LOG — if syslog is enabled, one can use copy_to_syslog parameter to echo the log line into syslog;
  • DS_CAP_SYS_TIME — if time is enabled, log entries will be timestamped. Also, application startup timestamp will be logged on a first time synchronization event (in the case of NTP, this usually happens 1-2 seconds after system boot);
  • DS_CAP_WEBSERVER — if web server is enabled, additional /log page will be served, providing web browsing of the log. Also, "System Information" page will display current and max log size numbers;
  • DS_CAP_WIFIMANAGER — if Wi-Fi manager is enabled, network reconfiguration by user will be logged.

Conflicts With

None.

Usage

MySystem.h:

#define DS_CAP_APP_LOG      // Enable application log
#define DS_CAP_SYS_FS       // Enable file system (where log is stored)
#define DS_CAP_SYS_NETWORK  // Enable network (needed for web server and time sync)
#define DS_CAP_SYS_TIME     // Enable system time (to have timestamps in the log)
#define DS_CAP_WEBSERVER    // Enable web server (to have a log browser)

#define DS_TIMEZONE TZ_Europe_Paris  // Timezone

#include "System.h"         // System global definitions

sketch.ino:

#include "MySystem.h"

using namespace ds;

void setup() {
    System::begin();

    String msg = "Hello, world!";
    System::appLogWriteLn(msg);
}

void loop() {
    System::update();
}

Mandatory Calls

System::begin() Required
System::update() Required

Examples

Bugs

  • Maximum log file size is not strictly enforced, and may overshoot by a few bytes;
  • Direct operations with the log file object may confuse the logger.

Availability

Version 1.0 or later. Multi-line messages are supported from version 1.2.

See Also