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  }