Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.24'

- name: Format check
run: |
Expand All @@ -29,7 +29,7 @@ jobs:

- name: Install golangci-lint
run: |
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.61.0
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.64.8
Comment thread
vyruss marked this conversation as resolved.
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH

- name: Lint Go code
Expand Down Expand Up @@ -257,7 +257,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.24'

- name: Install PostgreSQL
run: |
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ radar uses the following exit codes:

### Prerequisites

- **Go**: 1.23 or higher
- **Go**: 1.24 or higher
- **Git**: For version control
- **golangci-lint**: For linting (install via `go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest`)
- **Docker**: For integration testing (optional but recommended)
Expand Down
61 changes: 61 additions & 0 deletions DATA.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,67 @@ These collectors only run on Linux systems.
| `system/tuned/tuned-list.out` | `tuned-adm list` | Available tuned profiles |
| `system/vmstat-command.out` | `vmstat 1 10` | Virtual memory statistics (10 samples) |

### Cgroup v2 Resource Limits (Linux)

Attempted on Linux (skipped if unavailable). Shows actual container resource limits instead of host values.

| File | Source | Description |
|------|--------|-------------|
| `system/cgroup/cpu_max.out` | `/sys/fs/cgroup/cpu.max` | CPU bandwidth limit (quota/period) |
| `system/cgroup/cpu_weight.out` | `/sys/fs/cgroup/cpu.weight` | CPU weight (relative share) |
| `system/cgroup/cpuset_cpus_effective.out` | `/sys/fs/cgroup/cpuset.cpus.effective` | Effective CPU set |
| `system/cgroup/io_max.out` | `/sys/fs/cgroup/io.max` | I/O bandwidth limits |
| `system/cgroup/memory_current.out` | `/sys/fs/cgroup/memory.current` | Current memory usage |
| `system/cgroup/memory_max.out` | `/sys/fs/cgroup/memory.max` | Memory limit |
| `system/cgroup/memory_stat.out` | `/sys/fs/cgroup/memory.stat` | Detailed memory statistics |
| `system/cgroup/memory_swap_max.out` | `/sys/fs/cgroup/memory.swap.max` | Swap limit |
| `system/cgroup/pids_current.out` | `/sys/fs/cgroup/pids.current` | Current number of PIDs |
| `system/cgroup/pids_max.out` | `/sys/fs/cgroup/pids.max` | PID limit |

### Cgroup v1 Resource Limits (Linux)

Attempted on Linux (skipped if unavailable). Present on older kernels (pre-cgroup v2 unified hierarchy).

| File | Source | Description |
|------|--------|-------------|
| `system/cgroup-v1/cpu_cfs_period_us.out` | `/sys/fs/cgroup/cpu/cpu.cfs_period_us` | CFS scheduling period |
| `system/cgroup-v1/cpu_cfs_quota_us.out` | `/sys/fs/cgroup/cpu/cpu.cfs_quota_us` | CFS CPU quota (-1 = unlimited) |
| `system/cgroup-v1/cpu_shares.out` | `/sys/fs/cgroup/cpu/cpu.shares` | CPU shares (relative weight) |
| `system/cgroup-v1/cpuset_cpus.out` | `/sys/fs/cgroup/cpuset/cpuset.cpus` | Allowed CPUs |
| `system/cgroup-v1/memory_limit_in_bytes.out` | `/sys/fs/cgroup/memory/memory.limit_in_bytes` | Memory limit |
| `system/cgroup-v1/memory_stat.out` | `/sys/fs/cgroup/memory/memory.stat` | Detailed memory statistics |
| `system/cgroup-v1/memory_usage_in_bytes.out` | `/sys/fs/cgroup/memory/memory.usage_in_bytes` | Current memory usage |

### Cloud/Hardware Identity (Linux)

Attempted on Linux (skipped if unavailable). Identifies cloud provider and instance type via DMI data.

