- Add .cursorrules for Cursor AI - Add CLAUDE.md for Claude Code - Add AGENTS.md for universal AI agent context - Add .github/copilot-instructions.md for GitHub Copilot These files provide comprehensive context about the UnPoller project architecture, coding standards, and development patterns to help AI coding assistants understand and work with the codebase effectively.
6.8 KiB
UnPoller - Claude Code Context
Project Overview
UnPoller is a Go application that collects metrics and events from UniFi network controllers and exports them to various time-series databases and monitoring systems. The application uses a plugin-based architecture where input plugins collect data and output plugins export it to different backends.
Architecture
Core Design Principles
-
Plugin-Based Architecture: The core
pkg/pollerlibrary is generic and provides interfaces for input and output plugins. It has no knowledge of UniFi, InfluxDB, Prometheus, etc. -
Automatic Plugin Discovery: Plugins are loaded via blank imports in
main.go. The poller automatically discovers and initializes all imported plugins. -
Flexible Configuration: Supports TOML (default), JSON, and YAML configuration files, plus environment variables with
UP_prefix. -
Multiple Backends: Supports InfluxDB, Prometheus, Loki, DataDog, and MySQL as output backends.
Package Structure
pkg/
├── poller/ # Core plugin system - generic, no UniFi/backend knowledge
├── inputunifi/ # UniFi controller input plugin
├── influxunifi/ # InfluxDB output plugin
├── promunifi/ # Prometheus output plugin
├── lokiunifi/ # Loki output plugin
├── datadogunifi/ # DataDog output plugin
├── mysqlunifi/ # MySQL output plugin
└── webserver/ # Web server for health checks and metrics
Key Interfaces
Input Interface (pkg/poller/inputs.go):
GetMetrics()- Returns aggregated metricsGetEvents()- Returns events/logs- Plugins must implement this to provide data
Output Interface (pkg/poller/outputs.go):
WriteMetrics()- Writes metrics to backendWriteEvents()- Writes events to backend- Plugins must implement this to export data
Code Style Guidelines
Go Conventions
- Go Version: 1.25.5+
- Formatting: Use
gofmtstandard formatting - Linting: Follow
.golangci.yamlconfiguration- Enabled:
nlreturn,revive,tagalign,testpackage,wsl_v5 - Use
//nolint:gcifor import ordering exceptions
- Enabled:
Naming
- Packages: Lowercase, single word
- Exported: PascalCase (types, functions, constants)
- Unexported: camelCase
- Errors: Always named
err, checked immediately
Error Handling
// Good: Check and return errors
if err != nil {
return fmt.Errorf("operation failed: %w", err)
}
// Bad: Ignoring errors
_ = someFunction()
Configuration Pattern
type Config struct {
URL string `json:"url" toml:"url" yaml:"url"`
Interval string `json:"interval" toml:"interval" yaml:"interval"`
Timeout string `json:"timeout" toml:"timeout" yaml:"timeout"`
}
- Always include
json,toml,xml,yamltags - Environment variables use
UP_prefix automatically - Use
golift.io/cnfgfor configuration management
Testing
- Tests in separate
_testpackages (enforced bytestpackagelinter) - Use
github.com/stretchr/testifyfor assertions - Integration tests use
integration_test_expectations.yaml
Common Tasks
Adding a New Output Plugin
-
Create Package Structure:
package myoutput import ( "github.com/unpoller/unpoller/pkg/poller" ) type Output struct { // Configuration fields } func (o *Output) WriteMetrics(m *poller.Metrics) error { // Implementation } func (o *Output) WriteEvents(e *poller.Events) error { // Implementation } func init() { poller.RegisterOutput(&Output{}) } -
Add Blank Import to
main.go:_ "github.com/unpoller/unpoller/pkg/myoutput" -
Add Configuration to config structs with proper tags
-
Create README.md documenting usage
Adding Device Type Support
Each output plugin has device-specific files:
uap.go- Access Pointsusg.go- Security Gatewaysusw.go- Switchesudm.go- Dream Machinesuxg.go- Next-Gen Gatewaysubb.go- Building Bridgesuci.go- Industrial devicespdu.go- Power Distribution Units
Follow the pattern in existing files:
func (r *Report) UAP(uaps []*unifi.UAP) {
// Convert UniFi device data to output format
}
Working with UniFi Data
- UniFi library:
github.com/unpoller/unifi/v5(local replace at/Users/briangates/unifi) - Device types come from the UniFi controller API
- Data includes: sites, clients, devices, DPI data, speed tests, country traffic
- Events include: system logs, alarms, IDS events, anomalies
Dependencies
Core
github.com/unpoller/unifi/v5- UniFi API clientgolift.io/cnfg- Configuration managementgolift.io/cnfgfile- Config file parsinggithub.com/spf13/pflag- CLI flags
Output Backends
- InfluxDB:
github.com/influxdata/influxdb1-client(v1) andgithub.com/influxdata/influxdb-client-go/v2(v2) - Prometheus:
github.com/prometheus/client_golang - DataDog:
github.com/DataDog/datadog-go/v5 - Loki: Custom HTTP client implementation
Important Patterns
Plugin Registration
func init() {
poller.RegisterInput(&Input{})
// or
poller.RegisterOutput(&Output{})
}
Configuration Loading
Configuration is automatically loaded from:
- Config file (TOML/JSON/YAML) - path specified via
--configflag or defaults - Environment variables with
UP_prefix - CLI flags
Metrics Structure
type Metrics struct {
TS time.Time
Sites []any
Clients []any
SitesDPI []any
ClientsDPI []any
Devices []any
RogueAPs []any
SpeedTests []any
CountryTraffic []any
}
Events Structure
type Events struct {
Logs []any
}
Build & Deployment
- CI/CD: GitHub Actions
- Build Tool:
goreleaserfor multi-platform builds - Platforms: Linux, macOS, Windows, FreeBSD
- Docker: Images built automatically to
ghcr.io - Homebrew: Formula for macOS users
- Packages: Debian, RedHat packages via goreleaser
When Writing Code
- Keep it Generic: The
pkg/pollercore should remain generic - Follow Patterns: Look at existing plugins for examples
- Error Handling: Always check and return errors
- Cross-Platform: Consider Windows, macOS, Linux, BSD differences
- Context Usage: Use
context.Contextfor cancellable operations - Timeouts: Respect timeouts and deadlines
- Documentation: Document exported functions and types
- Testing: Write tests in separate
_testpackages
Configuration Examples
Configuration files support multiple formats. See examples/ directory:
up.conf.example- TOML formatup.json.example- JSON formatup.yaml.example- YAML format
Environment variables use UP_ prefix:
UP_INFLUX_URL=http://localhost:8086UP_UNIFI_DEFAULT_USER=adminUP_POLLER_DEBUG=true