Skip to content

Configuration JSON

Eduard Mishkurov edited this page Jul 28, 2026 · 12 revisions

JSON Configuration Format

This page documents the JSON fields supported by the current parser in Config.cpp, ParseChannel.cpp, ParseFlags.cpp, ParseSubsystem.cpp, ParseHomeDirectory.cpp, ParseControl.cpp, and backend-specific *Config::Parse() implementations.

The loader is intentionally strict about type errors. If a known field is present with the wrong type, LoadConfiguration() fails and, in the current API, can also return a textual reason through the optional std::string* error parameter.

Loading model

Logger::LoadConfiguration() parses JSON only when the library is built with USE_JSONCPP. Without that option the function fails with JSON configuration support is not enabled.

The loader first selects the requested section, then parses these parts in order:

  1. control
  2. structured_fields
  3. flags
  4. channels
  5. subsystems
  6. home-directory

After parsing, it creates channels and backends, replaces the active channel set, applies subsystem filters, updates the home directory and watchdog, and starts the control server if requested. If channel creation partially fails, the configuration may still have been parsed, but LoadConfiguration() returns false because the parsed configuration could not be applied.

Top-level sections

The parser currently recognizes these top-level sections:

{
  "control": {},
  "home-directory": {},
  "structured_fields": {},
  "flags": {},
  "channels": [],
  "subsystems": {}
}

All of them are optional. An empty configuration is valid, though it usually does not change anything useful.

control

The JSON parser for control configures only the built-in TCP control server and local discovery metadata. It is intentionally not the full control-server runtime API.

Supported fields:

  • enable — boolean
  • port — integer
  • interface — string
  • discovery.enable — boolean
  • discovery.namePrefix — string

The accepted interface names are loopback, 127.0.0.1, any, all, the empty string, or a concrete IPv4 address accepted by inet_addr().

Example:

{
  "control": {
    "enable": true,
    "interface": "loopback",
    "port": 49000,
    "discovery": {
      "enable": true,
      "namePrefix": "logme-discovery-"
    }
  }
}

control.discovery is used by tools such as logmeweb to discover local processes and connection metadata. Discovery does not expose the control password.

The current JSON parser does not parse pass, password, cert, or key. Password and TLS support exist in the control server API, but they must be configured from application code or other runtime paths, not through this JSON block.

If enable is true but port remains zero, the parser logs a warning and disables the control interface.

home-directory

home-directory.path sets the logger home directory. Relative file names used by file backends are resolved against this directory. The value is passed through ProcessTemplate(), so template placeholders can be used.

The optional watch-dog object configures directory cleanup:

{
  "home-directory": {
    "path": "logs",
    "watch-dog": {
      "enable": true,
      "max-size": "512Mb",
      "check-periodicity": "30s",
      "file-extension": [".log"]
    }
  }
}

Supported watchdog fields are enable, max-size, check-periodicity, and file-extension. Sizes may be integers or strings with supported byte-size suffixes. Intervals may be integers or strings with supported time suffixes.

See Size and interval values below for the exact suffix syntax.

The watchdog is not a per-file rotation mechanism. It monitors total size in the home directory for configured extensions and deletes old matching files that are not currently in use by registered FileBackend instances.

structured_fields

Structured output field names are global. The parser accepts these keys, case-insensitively after normalization in ParseFlags.cpp:

{
  "structured_fields": {
    "timestamp": "time",
    "level": "severity",
    "process_id": "pid",
    "thread_id": "tid",
    "channel": "channel",
    "subsystem": "subsystem",
    "file": "file",
    "line": "line",
    "method": "method",
    "message": "message",
    "duration": "duration"
  }
}

processid and threadid are also accepted aliases. Unsupported structured field names are logged as warnings and ignored. A supported field with a non-string value is an error.

These names affect Context::ApplyJson() and Context::ApplyXml(). They do not rename fields in text output.

Size and interval values

Several JSON fields accept either an integer or a string with a suffix. Integer byte-size values are interpreted as bytes. Integer interval values are interpreted as milliseconds.

