Skip to content

Latest commit

 

History

History
295 lines (221 loc) · 11.4 KB

CONTRIBUTING.md

File metadata and controls

295 lines (221 loc) · 11.4 KB

Contributing & Execution Reference for ProcLens

Thank you for considering contributing to ProcLens! This document covers the development setup, project structure, contribution workflows, and instructions on how to configure and execute ProcLens across various environments (bare-metal, VMs, Docker, and Kubernetes).


Table of Contents

  1. Code of Conduct
  2. Ways to Contribute
  3. Development Setup
  4. Deployment & Execution Guide
  5. Project Structure
  6. Branch & Commit Conventions
  7. Adding a New Workload Archetype
  8. Pull Request Process
  9. Testing Requirements
  10. Code Style Guidelines
  11. Reporting Issues

Code of Conduct

All contributors are expected to follow the Code of Conduct. We are committed to keeping this a welcoming, respectful, and productive community.


Ways to Contribute

Contribution Type Examples
🐛 Bug Fix Address a panic, wrong classification, or incorrect recommendation
✨ New Feature Introduce a new archetype, LLM provider support, or CLI command
📖 Documentation Improve code comments, terminologies, guides, or this reference
🧪 Tests Add table-driven tests, fuzz target checks, or benchmark scenarios
🎨 UI/UX Refine the Google Material ANSI colours or console outputs
⚡ Performance Reduce latency or memory allocations during process discovery

Development Setup

To build and run ProcLens from source locally:

# 1. Fork the repo, then clone your fork
git clone https://github.com/<your-username>/proc-lens.git
cd proc-lens

# 2. Verify Go version is 1.24+
go version

# 3. Download dependencies
go mod download

# 4. Build the binary
go build -o proc-lens ./cmd/proc-lens

# 5. Run the full test suite
go test ./... -count=1

# 6. Run a quick smoke test
./proc-lens scan -d 1s

Deployment & Execution Guide

Modes: Local vs AI-Enriched

ProcLens operates in two distinct execution modes:

Mode A: Local Classification (Default / Offline)

All core subcommands (scan, analyze, run) run entirely locally.

  • Zero Outbound Connections: Requires no external network access, API keys, or heavy machine learning runtimes.
  • Low Overhead: Features are scaled and compared using a fast, absolute-difference distance model in under 10 microseconds per process.

Mode B: LLM-Augmented Diagnostics (Optional / Enriched)

The enrich subcommand overlays process classification telemetry with generative SRE diagnostics:

  • Enriched Analysis: Combines node coordinates (RAM, cores, kernel version) and process outputs, submitting them to a generative AI endpoint for diagnostic narratives.
  • Supported Backends: Gemini, OpenAI, Claude, xAI (Grok), and self-hosted local Ollama instances.

Platform Compatibility

Telemetry collection adapts to host platform support and capabilities:

Telemetry Attribute Linux VM (Root) Linux VM (User) Windows VM macOS VM Container (Docker/K8s)
CPU / RSS / Threads Yes Yes Yes Yes Yes
Voluntary/Involuntary Ctx Yes Yes No No Yes
Open FD Counts Yes Only Own Yes Yes Yes
Socket Fast Path Yes Only Own No (Fallback) No (Fallback) Yes (via SYS_PTRACE)
Parent PID & Name Yes Yes Yes Yes Yes
Linux OOM Score & Adj Yes Yes No No Yes
cgroups (v1/v2) Paths Yes Yes No No Yes
Kubernetes Metadata No No No No Yes (via /var/log/containers)

