Contributing¶
This guide covers the development workflow, tooling, and conventions for contributing to opnsense2otel.
This page is the canonical contribution guide. The repository root CONTRIBUTING.md is a short pointer to this page — edit only this file; do not duplicate content into the root file.
Prerequisites¶
- Go - Check
go.modfor the required version (currently Go 1.27) - just 1.58+ - For build automation
- golangci-lint - Optional; runs in CI but can be used locally
- Docker - Optional; for container builds
Getting started¶
Clone the repository:
Build commands¶
| Command | Description |
|---|---|
just setup | Install repo-local release tooling and warm the module cache |
just build | Build the binary (static, version-embedded) |
just test | Run the full test suite under the race detector |
just fmt | Rewrite Go and justfile formatting |
just lint | Report golangci-lint findings without mutating source |
just check | Run the bare-toolchain pre-commit gate |
just ci | Add the Docker and cross-compilation CI legs when those prerequisites are available |
just sync-vendor | go mod tidy && go mod vendor |
just clean | Remove reproducible build output |
Building on macOS¶
just build uses the same static-link flags as CI. If your local toolchain cannot support them, use this instead:
Running a single test¶
Project conventions¶
Vendor directory¶
The vendor directory is committed to the repository. Always run just sync-vendor after modifying go.mod:
Static binary¶
The build produces a fully static binary with:
CGO_ENABLED=0-ldflags "-s -w"for stripped, optimized output-trimpathand-mod=vendorfor reproducibility
Version¶
The version is embedded at build time via -ldflags -X main.version=.... The version.txt file at the repository root is managed by release-please and tracks the current released version; GoReleaser embeds the git tag as the version in release builds, while local just build builds embed local-test.
Linters¶
The project uses golangci-lint with:
gosec,misspell, andreviveenabledunuseddisabled
Linting runs in CI. Locally, just fmt rewrites formatting and just lint only reports findings (the golangci-lint step may fail if the tool is not installed, which is expected).
Commit messages¶
This project uses conventional commits for automated changelog generation via release-please:
feat(collector): add new subsystem collector
fix(kea): handle disabled DHCP service response
docs: update README with new collector descriptions
refactor: modernize Go syntax patterns
Changelog¶
Release history lives entirely in CHANGELOG.md, generated by release-please from conventional commit messages. There is no separate "changes from upstream" section to maintain — do not add one to README.md; it was deliberately removed and conventional commit messages are what drive the changelog instead.
Pull request checklist¶
Before submitting a PR, run just check. It is the bare-toolchain pre-commit gate; run just ci too when Docker and cross-compilation are available. If generated artifacts changed, run just gen and commit the resulting diff.
-
just checkpasses - Generated artifacts are current:
just genwas run when needed and its diff is committed — never hand-edit content between<!-- docgen:begin/end -->markers - Vendor is synced when dependencies changed:
just sync-vendor - Conventional commit messages used
- New collectors follow the adding a collector guide
CI additionally verifies the container image, its embedded version, Compose contracts, and a disposable kind cluster (docker-build); the local just ci superset runs the plain image and deployment legs.
Project structure¶
.
+-- main.go # Entry point
+-- internal/
| +-- collector/ # Prometheus collectors
| | +-- collector.go # Top-level collector, interface
| | +-- arp_table.go # Per-subsystem collector files
| | +-- gateways.go
| | +-- ...
| +-- options/ # CLI flags and configuration
| | +-- ops.go # OPNsense connection config
| | +-- exporter.go # Server config
| | +-- collectors.go # Collector enable/disable switches
| +-- logship/ # Syslog + Zenarmor receivers, log enrichment, OTLP log sink
| | +-- syslog/ # Per-program syslog parsers
| | +-- zenarmor/ # Zenarmor HTTP receiver
| | +-- enrich/ # Device/service enrichment
| | +-- flowlog/ # Sink for internal/flow's correlated flow logs
| | +-- ...
| +-- flow/ # NetFlow receiver, rollup, correlator
| | +-- netflow/ # NetFlow wire decode + listener
| | +-- correlate.go # NetFlow + Zenarmor conn merge
| | +-- ...
| +-- webui/ # Operator console served at /
| | +-- server.go # Route registration, self-registering tabs
| | +-- status.go
| | +-- ...
| +-- metricsnap/ # Passive metric capture, teed at both scrape sites
| +-- recorder.go
+-- opnsense/ # API client
| +-- client.go # HTTP client, TLS, retries
| +-- gateways.go # Per-subsystem Fetch methods
| +-- ...
+-- deploy/ # Deployment manifests
| +-- k8s/ # Kubernetes manifests
+-- grafana/ # Grafana dashboard builder, panels, alert rules
+-- docs/ # Documentation (this site)
+-- vendor/ # Vendored dependencies