Skip to content

DS_CAP_APP_LOG

Denis Stepanov edited this page Oct 15, 2020 · 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 was open), 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
System::app_log_size_max Maximum size of the log (B) 1048576

The file system used is LittleFS. It is possible to change to SPIFFS with manual one-line change in the library. LittleFS was observed to make controller more responsive in general, and is a recommended choice.

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 prefix the log entry with time (if enabled), add a newline and write it to the 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 log rotation logic will not work correctly (this may change in future). You would also need to take care of timestamping yourself.

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.

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

#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.

See Also

Clone this wiki locally