Commit Graph

4921 Commits

Author SHA1 Message Date
dependabot[bot]
a70e52180d build(deps): bump goreleaser/goreleaser-action in the all group (#961)
Bumps the all group with 1 update: [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action).


Updates `goreleaser/goreleaser-action` from 6 to 7
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](https://github.com/goreleaser/goreleaser-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: goreleaser/goreleaser-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-07 14:41:33 -06:00
Brian Gates
074595c0a9 Fix remote API (Fabric/API key): 429 handling, NVR filter, updateWeb nil panic (#958) 2026-02-18 06:34:04 -05:00
dependabot[bot]
4bf5c1e6b5 build(deps): bump the all group with 2 updates (#955)
Bumps the all group with 2 updates: [golang.org/x/crypto](https://github.com/golang/crypto) and [golang.org/x/term](https://github.com/golang/term).


Updates `golang.org/x/crypto` from 0.47.0 to 0.48.0
- [Commits](https://github.com/golang/crypto/compare/v0.47.0...v0.48.0)

Updates `golang.org/x/term` from 0.39.0 to 0.40.0
- [Commits](https://github.com/golang/term/compare/v0.39.0...v0.40.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.48.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: golang.org/x/term
  dependency-version: 0.40.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
v2.34.0
2026-02-17 18:20:37 -06:00
Brian Gates
40e2a7703f Fix panic when remote discovery fails and no controllers configured (fixes #953) (#957)
* Fix panic when remote discovery fails and no controllers are configured

Call setDefaults(&u.Default) before logController(&u.Default) when
len(u.Controllers) == 0 so HashPII, DropPII, etc. are initialized
and logController does not dereference nil pointers.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore: trigger CI re-run

Co-authored-by: Cursor <cursoragent@cursor.com>

* ci: use golangci-lint v2.9 for Go 1.26-compatible deps

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 18:13:25 -06:00
dependabot[bot]
eae3741120 build(deps): bump the all group with 2 updates (#950)
Bumps the all group with 2 updates: [github.com/DataDog/datadog-go/v5](https://github.com/DataDog/datadog-go) and [github.com/unpoller/unifi/v5](https://github.com/unpoller/unifi).


Updates `github.com/DataDog/datadog-go/v5` from 5.8.2 to 5.8.3
- [Release notes](https://github.com/DataDog/datadog-go/releases)
- [Changelog](https://github.com/DataDog/datadog-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/DataDog/datadog-go/compare/v5.8.2...v5.8.3)

Updates `github.com/unpoller/unifi/v5` from 5.17.0 to 5.18.0
- [Release notes](https://github.com/unpoller/unifi/releases)
- [Commits](https://github.com/unpoller/unifi/compare/v5.17.0...v5.18.0)

---
updated-dependencies:
- dependency-name: github.com/DataDog/datadog-go/v5
  dependency-version: 5.8.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
- dependency-name: github.com/unpoller/unifi/v5
  dependency-version: 5.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-09 08:56:37 -06:00
Brian Gates
b4fa16b2fd fix(influxunifi): use CelsiusSafe() for temp fields to fix InfluxDB type conflict (#944) (#945)
* fix(influxunifi): use CelsiusSafe() for temp fields to fix InfluxDB type conflict

Write temp_* fields as float64 instead of int64 so InfluxDB does not
report 'field type conflict' when the measurement already has float.

Requires github.com/unpoller/unifi/v5 with CelsiusSafe() (unpoller/unifi#195).
Fixes #944.

Co-authored-by: Cursor <cursoragent@cursor.com>

* deps: unifi v5.17.0; nil guards and 429 retry (unpoller#943)

- Bump github.com/unpoller/unifi/v5 to v5.17.0 (CelsiusSafe, ErrNilUnifi, RateLimitError)
- inputunifi: guard pollController for nil c.Unifi; controllerID(c) in formatSites/Clients/Devices
- inputunifi: getUnifi retry with backoff on 429 (up to 5 attempts, Retry-After or exponential backoff)

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(influxunifi): expect temp_* as float after CelsiusSafe() (fix #944)

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
v2.33.0
2026-02-03 20:12:26 -06:00
dependabot[bot]
6488feff06 Bump docker/login-action from 3.6.0 to 3.7.0 in the all group (#942)
Bumps the all group with 1 update: [docker/login-action](https://github.com/docker/login-action).


Updates `docker/login-action` from 3.6.0 to 3.7.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3.6.0...v3.7.0)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 3.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-02 08:11:06 -06:00
Brian Gates
5ea7fcf736 feat: UPS battery metrics, example Prometheus/Loki alerts (unpoller#930) (#941) v2.32.0 2026-01-31 20:25:58 -06:00
Cody Lee
3eb7c1cf1d Merge pull request #940 from brngates98/feat/sysinfo-metrics
feat: add controller sysinfo metrics (unpoller#927)
v2.31.0
2026-01-31 19:27:09 -06:00
brngates98
ca568384d1 feat: add controller sysinfo metrics (unpoller#927)
- Add Sysinfo collection from stat/sysinfo endpoint
- Export controller_info, uptime, update_available, data retention, ports
- Hostname fallback: name, then site_name when API omits hostname
- Apply site name override to Sysinfo for remote/cloud
- Add Discover/Discoverer for endpoint discovery
- Require unpoller/unifi v5.15.0

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-31 20:25:56 -05:00
Cody Lee
bf2d1f7617 Merge pull request #939 from unpoller/upgrade-unifi-5-14-0
upgrade unifi
v2.30.0
2026-01-31 10:21:00 -06:00
Cody Lee
5e4a6cbef3 upgrade unifi 2026-01-31 10:19:38 -06:00
Cody Lee
9aba3101cd Merge pull request #938 from brngates98/restore-endpoint-discovery-tool
Restore tools/endpoint-discovery as optional Python tool
2026-01-30 20:32:51 -06:00
Brian Gates
adf9985675 Merge branch 'master' into restore-endpoint-discovery-tool 2026-01-30 21:30:47 -05:00
brngates98
4d19a9b2c8 Restore tools/endpoint-discovery as optional Python tool
Restores the browser-based endpoint discovery script that was
mistakenly removed in the Go --discover PR. Optional: use this for
broader discovery (XHR capture) or unpoller --discover for known endpoints.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-30 21:22:17 -05:00
Cody Lee
e3f1a8f7e0 Merge pull request #937 from brngates98/feat/discover-flag v2.29.0 2026-01-30 20:00:31 -06:00
brngates98
719b74627f deps: use unifi v5.13.0, remove replace and CI unifi checkout
- Require github.com/unpoller/unifi/v5 v5.13.0 (DiscoverEndpoints in release)
- Remove go.mod replace and workflow steps that cloned unifi for CI

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-30 20:58:10 -05:00
brngates98
8d3d983844 ci: checkout unifi discover-flag when go.mod has replace => ../unifi
So Build (test + lint) passes on PRs that depend on unifi with DiscoverEndpoints.
2026-01-30 20:19:05 -05:00
brngates98
9cfb732c11 Replace Python endpoint-discovery with --discover flag (replaces #936)
- Add --discover and --discover-output to unpoller; uses first unifi
  controller from config to probe known API endpoints and write a
  shareable markdown report.
- Add Discoverer interface and RunDiscover(); inputunifi implements
  Discoverer via unifi.DiscoverEndpoints.
- Remove tools/endpoint-discovery/ (Python/Playwright).
- Add docs/PR_936_REPLACEMENT.md. .gitignore: test config and report.

Requires unpoller/unifi with DiscoverEndpoints (replace in go.mod until
unifi release).
2026-01-30 20:17:00 -05:00
Cody Lee
fe23e85a21 Merge pull request #936 from brngates98/feat/endpoint-discovery-tool 2026-01-30 19:16:38 -06:00
brngates98
6be9312a1a Add tools/endpoint-discovery for controller API discovery
- Python script (Playwright) that logs in to UniFi controller and captures
  XHR/fetch requests to /api and /proxy/ endpoints
- Writes API_ENDPOINTS_HEADLESS_<date>.md in tool directory (easy for users)
- Helps debug 404s (e.g. device-tags #935): users can run and share output
- Optional, read-only; not required for building or running unpoller
2026-01-30 19:52:40 -05:00
Cody Lee
490ae4567a Merge pull request #934 from unpoller/upgrade-unifi-5-12-0
bump unifi version
v2.28.0
2026-01-30 11:50:54 -06:00
Cody Lee
a94b530adf bump unifi version 2026-01-30 11:48:00 -06:00
Cody Lee
11450439fc Merge pull request #925 from brngates98/feat/wan-metrics
feat: Add WAN metrics export to Prometheus, InfluxDB, and Datadog
v2.27.0
2026-01-29 16:50:47 -06:00
brngates98
b96606128d chore: Update go.sum for unifi v5.11.0 and fix formatting
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-29 17:37:33 -05:00
brngates98
af6cbdf79f chore: Update unifi dependency to v5.11.0 for WAN metrics support
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-29 17:36:03 -05:00
brngates98
b8519ca058 feat: Add WAN metrics to InfluxDB and Datadog exporters
Add comprehensive WAN metrics support to InfluxDB and Datadog exporters:

InfluxDB Metrics (measurement: wan):
- Configuration: failover_priority, load_balance_weight, provider_download_kbps,
  provider_upload_kbps, smartq_enabled, magic_enabled, vlan_enabled
- Statistics: uptime_percentage, peak_download_percent, peak_upload_percent,
  max_rx_bytes_rate, max_tx_bytes_rate
- Service Provider: service_provider_asn
- Metadata: creation_timestamp

Tags: wan_id, wan_name, wan_networkgroup, wan_type, wan_load_balance_type,
      isp_name, isp_city

Datadog Metrics (namespace: unpoller.wan.*):
- Same metrics as InfluxDB with gauge type
- All metrics tagged with WAN and ISP information

Changes:
- pkg/influxunifi/wan.go: New WAN exporter for InfluxDB
- pkg/influxunifi/influxdb.go: Add WAN to loopPoints and switchExport
- pkg/datadogunifi/wan.go: New WAN exporter for Datadog
- pkg/datadogunifi/datadog.go: Add WAN to loopPoints and switchExport

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-29 17:27:28 -05:00
brngates98
aac4917da7 feat: Add WAN metrics export to Prometheus
Add comprehensive WAN metrics support to unpoller:

WAN Configuration Metrics:
- wan_failover_priority: WAN failover priority
- wan_load_balance_weight: Load balancing weight
- wan_provider_download_kbps: Configured ISP download speed
- wan_provider_upload_kbps: Configured ISP upload speed
- wan_smartq_enabled: SmartQueue QoS status
- wan_magic_enabled: Magic WAN status
- wan_vlan_enabled: VLAN configuration status

WAN Statistics Metrics:
- wan_uptime_percentage: WAN uptime percentage
- wan_peak_download_percent: Peak download utilization
- wan_peak_upload_percent: Peak upload utilization
- wan_max_rx_bytes_rate: Maximum receive rate
- wan_max_tx_bytes_rate: Maximum transmit rate

WAN Service Provider Metrics:
- wan_service_provider_asn: ISP autonomous system number

Labels include:
- wan_id, wan_name, wan_networkgroup
- wan_type (dhcp, static, pppoe)
- wan_load_balance_type (weighted, failover-only)
- isp_name, isp_city (service provider metrics)
- site_name, source

Changes:
- pkg/poller/config.go: Add WANConfigs field to Metrics struct
- pkg/poller/inputs.go: Append WAN configs in metric aggregation
- pkg/inputunifi/input.go: Add WANConfigs field to Metrics struct
- pkg/inputunifi/collector.go: Fetch WAN enriched configuration
- pkg/promunifi/wan.go: New WAN metrics exporter
- pkg/promunifi/collector.go: Initialize and export WAN metrics

Depends on: unpoller/unifi PR (WAN API support)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-29 17:24:12 -05:00
Cody Lee
d178da7c75 Merge pull request #924 from brngates98/feat/dhcp-client-monitoring
feat: Add DHCP lease metrics export to Prometheus
v2.26.0
2026-01-29 16:12:31 -06:00
brngates98
86bc1c9d6d fix: rename unused exportWithTags param to _ to satisfy revive
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-29 17:07:43 -05:00
Brian Gates
39b1b316a2 Merge branch 'master' into feat/dhcp-client-monitoring 2026-01-29 17:04:00 -05:00
brngates98
8769f8f121 chore: bump unifi to v5.10.0
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-29 17:02:38 -05:00
brngates98
3faaa3a696 fix: Remove local replace directive and update unifi to v5.8.0 to resolve go.sum conflicts 2026-01-28 21:48:33 -05:00
brngates98
74c30eabe6 feat: Add DHCP lease metrics export to Prometheus
- Add DHCP lease fetching in inputunifi collector
- Create promunifi/dhcp_leases.go with network-level and per-lease metrics
- Network-level metrics: pool_size, active_leases, utilization_percent, free_percent, available_ips
- Per-lease metrics: is_static, lease_end, lease_start, lease_time
- Separate network-level pool metrics from per-lease metrics
2026-01-28 21:42:44 -05:00
brngates98
6d85ea76ab Add device tag support to Prometheus metrics
- Add 'tag' label to all device metric descriptors
- Update exportWithTags helper to create separate metric series per tag
- Update all device export functions (UAP, USW, UDM, USG, UXG, PDU, UBB, UCI) to include tags
- Update all label arrays (VAP, Radio, Port, etc.) to include tag label
- Devices with multiple tags create multiple metric series (one per tag)
- Devices without tags export with tag=""

Requires unpoller/unifi#92
2026-01-28 20:48:10 -05:00
Cody Lee
d26d84e8ad Merge pull request #923 from unpoller/issue-921
fix client side log error
v2.25.0
2026-01-27 21:16:14 -06:00
Cody Lee
5e68016564 fix client side log error 2026-01-27 21:14:21 -06:00
Cody Lee
a14d5c4150 Merge pull request #922 from brngates98/add-ai-context-files
Add AI context files for major LLMs
2026-01-27 20:51:34 -06:00
brngates98
969445fade Add AI context files for major LLMs
- 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.
2026-01-27 20:40:02 -05:00
Cody Lee
2a44b2f0be Merge pull request #920 from unpoller/issue-742
Fix Homebrew formula for newer Homebrew versions
v2.24.0
2026-01-25 12:29:57 -06:00
Cody Lee
3f60654a2a Fix Homebrew formula for newer Homebrew versions
Updated the install section in the brews configuration to use the
new Homebrew formula syntax for directory creation.

Changes:
- Changed `etc.mkdir "unpoller"` to `(etc/"unpoller").mkpath`

The old syntax was causing errors with newer Homebrew versions:
  TypeError: no implicit conversion of String into Integer

This fix ensures compatibility with Homebrew 4.3+ while maintaining
backward compatibility with older versions.

Fixes #742

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 12:29:13 -06:00
Cody Lee
037f4563f0 Merge pull request #919 from unpoller/issue-415
Enrich alarms with device names for Loki logs
2026-01-25 12:22:39 -06:00
Cody Lee
0fc8b6f008 use new unifi version 2026-01-25 12:21:16 -06:00
Cody Lee
97d3f995b1 Enrich alarms with device names for Loki logs
Added device name enrichment to alarms so that Loki logs show
human-readable device names instead of just MAC addresses.

Changes:
- Modified collectAlarms to fetch devices and build MAC-to-name lookup
- Added extractDeviceNameFromAlarm helper to extract MAC addresses from
  alarm messages and lookup corresponding device names
- Device names are extracted from messages like "AP[fc:ec:da:89:a6:91]"
  or from SrcMAC/DstMAC fields
- Added go.mod replace directive to use local unifi library with new
  DeviceName field

The device_name field will now be included in the JSON output sent to
Loki, making it easier to identify which device triggered an alarm.

Fixes #415

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 12:17:12 -06:00
Cody Lee
a35e52c140 Merge pull request #918 from unpoller/issue-417
Populate num_user field for VPN subsystem metrics
2026-01-25 12:10:53 -06:00
Cody Lee
ae1ab40386 Populate num_user field for VPN subsystem metrics
Fixes #417

UniFi controllers populate RemoteUserNumActive for VPN connections but
leave NumUser at 0 for the VPN subsystem. This caused dashboard queries
looking for num_user in the VPN subsystem to always show 0 active users,
even when VPN connections were active.

Root Cause:
For most subsystems (wlan, lan, www), the controller populates NumUser
directly. However, for the VPN subsystem, the controller uses the
RemoteUserNumActive field instead, leaving NumUser at 0.

The Prometheus exporter had special handling for VPN (lines 148-156 in
pkg/promunifi/site.go) and exported RemoteUserNumActive, but did not
export NumUser. The InfluxDB and Datadog exporters exported all fields
for all subsystems without special handling, resulting in num_user
always being 0 for VPN.

Existing Grafana dashboards query:
  SELECT "num_user" FROM "subsystems" WHERE subsystem='vpn'

This always returned 0 even with active VPN users.

Solution:
For all three exporters (InfluxDB, Datadog, Prometheus), when the
subsystem is 'vpn' and NumUser is 0 but RemoteUserNumActive has a
value, populate num_user with RemoteUserNumActive.

Changes:
- pkg/influxunifi/site.go: Add VPN-specific num_user fallback logic
- pkg/datadogunifi/site.go: Add VPN-specific num_user fallback logic
- pkg/promunifi/site.go: Add NumUser metric to VPN case with fallback

This maintains backward compatibility - existing queries for num_user
will now work correctly, and the remote_user_num_active field is still
available for those who updated their dashboards.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 12:09:01 -06:00
Cody Lee
10a43dcf04 Merge pull request #917 from unpoller/issue-425
Allow polling to continue when individual controllers fail
2026-01-25 12:04:38 -06:00
Cody Lee
f51a0c7202 Allow polling to continue when individual controllers fail
Fixes #425

When polling multiple controllers, if one controller was down or
unreachable, unpoller would stop collecting data from ALL controllers.
This caused complete data loss across all sites when just one was down.

Root Cause:
Both Metrics() and Events() methods would immediately return an error
when any controller failed, skipping all remaining controllers in the
loop.

Changes:
- Log errors from failed controllers but continue to next controller
- Track collection errors separately from successful data collection
- Only return error if ALL controllers failed and no data was collected
- Return success if at least one controller provided data

This allows unpoller to continue monitoring healthy controllers even
when some are temporarily unreachable due to network issues, timeouts,
or maintenance.

Example behavior:
- Controller 1: Down (timeout) - logs error, continues
- Controller 2: Up - collects data successfully
- Controller 3: Up - collects data successfully
- Result: Returns data from controllers 2 and 3

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 12:01:37 -06:00
Cody Lee
4e3c823989 Merge pull request #916 from unpoller/issue-904
Fix authentication retry to prevent data gaps after re-auth
v2.23.0
2026-01-25 11:55:47 -06:00
Cody Lee
a1a8963159 Fix authentication retry to prevent data gaps after re-auth
Fixes #904

When a poll fails (typically with 401 Unauthorized after ~2 hour token
expiration), the code would re-authenticate but then return the original
poll error without retrying. This caused a one-minute data gap every
2 hours.

Changes:
- After successful re-authentication, retry the poll operation
- Add 500ms delay before retry to allow controller to process new auth
- Rename error variable to avoid shadowing during re-auth attempt

This ensures that transient authentication failures during the re-auth
window don't cause data gaps.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 11:53:31 -06:00