Skip to content

git-developer/symone

Repository files navigation

SYMONE

Key features

SYMONE performs system monitoring tasks:

  • Collect information, e.g. about cpu, memory, storage, temperature, containers

  • Format, e.g. convert to JSON or CSV

  • Publish, e.g. via MQTT

SYMONE is polite and reliable:

  • Runs in a Docker container to keep the system clean of dependencies

  • Does not need root permissions

  • Does her job regularly

Example

Let’s suppose that SYMONE runs on a Raspberry Pi with hostname raspberry using the following configuration:

compose.yml
services:
  symone:
    image: ghcr.io/git-developer/symone
    container_name: symone
    hostname: raspberry
    init: true
    restart: unless-stopped
    user: "1000:44"
    devices:
      - /dev/vchiq
    volumes:
      - "./collectors:/opt/symone/host-collectors:ro"
      - "/var/run/symone:/var/run/symone"
      - "/lost+found:/mnt/root:ro"
      - "/boot/System Volume Information:/mnt/boot:ro"
    environment:
      MQTT_OPTIONS: '-h broker-host'

Result: every 5 minutes, she publishes a JSON message via MQTT to topic /symone/raspberry/json on broker broker-host:

{
  "process": {
    "load": {
      "average1": 0.98,
      "average5": 0.94,
      "average15": 0.93
    },
    "memory": {
      "total": "996096 kB",
      "free": "98640 kB",
      "available": "672800 kB"
    }
  },
  "storage": {
    "boot": {
      "total": "262128 kB",
      "use": "49263 kB",
      "available": "212866 kB",
      "use_relative": "19 %"
    },
    "root": {
      "total": "14154680 kB",
      "use": "7550664 kB",
      "available": "5999948 kB",
      "use_relative": "56 %"
    }
  },
  "thermal": {
    "cpu-thermal": {
      "temperature": "54.768 °C"
    }
  },
  "video-core": {
    "soc": {
      "temperature": "53.7 °C"
    },
    "core": {
      "voltage": "1.2938 V"
    }
  }
}

Pre-requisites

  • A linux system with Docker Compose.

The Docker Compose documentation contains a comprehensive guide explaining several install options. On Debian-based systems, Docker Compose may be installed by calling

$ sudo apt install docker-compose-v2

Usage

  • Create a configuration file compose.yml (see the examples and docs for an inspiration)

  • Optionally, when the host collector is used:

    • Add one or more collector scripts in ./collectors

    • Install and start the symone-host-service

  • Start SYMONE by calling docker compose up -d

Features

  • Collectors:

    • Process: cpu load, memory

    • Storage: storage use

    • Thermal: system temperatures

    • Video Core: temperature, voltage

    • Host: user-configurable info prepared on the Docker host

  • Formatters:

    • JSON

    • CSV

  • Publishers:

    • MQTT

    • stdout

  • Scheduling using a CRON expression

Configuration

Docker options

Option Description Example Default Explanation

user

Linux user and group

1000:44

none (effectively: root)

This option is useful when statistics require a certain user or group. Example: In Pi OS (formerly Raspbian), user pi (uid 1000) in group video (gid 44) has permission to read video core statistics.

devices

Devices for monitoring

/dev/vchiq

none

This option is useful when statistics require access to a system device. Example: On a Raspberry Pi, /dev/vchiq is required to read video core statistics.

volumes

Volumes for storage monitoring

/lost+found:/mnt/root:ro

none

Storage statistics are collected automatically for anything within /mnt/. You don’t have to mount a complete partition; it is enough to mount a single file or directory that may be read-only or even unreadable by the running user.

hostname

Hostname

nas

none (effectively: hostname generated by Docker)

The hostname is used as part of the MQTT topic when the option MQTT_TOPIC_APPEND_HOSTNAME is enabled.

extra_hosts

Additional host names

broker-host:host-gateway

none

When the MQTT broker is running on the same host as SYMONE, the host has to be declared as host-gateway.

Environment variables

Scheduling

Option Description Example Default

