github.com/netdata/go.d.plugin@v0.58.1/modules/upsd/charts.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package upsd 4 5 import ( 6 "fmt" 7 "strings" 8 9 "github.com/netdata/go.d.plugin/agent/module" 10 ) 11 12 const ( 13 prioUpsLoad = module.Priority + iota 14 prioUpsLoadUsage 15 prioUpsStatus 16 prioUpsTemperature 17 18 prioBatteryCharge 19 prioBatteryEstimatedRuntime 20 prioBatteryVoltage 21 prioBatteryVoltageNominal 22 23 prioInputVoltage 24 prioInputVoltageNominal 25 prioInputCurrent 26 prioInputCurrentNominal 27 prioInputFrequency 28 prioInputFrequencyNominal 29 30 prioOutputVoltage 31 prioOutputVoltageNominal 32 prioOutputCurrent 33 prioOutputCurrentNominal 34 prioOutputFrequency 35 prioOutputFrequencyNominal 36 ) 37 38 var upsChartsTmpl = module.Charts{ 39 upsLoadChartTmpl.Copy(), 40 upsLoadUsageChartTmpl.Copy(), 41 upsStatusChartTmpl.Copy(), 42 upsTemperatureChartTmpl.Copy(), 43 44 upsBatteryChargePercentChartTmpl.Copy(), 45 upsBatteryEstimatedRuntimeChartTmpl.Copy(), 46 upsBatteryVoltageChartTmpl.Copy(), 47 upsBatteryVoltageNominalChartTmpl.Copy(), 48 49 upsInputVoltageChartTmpl.Copy(), 50 upsInputVoltageNominalChartTmpl.Copy(), 51 upsInputCurrentChartTmpl.Copy(), 52 upsInputCurrentNominalChartTmpl.Copy(), 53 upsInputFrequencyChartTmpl.Copy(), 54 upsInputFrequencyNominalChartTmpl.Copy(), 55 56 upsOutputVoltageChartTmpl.Copy(), 57 upsOutputVoltageNominalChartTmpl.Copy(), 58 upsOutputCurrentChartTmpl.Copy(), 59 upsOutputCurrentNominalChartTmpl.Copy(), 60 upsOutputFrequencyChartTmpl.Copy(), 61 upsOutputFrequencyNominalChartTmpl.Copy(), 62 } 63 64 var ( 65 upsLoadChartTmpl = module.Chart{ 66 IDSep: true, 67 ID: "%s.load_percentage", 68 Title: "UPS load", 69 Units: "percentage", 70 Fam: "ups", 71 Ctx: "upsd.ups_load", 72 Priority: prioUpsLoad, 73 Type: module.Area, 74 Dims: module.Dims{ 75 {ID: "ups_%s_ups.load", Name: "load", Div: varPrecision}, 76 }, 77 } 78 upsLoadUsageChartTmpl = module.Chart{ 79 IDSep: true, 80 ID: "%s.load_usage", 81 Title: "UPS load usage (power output)", 82 Units: "Watts", 83 Fam: "ups", 84 Ctx: "upsd.ups_load_usage", 85 Priority: prioUpsLoadUsage, 86 Dims: module.Dims{ 87 {ID: "ups_%s_ups.load.usage", Name: "load_usage", Div: varPrecision}, 88 }, 89 } 90 upsStatusChartTmpl = module.Chart{ 91 IDSep: true, 92 ID: "%s.status", 93 Title: "UPS status", 94 Units: "status", 95 Fam: "ups", 96 Ctx: "upsd.ups_status", 97 Priority: prioUpsStatus, 98 Dims: module.Dims{ 99 {ID: "ups_%s_ups.status.OL", Name: "on_line"}, 100 {ID: "ups_%s_ups.status.OB", Name: "on_battery"}, 101 {ID: "ups_%s_ups.status.LB", Name: "low_battery"}, 102 {ID: "ups_%s_ups.status.HB", Name: "high_battery"}, 103 {ID: "ups_%s_ups.status.RB", Name: "replace_battery"}, 104 {ID: "ups_%s_ups.status.CHRG", Name: "charging"}, 105 {ID: "ups_%s_ups.status.DISCHRG", Name: "discharging"}, 106 {ID: "ups_%s_ups.status.BYPASS", Name: "bypass"}, 107 {ID: "ups_%s_ups.status.CAL", Name: "calibration"}, 108 {ID: "ups_%s_ups.status.OFF", Name: "offline"}, 109 {ID: "ups_%s_ups.status.OVER", Name: "overloaded"}, 110 {ID: "ups_%s_ups.status.TRIM", Name: "trim_input_voltage"}, 111 {ID: "ups_%s_ups.status.BOOST", Name: "boost_input_voltage"}, 112 {ID: "ups_%s_ups.status.FSD", Name: "forced_shutdown"}, 113 {ID: "ups_%s_ups.status.other", Name: "other"}, 114 }, 115 } 116 upsTemperatureChartTmpl = module.Chart{ 117 IDSep: true, 118 ID: "%s.temperature", 119 Title: "UPS temperature", 120 Units: "Celsius", 121 Fam: "ups", 122 Ctx: "upsd.ups_temperature", 123 Priority: prioUpsTemperature, 124 Dims: module.Dims{ 125 {ID: "ups_%s_ups.temperature", Name: "temperature", Div: varPrecision}, 126 }, 127 } 128 ) 129 130 var ( 131 upsBatteryChargePercentChartTmpl = module.Chart{ 132 IDSep: true, 133 ID: "%s.battery_charge_percentage", 134 Title: "UPS Battery charge", 135 Units: "percentage", 136 Fam: "battery", 137 Ctx: "upsd.ups_battery_charge", 138 Priority: prioBatteryCharge, 139 Type: module.Area, 140 Dims: module.Dims{ 141 {ID: "ups_%s_battery.charge", Name: "charge", Div: varPrecision}, 142 }, 143 } 144 upsBatteryEstimatedRuntimeChartTmpl = module.Chart{ 145 IDSep: true, 146 ID: "%s.battery_estimated_runtime", 147 Title: "UPS Battery estimated runtime", 148 Units: "seconds", 149 Fam: "battery", 150 Ctx: "upsd.ups_battery_estimated_runtime", 151 Priority: prioBatteryEstimatedRuntime, 152 Dims: module.Dims{ 153 {ID: "ups_%s_battery.runtime", Name: "runtime", Div: varPrecision}, 154 }, 155 } 156 upsBatteryVoltageChartTmpl = module.Chart{ 157 IDSep: true, 158 ID: "%s.battery_voltage", 159 Title: "UPS Battery voltage", 160 Units: "Volts", 161 Fam: "battery", 162 Ctx: "upsd.ups_battery_voltage", 163 Priority: prioBatteryVoltage, 164 Dims: module.Dims{ 165 {ID: "ups_%s_battery.voltage", Name: "voltage", Div: varPrecision}, 166 }, 167 } 168 upsBatteryVoltageNominalChartTmpl = module.Chart{ 169 IDSep: true, 170 ID: "%s.battery_voltage_nominal", 171 Title: "UPS Battery voltage nominal", 172 Units: "Volts", 173 Fam: "battery", 174 Ctx: "upsd.ups_battery_voltage_nominal", 175 Priority: prioBatteryVoltageNominal, 176 Dims: module.Dims{ 177 {ID: "ups_%s_battery.voltage.nominal", Name: "nominal_voltage", Div: varPrecision}, 178 }, 179 } 180 ) 181 182 var ( 183 upsInputVoltageChartTmpl = module.Chart{ 184 IDSep: true, 185 ID: "%s.input_voltage", 186 Title: "UPS Input voltage", 187 Units: "Volts", 188 Fam: "input", 189 Ctx: "upsd.ups_input_voltage", 190 Priority: prioInputVoltage, 191 Dims: module.Dims{ 192 {ID: "ups_%s_input.voltage", Name: "voltage", Div: varPrecision}, 193 }, 194 } 195 upsInputVoltageNominalChartTmpl = module.Chart{ 196 IDSep: true, 197 ID: "%s.input_voltage_nominal", 198 Title: "UPS Input voltage nominal", 199 Units: "Volts", 200 Fam: "input", 201 Ctx: "upsd.ups_input_voltage_nominal", 202 Priority: prioInputVoltageNominal, 203 Dims: module.Dims{ 204 {ID: "ups_%s_input.voltage.nominal", Name: "nominal_voltage", Div: varPrecision}, 205 }, 206 } 207 upsInputCurrentChartTmpl = module.Chart{ 208 IDSep: true, 209 ID: "%s.input_current", 210 Title: "UPS Input current", 211 Units: "Ampere", 212 Fam: "input", 213 Ctx: "upsd.ups_input_current", 214 Priority: prioInputCurrent, 215 Dims: module.Dims{ 216 {ID: "ups_%s_input.current", Name: "current", Div: varPrecision}, 217 }, 218 } 219 upsInputCurrentNominalChartTmpl = module.Chart{ 220 IDSep: true, 221 ID: "%s.input_current_nominal", 222 Title: "UPS Input current nominal", 223 Units: "Ampere", 224 Fam: "input", 225 Ctx: "upsd.ups_input_current_nominal", 226 Priority: prioInputCurrentNominal, 227 Dims: module.Dims{ 228 {ID: "ups_%s_input.current.nominal", Name: "nominal_current", Div: varPrecision}, 229 }, 230 } 231 upsInputFrequencyChartTmpl = module.Chart{ 232 IDSep: true, 233 ID: "%s.input_frequency", 234 Title: "UPS Input frequency", 235 Units: "Hz", 236 Fam: "input", 237 Ctx: "upsd.ups_input_frequency", 238 Priority: prioInputFrequency, 239 Dims: module.Dims{ 240 {ID: "ups_%s_input.frequency", Name: "frequency", Div: varPrecision}, 241 }, 242 } 243 upsInputFrequencyNominalChartTmpl = module.Chart{ 244 IDSep: true, 245 ID: "%s.input_frequency_nominal", 246 Title: "UPS Input frequency nominal", 247 Units: "Hz", 248 Fam: "input", 249 Ctx: "upsd.ups_input_frequency_nominal", 250 Priority: prioInputFrequencyNominal, 251 Dims: module.Dims{ 252 {ID: "ups_%s_input.frequency.nominal", Name: "nominal_frequency", Div: varPrecision}, 253 }, 254 } 255 ) 256 257 var ( 258 upsOutputVoltageChartTmpl = module.Chart{ 259 IDSep: true, 260 ID: "%s.output_voltage", 261 Title: "UPS Output voltage", 262 Units: "Volts", 263 Fam: "output", 264 Ctx: "upsd.ups_output_voltage", 265 Priority: prioOutputVoltage, 266 Dims: module.Dims{ 267 {ID: "ups_%s_output.voltage", Name: "voltage", Div: varPrecision}, 268 }, 269 } 270 upsOutputVoltageNominalChartTmpl = module.Chart{ 271 IDSep: true, 272 ID: "%s.output_voltage_nominal", 273 Title: "UPS Output voltage nominal", 274 Units: "Volts", 275 Fam: "output", 276 Ctx: "upsd.ups_output_voltage_nominal", 277 Priority: prioOutputVoltageNominal, 278 Dims: module.Dims{ 279 {ID: "ups_%s_output.voltage.nominal", Name: "nominal_voltage", Div: varPrecision}, 280 }, 281 } 282 upsOutputCurrentChartTmpl = module.Chart{ 283 IDSep: true, 284 ID: "%s.output_current", 285 Title: "UPS Output current", 286 Units: "Ampere", 287 Fam: "output", 288 Ctx: "upsd.ups_output_current", 289 Priority: prioOutputCurrent, 290 Dims: module.Dims{ 291 {ID: "ups_%s_output.current", Name: "current", Div: varPrecision}, 292 }, 293 } 294 upsOutputCurrentNominalChartTmpl = module.Chart{ 295 IDSep: true, 296 ID: "%s.output_current_nominal", 297 Title: "UPS Output current nominal", 298 Units: "Ampere", 299 Fam: "output", 300 Ctx: "upsd.ups_output_current_nominal", 301 Priority: prioOutputCurrentNominal, 302 Dims: module.Dims{ 303 {ID: "ups_%s_output.current.nominal", Name: "nominal_current", Div: varPrecision}, 304 }, 305 } 306 upsOutputFrequencyChartTmpl = module.Chart{ 307 IDSep: true, 308 ID: "%s.output_frequency", 309 Title: "UPS Output frequency", 310 Units: "Hz", 311 Fam: "output", 312 Ctx: "upsd.ups_output_frequency", 313 Priority: prioOutputFrequency, 314 Dims: module.Dims{ 315 {ID: "ups_%s_output.frequency", Name: "frequency", Div: varPrecision}, 316 }, 317 } 318 upsOutputFrequencyNominalChartTmpl = module.Chart{ 319 IDSep: true, 320 ID: "%s.output_frequency_nominal", 321 Title: "UPS Output frequency nominal", 322 Units: "Hz", 323 Fam: "output", 324 Ctx: "upsd.ups_output_frequency_nominal", 325 Priority: prioOutputFrequencyNominal, 326 Dims: module.Dims{ 327 {ID: "ups_%s_output.frequency.nominal", Name: "nominal_frequency", Div: varPrecision}, 328 }, 329 } 330 ) 331 332 func (u *Upsd) addUPSCharts(ups upsUnit) { 333 charts := upsChartsTmpl.Copy() 334 335 var removed []string 336 for _, v := range []struct{ v, id string }{ 337 {varBatteryVoltage, upsBatteryVoltageChartTmpl.ID}, 338 {varBatteryVoltageNominal, upsBatteryVoltageNominalChartTmpl.ID}, 339 340 {varUpsTemperature, upsTemperatureChartTmpl.ID}, 341 342 {varInputVoltage, upsInputVoltageChartTmpl.ID}, 343 {varInputVoltageNominal, upsInputVoltageNominalChartTmpl.ID}, 344 {varInputCurrent, upsInputCurrentChartTmpl.ID}, 345 {varInputCurrentNominal, upsInputCurrentNominalChartTmpl.ID}, 346 {varInputFrequency, upsInputFrequencyChartTmpl.ID}, 347 {varInputFrequencyNominal, upsInputFrequencyNominalChartTmpl.ID}, 348 349 {varOutputVoltage, upsOutputVoltageChartTmpl.ID}, 350 {varOutputVoltageNominal, upsOutputVoltageNominalChartTmpl.ID}, 351 {varOutputCurrent, upsOutputCurrentChartTmpl.ID}, 352 {varOutputCurrentNominal, upsOutputCurrentNominalChartTmpl.ID}, 353 {varOutputFrequency, upsOutputFrequencyChartTmpl.ID}, 354 {varOutputFrequencyNominal, upsOutputFrequencyNominalChartTmpl.ID}, 355 } { 356 if !hasVar(ups.vars, v.v) { 357 removed = append(removed, v.v) 358 _ = charts.Remove(v.id) 359 } 360 } 361 362 u.Debugf("UPS '%s' no metrics: %v", ups.name, removed) 363 364 name := cleanUpsName(ups.name) 365 for _, chart := range *charts { 366 chart.ID = fmt.Sprintf(chart.ID, name) 367 chart.Labels = []module.Label{ 368 {Key: "ups_name", Value: ups.name}, 369 {Key: "battery_type", Value: ups.vars[varBatteryType]}, 370 {Key: "device_model", Value: ups.vars[varDeviceModel]}, 371 {Key: "device_serial", Value: ups.vars[varDeviceSerial]}, 372 {Key: "device_manufacturer", Value: ups.vars[varDeviceMfr]}, 373 {Key: "device_type", Value: ups.vars[varDeviceType]}, 374 } 375 for _, dim := range chart.Dims { 376 dim.ID = fmt.Sprintf(dim.ID, ups.name) 377 } 378 } 379 380 if err := u.Charts().Add(*charts...); err != nil { 381 u.Warning(err) 382 } 383 } 384 385 func (u *Upsd) removeUPSCharts(name string) { 386 name = cleanUpsName(name) 387 for _, chart := range *u.Charts() { 388 if strings.HasPrefix(chart.ID, name) { 389 chart.MarkRemove() 390 chart.MarkNotCreated() 391 } 392 } 393 } 394 395 func cleanUpsName(name string) string { 396 name = strings.ReplaceAll(name, " ", "_") 397 name = strings.ReplaceAll(name, ".", "_") 398 return name 399 }