Byte-size strings are parsed by Logme::GetByteSize() / Logme::ParseByteSize(). Supported suffixes are case-insensitive:

Suffixes Meaning
b bytes
Kb, Kib, K 1024 bytes
Mb, Mib, M 1024 * 1024 bytes
Gb, Gib, G 1024 * 1024 * 1024 bytes

Interval strings are parsed by Logme::GetInterval() / Logme::ParseInterval(). Supported suffixes are case-insensitive:

Suffixes Meaning
ms, millisecond, milliseconds milliseconds
s, sec, second, seconds seconds
m, min, minute, minutes minutes
h, hour, hours hours
d, day, days days
w, week, weeks weeks

Examples:

{
  "max-size": "64Mb",
  "queue-byte-limit": "8Mb",
  "timeout": "10s",
  "check-periodicity": "5min"
}

The same parser is used by runtime control commands. The reverse formatting helpers are documented in Utility Helpers.

flags

flags is a map of named OutputFlags presets. Each preset starts from zero because ParseFlags() explicitly sets f.Value = 0 before applying fields. This is different from the default OutputFlags() constructor used by channels when no preset is selected.

Example:

{
  "flags": {
    "text-default": {
      "timestamp": "local",
      "signature": true,
      "method": true,
      "eol": true,
      "highlight": true
    },
    "json-file": {
      "timestamp": "utc",
      "signature": true,
      "threadid": true,
      "channel": true,
      "subsystem": true,
      "format": "json",
      "eol": true
    }
  }
}

Boolean fields: signature, method, eol, errorprefix, duration, threadid, processid, channel, highlight, disablelink, transition, subsystem.

String-valued fields:

  • timestamp: none, local, tz, utc
  • location: none, short, full
  • console: cout, warncerr, errcerr, cerrcerr, cerr
  • format: text, json, xml

A preset can inherit another preset by using inherit with the parent preset name. Inheritance copies the already parsed parent, so the parent must appear before the child in the parsed map.

Unsupported flag values are warnings, not hard errors. Wrong JSON types for known fields are errors.

channels

channels must be an array of objects. Each channel object requires name. The empty string represents the default channel.

Supported channel fields are:

  • name — string, required
  • flags — string name of a preset from flags
  • level — string level filter
  • enable — boolean
  • backends — array of backend objects
  • link — string target channel name
  • platform — optional gating field
  • build — optional gating field

Example:

{
  "channels": [
    {
      "name": "",
      "flags": "text-default",
      "backends": [
        { "type": "ConsoleBackend" }
      ]
    },
    {
      "name": "file",
      "flags": "json-file",
      "level": "debug",
      "backends": [
        {
          "type": "FileBackend",
          "file": "app.log",
          "append": true,
          "rotation": "daily",
          "max-size": "64Mb",
          "on-size-limit": "rotate",
          "archive": "archive/app.{date}.{index}.log",
          "compression": "gz",
          "retention": {
            "max-files": 7,
            "max-age": "30d",
            "max-total-size": "1Gb",
            "clean-on-start": true
          }
        }
      ]
    }
  ]
}

The parser uses backend type ids exactly as Backend::Create() expects: ConsoleBackend, DebugBackend, FileBackend, SharedFileBackend, BufferBackend, RingBufferBackend, CallbackBackend, and WindowsEventLogBackend.

Channel creation happens in two passes. The first pass creates channel objects and applies backend configs. The second pass resolves links between the newly created channels. After that ReplaceChannels() replaces the active set. If the configuration did not provide a default channel, CreateDefaultChannelLayout(false) restores the default console layout.

Backend-specific fields

FileBackend

The current FileBackendConfig::Parse() supports:

  • file — string, required;
  • append — boolean, default true;
  • max-size — integer or size string, default FileBackend::GetMaxSizeDefault(); see Size and interval values;
  • on-size-limit — string: truncate or rotate;
  • archive — archive file pattern used by rotation; required for on-size-limit: "rotate" and must contain {index};
  • rotation — string: none, off, disabled, hourly, daily, weekly, or monthly;
  • max-parts — legacy integer alias for retention.max-files, default 2;
  • compression — string: gz, gzip, none, off, disabled, or an empty string;
  • retention.max-files — maximum number of matching completed archives to keep;
  • retention.max-age — maximum age for matching completed archives, using interval syntax;
  • retention.max-total-size — maximum total size of matching completed archives;
  • retention.clean-on-start — boolean controlling whether retention runs when the backend is configured.