TZ

Timezone

Europe/Berlin

none

SCHEDULE

Schedule (a CRON expression)

* * * * *

*/5 * * * * (every 5 minutes)

Formatting

Option Description Example Default

FORMAT_JSON

Enable JSON format

true, false

true

FORMAT_CSV

Enable CSV format

true, false

false

FORMAT_CSV_SEPARATOR

Item separator for CSV format

:

,

Publishing

Option Description Example Default

PUBLISH_STDOUT

Publish to stdout

true, false

false

PUBLISH_MQTT

Publish via MQTT

true, false

true

MQTT_OPTIONS

MQTT options

-h broker-host

none

MQTT_TOPIC

MQTT topic

system-statistics

symone

MQTT_TOPIC_APPEND_HOSTNAME

Append hostname to MQTT topic

true, false

true

MQTT_TOPIC_APPEND_FORMAT

Append format to MQTT topic

true, false

true

Collecting

Option Description Example Default

COLLECTOR_PROCESS

Collect info about system processes

true, false

true

COLLECTOR_PROCESS_LOAD

Collect info about system load

true, false

true

COLLECTOR_PROCESS_MEMORY

Collect info about system memory

true, false

true

COLLECTOR_PROCESS_ROOT

Root directory for process info

/proc

/proc

COLLECTOR_STORAGE

Collect info about storage

true, false

true

COLLECTOR_STORAGE_ROOT

Root directory for storage

/mnt

/mnt

COLLECTOR_THERMAL

Collect info about thermal

true, false

true

COLLECTOR_THERMAL_ROOT

Root directory for thermal info

/sys/devices/virtual/thermal

/sys/devices/virtual/thermal

COLLECTOR_THERMAL_TYPE

Group thermal info by type

true, false

true

COLLECTOR_THERMAL_ZONE

Group thermal info by zone

true, false

false

COLLECTOR_VIDEO_CORE

Collect video core info

true, false

true

COLLECTOR_HOST

Collect info read from the host

true, false

true

Debugging

Option Description Example Default

DEBUG

Enable debug log output

true, false

false

TRACE

Enable trace log output

true, false

false

Host collector

SYMONE contains an optional feature to collect info that is not available within the container. A common use case are statistics about all Docker containers running on the host.

To use this feature, you have to add two volumes and enable the symone-host-service.

Volumes

compose.yml
---
services:
  symone:
    volumes:
      - '/var/run/symone:/var/run/symone'
      - './collectors:/opt/symone/host-collectors:ro'

/var/run/symone is a working directory that is used internally for communication between container and host.

./collectors is a directory for custom collectors. A collector is an executable that is run by the symone-host-service on the host. Its output is parsed and sent to publishers. Each line of output is expected to contain one or more keys and a trailing value. Non-executable files are skipped.

Example Configuration Published output

Simple command

./collectors/simple
echo timestamp "$(date -u -Is)"
{ "timestamp": "2025-04-13T10:42:34+00:00" }

Multiple values

./collectors/multiple-values
for roll in first second; do
  printf 'dice %s-roll %s\n' \
    "${roll}" "$(shuf -i 1-6 -n 1)"
done
{
  "dice": {
    "first-roll":3,
    "second-roll":5
  }
}

Post processing

./collectors/post-processing
set -a
LANG=C df -t tmpfs -h \
| tail -n +2 \
| while read fs total used available usage mountpoint; do
  for field in total used available; do
    printf 'tempfs-usage %s %s %s\n' \
      "${mountpoint}" "${field}" "$(printenv "${field}")"
  done
done
{
  "tempfs-usage": {
    "/run": {
      "total": "1,6G",
      "used": "5,5M",
      "available": "1,6G"
    },
    "/dev/shm": {
      "total": "7,8G",
      "used": 0,
      "available": "7,8G"
    },
    "/run/lock": {
      "total": "5,0M",
      "used": 0,
      "available": "5,0M"
    }
  }
}

Container statistics

