Merge pull request #1007 from unpoller/feature/influx-global-tags-1001

feat(influxunifi): add global tags applied to every measurement
This commit is contained in:
Cody Lee
2026-05-09 09:01:23 -05:00
committed by GitHub
5 changed files with 62 additions and 3 deletions
+6
View File
@@ -56,6 +56,12 @@
## Record data for disabled or down (unlinked) switch ports.
dead_ports = false
# Global tags applied to every InfluxDB measurement. Per-metric tags
# (site, device id, etc.) always win on key collision.
# [influxdb.tags]
# customer = "abc_corp"
# env = "prod"
# To enable output of UniFi Events to Loki, add a URL; it's disabled otherwise.
# User, pass and tenant_id are optional and most folks wont set them.
# Pick which logs you want per-controller in the [unifi.controller] section.
+5 -1
View File
@@ -21,7 +21,11 @@
"pass": "unifipoller",
"db": "unifi",
"verify_ssl": false,
"interval": "30s"
"interval": "30s",
"tags": {
"customer": "abc_corp",
"env": "prod"
}
},
"webserver": {
+3
View File
@@ -29,6 +29,9 @@ influxdb:
pass: "unifipoller"
db: "unifi"
verify_ssl: false
tags:
customer: abc_corp
env: prod
webserver:
enable: false
+21
View File
@@ -45,3 +45,24 @@ influxdb:
# the influxdb api password
pass: supersecret
```
### Global Tags
Tags configured under `tags` are attached to every measurement written to
InfluxDB. Per-metric tags (site, device id, etc.) take precedence on key
collision so they cannot be overwritten by a misconfigured global tag.
```yaml
influxdb:
tags:
customer: abc_corp
env: prod
```
Equivalent TOML:
```toml
[influxdb.tags]
customer = "abc_corp"
env = "prod"
```
+27 -2
View File
@@ -61,6 +61,9 @@ type Config struct {
VerifySSL bool `json:"verify_ssl" toml:"verify_ssl" xml:"verify_ssl" yaml:"verify_ssl"`
// DeadPorts when true will save data for dead ports, for example ports that are down or disabled.
DeadPorts bool `json:"dead_ports" toml:"dead_ports" xml:"dead_ports" yaml:"dead_ports"`
// Tags are global tags applied to every metric written to InfluxDB. Per-metric
// tags take precedence and will not be overwritten by a global tag of the same name.
Tags map[string]string `json:"tags,omitempty" toml:"tags,omitempty" xml:"tags" yaml:"tags,omitempty"`
}
// InfluxDB allows the data to be nested in the config file.
@@ -373,11 +376,13 @@ func (u *InfluxUnifi) collect(r report, ch chan *metric) {
m.TS = r.metrics().TS
}
tags := u.mergeGlobalTags(m.Tags)
if u.IsVersion2 {
pt := influx.NewPoint(m.Table, m.Tags, m.Fields, m.TS)
pt := influx.NewPoint(m.Table, tags, m.Fields, m.TS)
r.batchV2(m, pt)
} else {
pt, err := influxV1.NewPoint(m.Table, m.Tags, m.Fields, m.TS)
pt, err := influxV1.NewPoint(m.Table, tags, m.Fields, m.TS)
if err == nil {
r.batchV1(m, pt)
}
@@ -389,6 +394,26 @@ func (u *InfluxUnifi) collect(r report, ch chan *metric) {
}
}
// mergeGlobalTags returns a tag map containing the per-metric tags layered on
// top of the configured global tags. Per-metric tags win on key collision so
// device/site identifiers can never be overwritten by a misconfigured global.
func (u *InfluxUnifi) mergeGlobalTags(tags map[string]string) map[string]string {
if len(u.Tags) == 0 {
return tags
}
merged := make(map[string]string, len(u.Tags)+len(tags))
for k, v := range u.Tags {
merged[k] = v
}
for k, v := range tags {
merged[k] = v
}
return merged
}
// loopPoints kicks off 3 or 7 go routines to process metrics and send them
// to the collect routine through the metric channel.
func (u *InfluxUnifi) loopPoints(r report) {