Skip to content

Chapter 8: System Information Collector

Overview

The SystemCollector (internal/collector/system.go) gathers environmental context: what OS is running, what kernel version, what filesystems are mounted, what block devices exist, and recent kernel errors from dmesg.

This data isn't about performance metrics — it's about context. An anomaly detection rule might fire differently on Ubuntu 20.04 with kernel 5.4 than on RHEL 9 with kernel 6.1.

Source File: system.go

  • Lines: 237
  • Functions: 9
  • Tier: 1 (always available)

Function Walkthrough

readOSRelease() — OS Identification

func (c *SystemCollector) readOSRelease() string {
    data, _ := os.ReadFile("/etc/os-release")
    for _, line := range strings.Split(string(data), "\n") {
        if strings.HasPrefix(line, "PRETTY_NAME=") {
            return strings.Trim(strings.TrimPrefix(line, "PRETTY_NAME="), "\"")
        }
    }
    return runtime.GOOS  // fallback: "linux"
}

Example: returns "Ubuntu 22.04.3 LTS" or "Debian GNU/Linux 12 (bookworm)".

Uptime Parsing

// /proc/uptime: "1234567.89 2345678.12"
//                ^uptime_sec  ^idle_time_all_cpus
parts := strings.Fields(raw)
uptime, _ := strconv.ParseFloat(parts[0], 64)
sysInfo.UptimeSeconds = int64(uptime)

Why uptime matters: A freshly rebooted server (uptime < 1 hour) may not have warmed its caches yet. Performance baselines should be taken after the system is warm.

collectFilesystems() — Disk Usage

func (c *SystemCollector) collectFilesystems(ctx context.Context) []model.FilesystemInfo {
    out, _ := exec.CommandContext(ctx, "df", "-P", "-T").Output()
    // -P: POSIX output format (no line wrapping)
    // -T: include filesystem type
    // Fields: Filesystem Type 1024-blocks Used Available Capacity Mounted
    fss = append(fss, model.FilesystemInfo{
        Mount:   fields[6],           // e.g. "/data"
        Device:  fields[0],           // e.g. "/dev/sda1"
        Type:    fields[1],           // e.g. "ext4"
        SizeGB:  sizeKB / 1024 / 1024, // KB → GB
        UsedPct: usedKB / sizeKB * 100,
    })
}

collectBlockDevices() — Hardware Detection

func (c *SystemCollector) collectBlockDevices() []model.BlockDevice {
    entries, _ := os.ReadDir("/sys/block/")
    for _, entry := range entries {
        name := entry.Name()
        // Size from sectors (512 bytes each)
        sizeStr := c.readFile(filepath.Join(basePath, "size"))
        sectors, _ := strconv.ParseInt(sizeStr, 10, 64)
        sizeGB := float64(sectors*512) / (1024 * 1024 * 1024)

        // SSD vs HDD
        rotStr := c.readFile(filepath.Join(basePath, "queue", "rotational"))
        devType := "ssd"
        if rotStr == "1" { devType = "hdd" }

        // Model name (if available)
        modelStr := c.readFile(filepath.Join(basePath, "device", "model"))
    }
}

collectDmesg() — Kernel Errors

func (c *SystemCollector) collectDmesg(ctx context.Context) []model.LogEntry {
    out, _ := exec.CommandContext(ctx, "dmesg", "--level=err,warn", "-T", "--nopager").Output()
    lines := strings.Split(string(out), "\n")
    // Take last 50 entries max
    // Classify each entry as "err" or "warn" based on content heuristics
}

What to look for in dmesg: | Pattern | Meaning | |---------|---------| | EXT4-fs error | Filesystem corruption | | EDAC ... CE | Correctable memory errors (ECC) | | EDAC ... UE | Uncorrectable memory errors — REPLACE RAM | | NMI: ... stuck | Hardware watchdog timeout | | Out of memory | OOM killer invoked | | CPU: ... microcode updated | CPU firmware update applied | | link ... down | Network link failure |

readSysctl*() — Kernel Parameters

Three helper functions read kernel tunables:

func readSysctlInt(procRoot, path string) int       { ... }
func readSysctlInt64(procRoot, path string) int64    { ... }
func readSysctlString(procRoot, path string) string  { ... }

These read files under /proc/sys/ — e.g., readSysctlInt(procRoot, "sys/vm/swappiness") reads /proc/sys/vm/swappiness.

These are shared by all collectors (they're package-level functions in system.go), used by Memory, Network, and CPU collectors.


Next: Chapter 9 — BCC Tools