Grafana UPS Dashboard

I couldn’t find any decent Grafana-based dashboards for monitoring APC UPS’s. So I wrote my own. Below is a quick guide to what it took to get my UPS’s power/battery statistics into a decent-looking dashboard.

It all starts with the APC UPS. SNMPv1 is feeling more dated as time goes on, with a simple shared passphrase, and the data sent over the wire in cleartext.

Enter SNMPv3, with its authentication and privacy protocols. First step is to configure the UPS.

snmp config

Next we need some way to get the data out of the UPS. In my case, I use Telegraf. I couldn’t provide a better description than the one found on its Github repository: “Telegraf is an agent written in Go for collecting, processing, aggregating, and writing metrics.” InfluxDB is used as the time series database.

Using the following Telegraf config, I am able to query ups1 and stick its power and battery data into the telegraf database on db2.

[[inputs.snmp]]
  agents = [ "ups1" ]
  version=3
  sec_name="telegraf"
  auth_protocol="SHA"
  auth_password="myauthpassword"
  sec_level="authPriv"
  priv_protocol="AES"
  priv_password="myprivpassword"
  name="ups"
  interval="60s"

  [[inputs.snmp.field]]
    name = "hostname"
    oid = "RFC1213-MIB::sysName.0"
    is_tag = true

  [[inputs.snmp.field]]
    name = "uptime"
    oid = "DISMAN-EXPRESSION-MIB::sysUpTimeInstance"

  [[inputs.snmp.field]]
    name = "model"
    oid = "PowerNet-MIB::upsBasicIdentModel.0"

  [[inputs.snmp.field]]
      name = "name"
      oid = "PowerNet-MIB::upsBasicIdentName.0"

  [[inputs.snmp.field]]
      name = "upsBasicBatteryTimeOnBattery"
      oid = "PowerNet-MIB::upsBasicBatteryTimeOnBattery.0"

  [[inputs.snmp.field]]
      name = "upsAdvBatteryRunTimeRemaining"
      oid = "PowerNet-MIB::upsAdvBatteryRunTimeRemaining.0"

  [[inputs.snmp.field]]
      name = "upsAdvBatteryReplaceIndicator"
      oid = "PowerNet-MIB::upsAdvBatteryReplaceIndicator.0"

  [[inputs.snmp.field]]
      name = "upsHighPrecBatteryCapacity"
      oid = "PowerNet-MIB::upsHighPrecBatteryCapacity.0"
      conversion = "float(1)"

  [[inputs.snmp.field]]
      name = "upsHighPrecBatteryTemperature"
      oid = "PowerNet-MIB::upsHighPrecBatteryTemperature.0"
      conversion = "float(1)"

  [[inputs.snmp.field]]
      name = "upsBasicOutputStatus"
      oid = "PowerNet-MIB::upsBasicOutputStatus.0"

  [[inputs.snmp.field]]
      name = "upsHighPrecOutputLoad"
      oid = "PowerNet-MIB::upsHighPrecOutputLoad.0"
      conversion = "float(1)"

  [[inputs.snmp.field]]
      name = "upsHighPrecOutputEfficiency"
      oid = "PowerNet-MIB::upsHighPrecOutputEfficiency.0"
      conversion = "float(1)"

  [[inputs.snmp.field]]
      name = "upsHighPrecOutputVoltage"
      oid = "PowerNet-MIB::upsHighPrecOutputVoltage.0"
      conversion = "float(1)"

  [[inputs.snmp.field]]
      name = "upsHighPrecInputLineVoltage"
      oid = "PowerNet-MIB::upsHighPrecInputLineVoltage.0"
      conversion = "float(1)"

  [[inputs.snmp.field]]
      name = "upsHighPrecOutputCurrent"
      oid = "PowerNet-MIB::upsHighPrecOutputCurrent.0"
      conversion = "float(1)"

  [[inputs.snmp.field]]
      name = "upsHighPrecOutputEnergyUsage"
      oid = "PowerNet-MIB::upsHighPrecOutputEnergyUsage.0"
      conversion = "float(1)"


  # IF-MIB::ifTable contains counters on input and output traffic as well as errors and discards.
  [[inputs.snmp.table]]
    name = "interface"
    inherit_tags = [ "hostname" ]
    oid = "IF-MIB::ifTable"

    # Interface tag - used to identify interface in metrics database
    [[inputs.snmp.table.field]]
      name = "ifDescr"
      oid = "IF-MIB::ifDescr"
      is_tag = true

  # IF-MIB::ifXTable contains newer High Capacity (HC) counters that do not overflow as fast for a few of the ifTable counters
  [[inputs.snmp.table]]
    name = "interface"
    inherit_tags = [ "hostname" ]
    oid = "IF-MIB::ifXTable"

    # Interface tag - used to identify interface in metrics database
    [[inputs.snmp.table.field]]
      name = "ifDescr"
      oid = "IF-MIB::ifDescr"
      is_tag = true

  # EtherLike-MIB::dot3StatsTable contains detailed ethernet-level information about what kind of errors have been logged on an interface (such as FCS error, frame too long, etc)
  [[inputs.snmp.table]]
    name = "interface"
    inherit_tags = [ "hostname" ]
    oid = "EtherLike-MIB::dot3StatsTable"

    # Interface tag - used to identify interface in metrics database
    [[inputs.snmp.table.field]]
      name = "ifDescr"
      oid = "IF-MIB::ifDescr"
      is_tag = true

  [[outputs.influxdb]]
    urls = ["http://db2:8086"]
    database = "telegraf"
    retention_policy = ""
    write_consistency = "any"
    timeout = "5s"
    username = "myusername"
    password = "mypassword"

Finally, assuming you are able to query your UPS power information in the InfluxDB instance, you’re ready to add my UPS dashboard to your Grafana instance.

Assumptions: You have a working Grafana instance that can query your Telegraf database.

Download the UPS dashboard from the Grafana Labs dashboard repository. Import the dashboard into your instance.

Wait several minutes (or really hours) and your data should begin to appear.

dashboard-1

Or if you decide to do some electrical work in your house, turn off the main breaker, let the UPS completely drain, and then let it completely charge again, your graphs will look like this:

ups-power-recovery