By default, max-size keeps the historical truncate behavior. To archive completed files instead, set on-size-limit to rotate and provide an archive pattern.

Retention applies to completed archive files, not to the active file. max-parts remains supported for compatibility. If both max-parts and retention.max-files are specified, they must have the same value.

Gzip compression depends on the USE_ZLIB CMake option. When zlib support is not compiled in, compression: "gz" is accepted but has no effect.

See File Rotation & Retention for examples and operational details.

WindowsEventLogBackend

The current WindowsEventLogBackendConfig::Parse() supports:

  • source — string used as the Windows Event Log source; when omitted, the backend uses the current executable base name
  • event-id — unsigned integer event id, default 1000
  • category — unsigned integer category in the 16-bit range, default 0
  • common backend fields such as async, when supported by the backend

The backend supports async delivery through the Windows Event Log manager. On non-Windows platforms the backend remains build-compatible, but it does not write to Windows Event Log.

CallbackBackend

CallbackBackend supports only the common backend fields parsed by BackendConfig. JSON can create the backend object, but it cannot configure the callback function pointer or userData; application code must install them with SetCallback().

ConsoleBackend

ConsoleBackendConfig::Parse() supports the common backend fields and, when console async support is enabled in the build, these console queue fields:

  • async — boolean
  • queue-record-limit — integer maximum number of queued console records
  • queue-byte-limit — integer or size string maximum queued console bytes; see Size and interval values
  • overflow-policy — string: block, drop-new, or drop-oldest

These settings affect the process-wide console manager behavior used by asynchronous console output.

RingBufferBackend

RingBufferBackendConfig::Parse() supports:

  • max-items — positive integer number of recent records to keep

Other built-in backends

DebugBackend and BufferBackend have their own config classes. When a backend config page documents a field, it should be checked against the corresponding *BackendConfig.cpp, not inferred from the backend name.

Platform/build gating

Both channel objects and backend objects may contain platform and build. If the gate does not match the current runtime/build, the entry is skipped. A wrong type is an error.

This is useful for configurations that include Windows-only debugger output or different console/file choices for CI builds. It is not a comment mechanism; skipped entries are not created.

subsystems

Subsystem configuration controls three independent mechanisms:

  • blocked — named subsystems that are always rejected;
  • allowed — when non-empty, only named subsystems in this list are permitted;
  • levels — per-subsystem severity thresholds that replace channel levels for matching records.
{
  "subsystems": {
    "blocked": ["NOISE"],
    "allowed": ["DSL", "CLOUD"],
    "levels": {
      "DSL": "DEBUG",
      "CLOUD": "WARN"
    }
  }
}

blocked, allowed, and the legacy list field must be arrays of strings. levels must be an object whose keys are non-empty subsystem names and whose values are supported level-name strings. Level names are parsed case-insensitively.

A subsystem level replaces the channel level; it is not combined with it. For example, DSL: DEBUG can allow DEBUG records through an INFO channel, while CLOUD: WARN rejects INFO records that the same channel would normally accept. Blocked/allowed filtering still has priority over level selection.

Each successful configuration load replaces the complete subsystem state. If levels is absent, previously configured subsystem level overrides are cleared. Invalid types, empty subsystem names, and unsupported levels make subsystem configuration parsing fail.

The legacy fields remain accepted:

{
  "subsystems": {
    "block-listed": true,
    "list": ["http"]
  }
}

With block-listed: true, list is applied as the blocked list. With block-listed: false, it is applied as the allowed list. New configurations should use explicit blocked and allowed fields.

See Subsystems and Subsystem Level Overrides.

Getting Started

Practical Runbooks

Architecture

Output & Formatting

Backends

Runtime Control

Tools

Reference

Examples

Clone this wiki locally