Skip to main content

Display a Metric

Most widgets display metrics, like the CPU temperature or the GPU usage. Metrics are provided by plugins, and users select the metric a widget displays in the dashboard builder. Let's create a widget that displays the value of a metric including its unit.

How Metric Values Reach a Widget

The plugin decides how often a metric is updated. The widget only subscribes to the metric the user selected and is re-rendered for every new value.

Widget Configuration

Create a new widget with a field of type metric. In the dashboard builder, the field lets users select any metric provided by the installed plugins:

src/widgets/metric-value/mobro-widget-config.json
{
"name": "metric_value",
"displayName": "Metric Value",
"filename": "MetricValue.tsx",
"config": [
{
"name": "metric",
"label": "Metric",
"type": "metric"
}
]
}

When selecting the metric, users can also choose a unit to convert the value to (e.g. °F instead of °C) and whether the widget should receive the current value or the minimum, maximum or average value of the metric.

tip

Use filters to only offer metrics your widget can display, e.g. only numeric metrics for a gauge. See Metric Field.

Widget Component

src/widgets/metric-value/MetricValue.tsx
import React from 'react'
import {
Loading,
MissingConfigPlaceholder,
useFormattedMetricValue,
useIsMetricFieldConfigured,
useMetricField
} from '@modbros/dashboard-sdk'

export default function MetricValue() {
const isConfigured = useIsMetricFieldConfigured({field: 'metric'})
const channelValue = useMetricField({field: 'metric'})
const formatted = useFormattedMetricValue(channelValue, {precision: 1})

if (!isConfigured) {
return <MissingConfigPlaceholder text="Please select a metric"/>
}

if (!channelValue || !formatted) {
return <Loading/>
}

return (
<div style={{display: 'flex', flexDirection: 'column'}}>
<span>{channelValue.metric.label}</span>
<strong>
{formatted.unitPosition === 'before' && formatted.unit}
{formatted.value}
{formatted.unitPosition === 'after' && formatted.unit}
</strong>
</div>
)
}

Let's go through it step by step:

  1. useIsMetricFieldConfigured returns whether the user selected a metric. As long as no metric is selected, the widget shows the MissingConfigPlaceholder.
  2. useMetricField subscribes to the selected metric and returns its ChannelValue: the metric, its type, its unit and its current value. It returns null until the first value arrives, so the widget shows the Loading indicator in the meantime.
  3. useFormattedMetricValue formats the value based on the metric type: numbers are rounded to the given precision, dates are formatted and so on. It returns the formatted value, the unit and whether the unit belongs before or after the value (e.g. for currencies).
note

All hooks must be called before the first return, as required by the rules of hooks. That's why the widget calls all three hooks first and checks their results afterwards.

Add the widget to a dashboard and select a metric, e.g. the CPU usage. The widget now shows the live value, updated every time the plugin provides a new value.

Going Further

  • useMetricField re-renders the widget for every new value, even if the displayed value didn't change. useMemoizedMetricField only re-renders when a value derived from the metric changes.
  • Every metric value also includes statistics like its minimum and maximum, which are useful to scale gauges and charts. See In-depth: Metrics.
  • If a selected metric no longer exists, e.g. because its plugin was uninstalled, the widget shows an error. See In-depth: Error Handling.

For complete metric widgets like gauges, charts and single values, check out the Charts widget pack.

Next, let's publish the widget pack to the marketplace.