Cursor Rules — unpoller/unpoller

Application: Collect ALL UniFi Controller, Site, Device & Client Data - Export to InfluxDB or Prometheus

6/19/2026 · 17 viewsCursor rules

← Browse

UnPoller - Cursor AI Rules

Project Overview

UnPoller is a Go application that collects metrics from UniFi network controllers and exports them to various backends (InfluxDB, Prometheus, Loki, DataDog). The architecture is plugin-based with input and output plugins.

Architecture

Core Components

  • main.go: Entry point, loads plugins via blank imports
  • pkg/poller/: Core library providing input/output interfaces and plugin management
  • pkg/inputunifi/: Input plugin for UniFi controller data collection
  • pkg/influxunifi/: Output plugin for InfluxDB
  • pkg/promunifi/: Output plugin for Prometheus
  • pkg/lokiunifi/: Output plugin for Loki
  • pkg/datadogunifi/: Output plugin for DataDog
  • pkg/webserver/: Web server for health checks and metrics
  • pkg/mysqlunifi/: MySQL output plugin

Plugin System

  • Plugins are loaded via blank imports (_ "github.com/unpoller/unpoller/pkg/inputunifi")
  • Input plugins implement the Input interface from pkg/poller/inputs.go
  • Output plugins implement the Output interface from pkg/poller/outputs.go
  • The poller core automatically discovers and initializes imported plugins
  • Configuration is automatically unmarshaled from config files (TOML/JSON/YAML) and environment variables

Code Style & Conventions

Go Standards

  • Use Go 1.25.5+ features
  • Follow standard Go formatting (gofmt)
  • Use golangci-lint with the project's .golangci.yaml configuration
  • Enable linters: nlreturn, revive, tagalign, testpackage, wsl_v5
  • Use //nolint:gci for import ordering when needed

Naming Conventions

  • Package names should be lowercase, single word
  • Exported types/functions use PascalCase
  • Unexported types/functions use camelCase
  • Constants use PascalCase with descriptive names
  • Error variables should be named err and checked immediately

Error Handling

  • Always check errors, don't ignore them
  • Use github.com/pkg/errors for error wrapping when appropriate
  • Return errors from functions, don't log and continue
  • Use descriptive error messages

Configuration

  • Configuration uses golift.io/cnfg and golift.io/cnfgfile
  • Environment variables use UP_ prefix (defined in ENVConfigPrefix)
  • Support TOML (default), JSON, and YAML formats
  • Config structs should have tags: json, toml, xml, yaml

Testing

  • Use testpackage linter - tests should be in separate _test packages
  • Use github.com/stretchr/testify for assertions
  • Integration tests use integration_test_expectations.yaml files

Logging

  • Use structured logging via logger interfaces
  • Log levels: ERROR, WARN, INFO, DEBUG
  • Prefix log messages with [LEVEL] when using standard log package

Dependencies

Key Libraries

  • github.com/unpoller/unifi/v5 - UniFi API client (local replace: /Users/briangates/unifi)
  • golift.io/cnfg - Configuration management
  • golift.io/cnfgfile - Config file parsing
  • github.com/spf13/pflag - CLI flag parsing
  • github.com/gorilla/mux - HTTP router
  • github.com/prometheus/client_golang - Prometheus metrics

Output Backends

  • InfluxDB: github.com/influxdata/influxdb1-client and github.com/influxdata/influxdb-client-go/v2
  • Prometheus: github.com/prometheus/client_golang
  • Loki: Custom HTTP client
  • DataDog: github.com/DataDog/datadog-go/v5

Project Structure

unpoller/
├── main.go                 # Entry point
├── pkg/
│   ├── poller/             # Core plugin system
│   ├── inputunifi/         # UniFi input plugin
│   ├── influxunifi/        # InfluxDB output
│   ├── promunifi/          # Prometheus output
│   ├── lokiunifi/          # Loki output
│   ├── datadogunifi/       # DataDog output
│   ├── mysqlunifi/         # MySQL output
│   └── webserver/          # Web server
├── examples/               # Configuration examples
├── init/                   # Init scripts (systemd, docker, etc.)
└── scripts/                # Build/deployment scripts

Common Patterns

Adding a New Output Plugin

  1. Create new package in pkg/ (e.g., pkg/myoutput/)
  2. Implement Output interface from pkg/poller/outputs.go
  3. Register plugin in init() function
  4. Add blank import to main.go
  5. Add configuration struct with proper tags
  6. Create README.md in package directory

Adding a New Input Plugin

  1. Create new package in pkg/ (e.g., pkg/myinput/)
  2. Implement Input interface from pkg/poller/inputs.go
  3. Register plugin in init() function
  4. Add blank import to main.go
  5. Add configuration struct with proper tags

Device Type Reporting

  • Device types: UAP, USG, USW, UDM, UBB, UCI, UXG, PDU
  • Each output plugin has device-specific reporting functions (e.g., uap.go, usg.go)
  • Follow existing patterns in pkg/promunifi/ or pkg/influxunifi/

Important Notes

  • The pkg/poller library is generic and has no knowledge of UniFi, Influx, Prometheus, etc.
  • It provides interfaces for any type of input/output plugin
  • Use []any types for flexibility in the core library
  • Configuration is automatically loaded from files and environment variables
  • The application supports multiple UniFi controllers via configuration
  • Timezone can be set via TZ environment variable

Build & Deployment

  • Uses GitHub Actions for CI/CD
  • Uses goreleaser for multi-platform builds
  • Supports: Linux, macOS, Windows, FreeBSD
  • Docker images built automatically
  • Homebrew formula for macOS
  • Configuration examples in examples/ directory

When Writing Code

  • Keep functions focused and single-purpose
  • Use interfaces for testability
  • Follow the existing plugin patterns
  • Document exported functions and types
  • Add appropriate error handling
  • Consider cross-platform compatibility (Windows, macOS, Linux, BSD)
  • Use context.Context for cancellable operations
  • Respect timeouts and deadlines

Source: unpoller/unpoller · 2643★ Repo: Application: Collect ALL UniFi Controller, Site, Device & Client Data - Export to InfluxDB or Prometheus