Note: If a metric is unsupported (e.g. OOM scores on Windows) or blocked by permissions (e.g. scanning another user's file descriptors as a non-root user), ProcLens degrades gracefully, defaults the fields to 0/empty, and continues execution.


Running Locally

Scan all running processes (One-shot):

./proc-lens scan -c 0.1 -m 5.0 -d 1s

Calculates process activity rates over a 1-second window and lists active processes consuming >0.1% CPU or >5.0 MB RAM.

Scan in continuous loop mode (Daemon/Top-like dashboard):

./proc-lens scan --loop --interval 10s

In loop mode, rates are estimated using cached metrics from the previous iteration to eliminate double-sampling overhead.

Profile a specific process PID:

./proc-lens analyze --pid 1024 --duration 2s

Profile a launched command:

./proc-lens run --cmd "tar -czf backup.tar.gz /var/log" --duration 3s --allow-run

Run AI-enriched diagnostics:

  • Set your API key and include the mandatory --allow-remote-llm security gate flag.
export GEMINI_API_KEY="your-gemini-key"
./proc-lens enrich --top 5 --allow-remote-llm
  • Or query a local Ollama instance (no remote security flag or API keys required):
./proc-lens enrich --endpoint "http://localhost:11434/v1/chat/completions" --model "llama3" --top 5

Running in Docker

Because the container runs as the unprivileged user nobody (UID 65534), you must share the host's PID namespace and mount /proc and /sys to introspect the host:

docker run -d --name proc-lens \
  --pid=host --cap-add=SYS_PTRACE \
  -v /proc:/host/proc:ro -v /sys:/host/sys:ro \
  -e HOST_PROC=/host/proc -e HOST_SYS=/host/sys \
  proc-lens:latest

Running in Kubernetes

To run as a DaemonSet to gather process intelligence from every worker node:

Step 1: Configure values

Verify that the Helm chart configuration (deploy/proc-lens/values.yaml) runs without root privileges:

hostNetwork: false
podSecurityContext:
  runAsUser: 65534
  runAsGroup: 65534
  fsGroup: 65534
securityContext:
  privileged: false
  readOnlyRootFilesystem: true
  allowPrivilegeEscalation: false
  runAsNonRoot: true
  capabilities:
    add:
      - SYS_PTRACE
    drop:
      - ALL

Step 2: Deploy

# Lint chart templates
helm lint deploy/proc-lens

# Deploy deployment agent
helm upgrade --install proc-lens deploy/proc-lens --namespace kube-system

Step 3: Telemetry & Prometheus Scraping

  • Health Check: Port 8091 exposes /healthz for liveness and readiness audits.
  • Scraping Endpoint: Exposes low-cardinality Prometheus metrics /metrics (e.g. process count per category) to prevent TSDB index bloat.

Production Readiness Checklist

  1. Least-Privilege Bounds: Ensure containers drop all capabilities, disable privilege escalation, and only request CAP_SYS_PTRACE.
  2. HTTP Hardening: Supply --http-bearer-token to secure metrics endpoints in production environments.
  3. Ingress Bounds: Set NetworkPolicy to allow incoming traffic only from designated Prometheus collector namespaces.
  4. Command-Line Security: Keep --expose-cmdline=false in production deployment flags to prevent environment variables and passwords from leaking to metrics logs.

Project Structure

proc-lens/
├── cmd/proc-lens/          # Main entrypoint (main.go)
├── pkg/
│   ├── classifier/         # 37-archetype absolute-difference classifier
│   │   ├── types.go        # Category constants (one per archetype)
│   │   ├── centroids.go    # Reference feature vectors per archetype
│   │   ├── classifier.go   # Predict() + rule boosters
│   │   └── classifier_test.go
│   ├── collector/          # /proc telemetry collection (gopsutil)
│   ├── cmd/                # Cobra subcommands (scan, analyze, enrich, ...)
│   ├── optimizer/          # Kernel tuning recommendations + validation
│   ├── explain/            # "Why was this classified X?" explainer
│   ├── pressure/           # Linux PSI collection
│   ├── hardware/           # NUMA / storage / SIMD topology
│   ├── completeness/       # Data completeness score tracker
│   └── metrics/            # Prometheus low-cardinality metrics
├── deploy/proc-lens/       # Helm chart (DaemonSet)
├── .goreleaser.yml         # GoReleaser v2 release pipeline
├── terminologies.md        # Plain-English concept glossary
└── CONTRIBUTING.md         # This file

Branch & Commit Conventions

Branch naming format: feat/add-graphdb-archetype · fix/context-canceled-enrich · docs/update-readme-archetypes · test/fuzz-classifier-edge-cases

Commit messages must follow Conventional Commits:

  • feat(classifier): add GraphDB and TimeSeriesDB archetypes
  • fix(enrich): use gemini-flash-latest model alias
  • docs(readme): update archetype table to 37 categories
  • test(classifier): add table-driven tests for all new archetypes

Adding a New Workload Archetype

Adding an archetype involves editing exactly 4 files in this order:

  1. pkg/classifier/types.go: Add the Category constant inside the correct tier.
  2. pkg/classifier/centroids.go: Define typical profile values inside the Centroids map.
  3. pkg/classifier/classifier.go: Add name/cmdline boosters to adjust classifier weights.
  4. pkg/classifier/classifier_test.go: Add a table-driven test inside TestPredictNewArchetypes and register the category constant.
  5. Update README.md: Register the category in the Comparison and Archetypes tables.

Pull Request Process

  1. Fork the repository and create your branch from main.
  2. Ensure the full test suite passes: go test ./... -count=1.
  3. Ensure the project builds cleanly: go build ./....
  4. Document any new user-facing configuration options, commands, or behaviours.
  5. Open a Pull Request referencing the issue it addresses and outlining the design choices.

Testing Requirements

  • Verification Build: go build ./...
  • Test Verification: go test ./... -count=1
  • Fuzzing Checks: go test ./pkg/classifier -fuzz=FuzzPredict -fuzztime=30s
  • Performance Benchmarks: go test ./pkg/classifier -bench=. -run=^$

Code Style Guidelines

  • Adhere to standard Go styling guidelines (gofmt, go vet).
  • All tests should be table-driven and use t.Run() scopes.
  • Add package-level comment headers with Note: and Caveat: sections for new files.
  • Error messages should be lowercase and properly wrapped (e.g. "failed to read /proc/stat: %w").
  • Avoid informal phrasing ("kindly", "do the needful") in comments or documentation.

Reporting Issues

  • Use GitHub Issues to report bugs, suggest features, or ask questions.
  • Security vulnerabilities must be reported via GitHub's Private Security Advisory feature rather than a public ticket.