Device health, metrics & geo

Configure the Health and Geo extensions in NervesHubLink: metric sets, custom metadata, alarms, and location resolvers.

Written By Josh Kalderimis

Last updated About 2 months ago

Extensions are non-critical features that run over the device websocket. They're kept separate so the client can ignore them if needed and keep firmware updates as the top priority. Two extensions report fleet data:

  • Health: device metrics, alarms, and metadata.

  • Geo: device location.

There's also a Local Shell extension, covered in Remote console & local shell.

Extensions must be enabled on the server too (in your Product and Device settings). The server can switch them off if they affect operations.

Health

By default, the Health report (Health.DefaultReport) sends these metric sets:

Metric set

Reports

MetricSet.CPU

CPU temperature, usage %, load averages.

MetricSet.Memory

Memory size, used, and % used.

MetricSet.Disk

Disk size, available, and % used.

MetricSet.NetworkTraffic (optional)

Bytes sent/received per interface.

Choose which metrics to send

Use :default (or :defaults) to include the standard set, and add your own or a library's:

config :nerves_hub_link,
  health: [
    metric_sets: [
      :defaults,
      MyApp.HealthMetrics,
      ALibrary.BatteryMetrics
    ]
  ]

Listing metric sets explicitly replaces the defaults, so include only what you want:

config :nerves_hub_link,
  health: [
    metric_sets: [
      NervesHubLink.Extensions.Health.MetricSet.CPU,
      NervesHubLink.Extensions.Health.MetricSet.Memory
      # Disk excluded
    ]
  ]

Disable metrics entirely with an empty list (metric_sets: []). To write your own, implement the NervesHubLink.Extensions.Health.MetricSet behaviour.

Add custom metadata

Attach extra metadata with a key and an {module, function, args} tuple that returns a string:

config :nerves_hub_link,
  health: [
    metadata: %{
      "placement" => {CatCounter, :venue, []}
    }
  ]

For full control, implement NervesHubLink.Extensions.Health.Report and set it as report:.

Alarms

The default report also sends current system alarms. It uses Erlang's :alarm_handler, though the alarmist library is recommended for better alarm handling.

The :disk_almost_full alarm for / is filtered out by default, since Nerves sizes the read-only root filesystem to fit the firmware exactly. Customize the ignored mounts (this replaces the default, so re-include / if you still want it ignored):

config :nerves_hub_link,
  health: [
    alarms: [
      ignore_disk_full_mounts: ["/", "/a_different_mount"]
    ]
  ]

Geo

The default Geo resolver (Geo.DefaultResolver) uses the public whenwhere.nerves-project.org service to estimate location from the device's public IP address.

If your device knows its location more precisely (GPS, LTE), implement the NervesHubLink.Extensions.Geo.Resolver behaviour and point the config at it:

config :nerves_hub_link,
  geo: [
    resolver: MyApp.GPSGeoResolver
  ]

Related