| File | Source | Description |
|------|--------|-------------|
| `system/cloud/bios_vendor.out` | `/sys/class/dmi/id/bios_vendor` | BIOS vendor (e.g. Amazon EC2, Google) |
| `system/cloud/chassis_asset_tag.out` | `/sys/class/dmi/id/chassis_asset_tag` | Chassis asset tag (e.g. AWS instance ID) |
| `system/cloud/product_name.out` | `/sys/class/dmi/id/product_name` | Product name (e.g. instance type) |
| `system/cloud/sys_vendor.out` | `/sys/class/dmi/id/sys_vendor` | System vendor |

### Container Identity (Linux)

Attempted on Linux (skipped if unavailable). Helps identify container runtime and environment.

| File | Source | Description |
|------|--------|-------------|
| `system/container/cgroup_membership.out` | `/proc/1/cgroup` | Cgroup membership (container signatures) |
| `system/container/mountinfo.out` | `/proc/1/mountinfo` | PID 1 mount info (overlay detection) |

### Container Detection (Linux, auto-detected)

Only collected when running inside a container (Docker, Kubernetes, LXC, containerd).

| File | Source | Description |
|------|--------|-------------|
| `system/container/dockerenv.out` | `test -f /.dockerenv` | Docker container detection |
| `system/container/environment.out` | `env \| grep` | Allowlisted env vars: `HOSTNAME`, `CONTAINER_ID`, `DOCKER_HOST`, `ECS_CLUSTER`, `ECS_CONTAINER_METADATA_URI`, `KUBERNETES_SERVICE_HOST`, `KUBERNETES_SERVICE_PORT`, `KUBERNETES_PORT` |
| `system/container/k8s_namespace.out` | `/run/secrets/.../namespace` | Kubernetes namespace |
Comment thread
vyruss marked this conversation as resolved.

---

## macOS-Specific System Collectors
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ For a complete reference of all collected data, see [docs/data.md](docs/data.md)
- **Operating system**: `apt`, `dnf`, `dpkg`, `hostname`, `hosts`, `limits.conf`, `locale`, `locale.conf`, `localectl`, `lsmod`, `lspci`, `machine-id`, `os-release`, `ps`, `rpm`, `system-release`, `systemctl`, `systemd-detect-virt`, `timedatectl`, `tuned-adm`, `uname`, `yum`
- **Network**: `ifconfig`, `ip`, `netstat`, `resolv.conf`, `ss`
- **Security**: `fips-mode-setup`, `openssl`, `sestatus`, `update-crypto-policies`
- **Cgroup v2**: `cpu.max`, `cpu.weight`, `cpuset.cpus.effective`, `io.max`, `memory.current`, `memory.max`, `memory.stat`, `memory.swap.max`, `pids.current`, `pids.max`
- **Cgroup v1**: `cpu.cfs_period_us`, `cpu.cfs_quota_us`, `cpu.shares`, `cpuset.cpus`, `memory.limit_in_bytes`, `memory.stat`, `memory.usage_in_bytes`
- **Cloud/hardware identity**: `bios_vendor`, `chassis_asset_tag`, `product_name`, `sys_vendor` (DMI)
- **Container detection** (auto-detected): cgroup membership, mount info, Docker detection, Kubernetes namespace, container environment variables

**PostgreSQL Instance**

Expand Down Expand Up @@ -219,7 +223,7 @@ radar-hostname-20260115-133700.zip

- **System**: Linux with standard utilities (lsblk, mount, df, ps, etc.)
- **PostgreSQL**: Version 12+ (some features require 13+, 14+, or 16+)
- **Go**: 1.23+ (for building from source - see [CONTRIBUTING.md](CONTRIBUTING.md))
- **Go**: 1.24+ (for building from source - see [CONTRIBUTING.md](CONTRIBUTING.md))

## Performance

Expand Down
53 changes: 53 additions & 0 deletions container_linux_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//go:build linux

/*-------------------------------------------------------------------------
*
* radar
*
* Portions copyright (c) 2026, pgEdge, Inc.
* This software is released under The PostgreSQL License
*
*-------------------------------------------------------------------------
*/

package main

import (
"os"
"testing"
)