./collectors/container-statistics
#!/bin/sh
set -eua
fields='cpu_usage
        memory_usage memory_limit
        network_read network_written
        block_read block_written
        pid_count'
LANG=C
docker stats --no-stream --format \
  "{{.Name}} {{.CPUPerc}} {{.MemUsage}} {{.NetIO}} {{.BlockIO}} {{.PIDs}}" \
| sed "s/kB\s/KB /g;s:/::g;s/\s\+/ /g" \
| numfmt --suffix B --field=3-8 --to-unit=1024 --from=auto --padding=1 \
| sed "s/B /kB /g" \
| while read -r container_name ${fields}; do
  for field in ${fields}; do
    printf '%s %s %s %s\n' \
      "containers" "${container_name}" "${field}" "$(printenv "${field}")"
  done
done
{
  "containers": {
    "symone": {
      "cpu_usage": "0.00%",
      "memory_usage": "5.465MiB",
      "memory_limit": "32MiB",
      "network_read": "4.28kB",
      "network_written": "8.41kB",
      "block_read": "0B",
      "block_written": "0B"
    }
}

Quoted values

./collectors/quoted-values
cat - <<'EOF'
a "b" 'c d' $'e\nf'
EOF
{
  "a": {
    "b": {
      "c d": "e\nf"
    }
  }
}

SYMONE Host Service

Commands configured for the host collector are executed by the symone-host-service. It is running on the host and listening for requests from the container.

To download and install the symone-host-service to systemd, run

$ wget -O- https://github.com/git-developer/symone/raw/refs/heads/main/symone-host-service \
  | install /dev/stdin ./symone-host-service \
  && sudo ./symone-host-service systemd-install

This will create, enable and start a minimal service unit in /etc/systemd/system that persists across boots. To uninstall it, run

$ sudo ./symone-host-service systemd-uninstall

It is possible to use the symone-host-service without systemd. It is a self-contained executable that offers subcommands to start, stop and show the status.

FHEM integration

This section contains an example configuration to integrate SYMONE with FHEM.

  • Example for an MQTT broker running on broker-host:1883:

    define mosquitto MQTT2_CLIENT broker-host:1883
    
    define mqtt_symone_raspberrypi MQTT2_DEVICE
    attr   mqtt_symone_raspberrypi readingList symone/raspberrypi/json:.* { json2nameValue($EVENT) }
    attr   mqtt_symone_raspberrypi stateFormat video-core_soc_temperature

Advanced topics

One-shot run

  • Trigger an immediate one-shot publish while SYMONE is running in a container named symone:

    $ docker compose exec symone take-sample
  • Example for a one-shot run to stdout (no MQTT) when SYMONE is not running:

    $ docker compose run --rm -e PUBLISH_MQTT=false -e PUBLISH_STDOUT=true symone take-sample

Extending SYMONE

SYMONE is prepared to be extended by additional collectors, formatters and publishers. To add something, simply mount a file or directory into the respective directory of the container.

Additional collectors

  1. Put an executable file within the directory collect. This file is a collector.

  2. When SYMONE calls a collector, it may emit 0..n items by calling ${COLLECTOR_PUBLISHER} for each item and hand over the item as arguments:

    • The last argument is treated as value of the item.

    • The last but one argument is treated as name of the item.

    • All preceding items are treated as group(s) for the item.

Additional formatters

  1. Put an executable file within the directory format. This file is a formatter. The formatter’s filename is used as format id.

  2. When SYMONE calls a formatter, she hands over all collected items as arguments. Parts of an item are separated by spaces, quoted as required. Item parts may contain spaces, newlines and special characters.

  3. The formatter is expected to print the formatted message to standard out.

Additional publishers

  1. Put an executable file within the directory publish. This file is a publisher.

  2. When SYMONE calls a publisher, she hands over two arguments:

    1. The format id

    2. The formatted message

  3. The publisher may publish the message.

Components

SYMONE integrates the following applications and libraries:

About

SYMONE allows SYstem MONitoring with Ease.

Resources

License

Stars

Watchers

Forks

Packages