func TestIsContainer(t *testing.T) {
_, err := os.Stat("/.dockerenv")
dockerExists := err == nil
got := isContainer()
if dockerExists && !got {
t.Fatalf("isContainer() = false, want true when /.dockerenv exists")
}
if !dockerExists && got {
t.Fatalf("isContainer() = true, want false on non-container host")
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

func TestContainerCommandTasksStructure(t *testing.T) {
for i, task := range containerCommandTasks {
if task.Name == "" {
t.Errorf("containerCommandTasks[%d] missing Name", i)
}
if task.ArchivePath == "" {
t.Errorf("containerCommandTasks[%d] (%s) missing ArchivePath", i, task.Name)
}
if task.Command == "" {
t.Errorf("containerCommandTasks[%d] (%s) missing Command", i, task.Name)
}
}
}

func TestContainerCommandTasksAlphabeticalOrder(t *testing.T) {
for i := 1; i < len(containerCommandTasks); i++ {
if containerCommandTasks[i].Name < containerCommandTasks[i-1].Name {
t.Errorf("containerCommandTasks not alphabetically ordered: %q comes after %q",
containerCommandTasks[i].Name, containerCommandTasks[i-1].Name)
}
}
}
61 changes: 61 additions & 0 deletions docs/data.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,67 @@ These collectors only run on Linux systems.
| `system/tuned/tuned-list.out` | `tuned-adm list` | Available tuned profiles |
| `system/vmstat-command.out` | `vmstat 1 10` | Virtual memory statistics (10 samples) |

### Cgroup v2 Resource Limits (Linux)

Attempted on Linux (skipped if unavailable). Shows actual container resource limits instead of host values.

| File | Source | Description |
|------|--------|-------------|
| `system/cgroup/cpu_max.out` | `/sys/fs/cgroup/cpu.max` | CPU bandwidth limit (quota/period) |
| `system/cgroup/cpu_weight.out` | `/sys/fs/cgroup/cpu.weight` | CPU weight (relative share) |
| `system/cgroup/cpuset_cpus_effective.out` | `/sys/fs/cgroup/cpuset.cpus.effective` | Effective CPU set |
| `system/cgroup/io_max.out` | `/sys/fs/cgroup/io.max` | I/O bandwidth limits |
| `system/cgroup/memory_current.out` | `/sys/fs/cgroup/memory.current` | Current memory usage |
| `system/cgroup/memory_max.out` | `/sys/fs/cgroup/memory.max` | Memory limit |
| `system/cgroup/memory_stat.out` | `/sys/fs/cgroup/memory.stat` | Detailed memory statistics |
| `system/cgroup/memory_swap_max.out` | `/sys/fs/cgroup/memory.swap.max` | Swap limit |
| `system/cgroup/pids_current.out` | `/sys/fs/cgroup/pids.current` | Current number of PIDs |
| `system/cgroup/pids_max.out` | `/sys/fs/cgroup/pids.max` | PID limit |

### Cgroup v1 Resource Limits (Linux)

Attempted on Linux (skipped if unavailable). Present on older kernels (pre-cgroup v2 unified hierarchy).

| File | Source | Description |
|------|--------|-------------|
| `system/cgroup-v1/cpu_cfs_period_us.out` | `/sys/fs/cgroup/cpu/cpu.cfs_period_us` | CFS scheduling period |
| `system/cgroup-v1/cpu_cfs_quota_us.out` | `/sys/fs/cgroup/cpu/cpu.cfs_quota_us` | CFS CPU quota (-1 = unlimited) |
| `system/cgroup-v1/cpu_shares.out` | `/sys/fs/cgroup/cpu/cpu.shares` | CPU shares (relative weight) |
| `system/cgroup-v1/cpuset_cpus.out` | `/sys/fs/cgroup/cpuset/cpuset.cpus` | Allowed CPUs |
| `system/cgroup-v1/memory_limit_in_bytes.out` | `/sys/fs/cgroup/memory/memory.limit_in_bytes` | Memory limit |
| `system/cgroup-v1/memory_stat.out` | `/sys/fs/cgroup/memory/memory.stat` | Detailed memory statistics |
| `system/cgroup-v1/memory_usage_in_bytes.out` | `/sys/fs/cgroup/memory/memory.usage_in_bytes` | Current memory usage |

### Cloud/Hardware Identity (Linux)

Attempted on Linux (skipped if unavailable). Identifies cloud provider and instance type via DMI data.

| File | Source | Description |
|------|--------|-------------|
| `system/cloud/bios_vendor.out` | `/sys/class/dmi/id/bios_vendor` | BIOS vendor (e.g. Amazon EC2, Google) |
| `system/cloud/chassis_asset_tag.out` | `/sys/class/dmi/id/chassis_asset_tag` | Chassis asset tag (e.g. AWS instance ID) |
| `system/cloud/product_name.out` | `/sys/class/dmi/id/product_name` | Product name (e.g. instance type) |
| `system/cloud/sys_vendor.out` | `/sys/class/dmi/id/sys_vendor` | System vendor |

### Container Identity (Linux)

Attempted on Linux (skipped if unavailable). Helps identify container runtime and environment.

| File | Source | Description |
|------|--------|-------------|
| `system/container/cgroup_membership.out` | `/proc/1/cgroup` | Cgroup membership (container signatures) |
| `system/container/mountinfo.out` | `/proc/1/mountinfo` | PID 1 mount info (overlay detection) |

### Container Detection (Linux, auto-detected)

Only collected when running inside a container (Docker, Kubernetes, LXC, containerd).

| File | Source | Description |
|------|--------|-------------|
| `system/container/dockerenv.out` | `test -f /.dockerenv` | Docker container detection |
| `system/container/environment.out` | `env \| grep` | Allowlisted env vars: `HOSTNAME`, `CONTAINER_ID`, `DOCKER_HOST`, `ECS_CLUSTER`, `ECS_CONTAINER_METADATA_URI`, `KUBERNETES_SERVICE_HOST`, `KUBERNETES_SERVICE_PORT`, `KUBERNETES_PORT` |
| `system/container/k8s_namespace.out` | `/run/secrets/.../namespace` | Kubernetes namespace |
Comment thread
vyruss marked this conversation as resolved.

---

## macOS-Specific System Collectors
Expand Down
4 changes: 4 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ For a complete reference of all collected data, see [data.md](data.md).
- **Operating system**: `apt`, `dnf`, `dpkg`, `hostname`, `hosts`, `limits.conf`, `locale`, `locale.conf`, `localectl`, `lsmod`, `lspci`, `machine-id`, `os-release`, `ps`, `rpm`, `system-release`, `systemctl`, `systemd-detect-virt`, `timedatectl`, `tuned-adm`, `uname`, `yum`
- **Network**: `ifconfig`, `ip`, `netstat`, `resolv.conf`, `ss`
- **Security**: `fips-mode-setup`, `openssl`, `sestatus`, `update-crypto-policies`
- **Cgroup v2**: `cpu.max`, `cpu.weight`, `cpuset.cpus.effective`, `io.max`, `memory.current`, `memory.max`, `memory.stat`, `memory.swap.max`, `pids.current`, `pids.max`
- **Cgroup v1**: `cpu.cfs_period_us`, `cpu.cfs_quota_us`, `cpu.shares`, `cpuset.cpus`, `memory.limit_in_bytes`, `memory.stat`, `memory.usage_in_bytes`
- **Cloud/hardware identity**: `bios_vendor`, `chassis_asset_tag`, `product_name`, `sys_vendor` (DMI)
- **Container detection** (auto-detected): cgroup membership, mount info, Docker detection, Kubernetes namespace, container environment variables

**PostgreSQL Instance**

Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module radar

go 1.23
go 1.24

require github.com/lib/pq v1.10.9

require github.com/DATA-DOG/go-sqlmock v1.5.2 // indirect
require github.com/DATA-DOG/go-sqlmock v1.5.2
1 change: 1 addition & 0 deletions postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ func execPGQueryOnDB(dbname string, cfg *Config, query string, w io.Writer) erro
return rowsToTSV(rows, w)
}

// printSummary logs the archive filename, size, and collector count.
func printSummary(totalCollected int, outputFile string, cfg *Config) {
stat, err := os.Stat(outputFile)
if err != nil {
Expand Down
Loading
Loading