Skip to content
KONIGI

Dashboards / Visual representation / Gauge and dial

7 of 22

Gauge and dial

One value against a range, read at a glance. Few and NN/g both argue against it; this entry says when it survives that critique.

Updated September 10, 2026

Problem

One number, one range, and a viewer who needs to know where in that range it currently sits without reading anything.

Solution

An arc, a needle or filled sweep, and a scale. The gauge encodes position within a bounded range, which is genuinely useful and is also the only thing it does.

The case against it is well made and worth stating properly. Few designed the bullet graph specifically to replace the meters and gauges that were filling dashboards, on the argument that a linear, no-frills display gives a rich reading in a small space, and space is the scarce resource on a dashboard. A gauge occupies a square to encode one value along one dimension. A bullet graph encodes the same value plus a target plus qualitative ranges in a strip a fraction of the size. On area alone the gauge loses, and on a page of twelve panels that is the whole argument.

So when does it survive? Three cases, and they are narrower than the number of gauges in the wild suggests.

When the range is genuinely bounded and familiar. Percentage full, percentage utilised, battery, capacity. The arc’s endpoints mean something. A gauge of “requests per second” has invented its own maximum and is lying about the scale.

When it is the only radial thing on the page. A row of gauges above a wall of line charts reads as a summary row precisely because the shape differs. That contrast is doing the work, not the arc. Repeat the gauges further down and it evaporates.

When it mimics a physical instrument the operator already reads. On a process display that mirrors real plant, matching the control-room instrument is a legitimate reason to be round, and consistency with the equipment beats abstract information density.

Grafana’s gauge inherits the standard threshold machinery, which is where most of the value lives: the arc is coloured by the same Absolute or Percentage thresholds used everywhere else, so the colour is a shared decision rather than a per-panel invention.

Use when

The range is real and bounded, the value’s position within it is the question, and there is exactly one row of them.

Don’t use when

You have more than about six, the maximum is invented, or the viewer needs to compare gauges against each other. Comparing angles across a grid is the task human perception is worst at, and it’s the task a grid of gauges sets.

Trade-offs

Gauges spend a lot of pixels on a single scalar, and the pixels come out of the panels that could have shown a trend. They carry no history, so a value sitting mid-arc looks identical whether it has been stable for a week or arrived there in the last minute. Angular position is read less accurately than length. And the decorative versions—chrome bezels, needle shadows, tick marks at every unit—add ink that encodes nothing, which is where the pattern gets its reputation.

Checklist

  • Is the maximum a real limit or a number someone picked?
  • Would a bullet graph carry the same information in a tenth of the space?
  • How many gauges are on this page, and are viewers comparing them to each other?
  • Does the gauge show a target as well as a value?
  • Where do the threshold colours come from, and are they the same ones the charts use?
  • Is there any history, or only the instantaneous value?
  • Is the number also printed, for people who need precision?
  • Does it stay readable at the size this panel actually renders at?
  • Would a colourblind reader get the same reading from the arc?
  • If this mirrors a physical instrument, does it match the one in the room?

Compare

Grafana ships the gauge as a first-class panel wired into the same threshold system as everything else, which makes it consistent and makes it easy to scatter across a dashboard where a stat panel would serve better. Tableau has no native gauge and the community builds them from stacked pie charts, which is a quiet statement of position from a tool whose analyst audience took Few’s argument seriously. Netdata favours a compact value with a live chart behind it over a radial reading, on the grounds that a per-second trend answers more questions than a position in an arc. Industrial HMI software, working to ISA-101 conventions, keeps the round instrument where it matches plant equipment and strips its decoration to a thin arc, which is the version of this pattern with the strongest justification.

Target and progress is the pattern Few built to replace this one, and the entry there covers the bullet graph properly. KPI tile is the smaller container for the same single number. Threshold line puts the same limits on a time axis where history is visible. Semantic status color governs the arc’s colouring. Process mimic is the context where a round instrument is the right answer rather than a nostalgic one.

Gauge and dial anatomy A gauge and a bullet graph given the same area on the page. The gauge encodes one value along one dimension. The bullet graph, in the same rectangle, encodes the value, the target and three qualitative ranges, and still leaves room for the label. The same area, twice 61% Disk used 0 100 One value, one dimension Disk used Percent 0 50 100 Value, target, three ranges 1 2 1 WHAT THE ARC COSTS A square to encode one value. On a page of twelve panels, space is the scarce resource, and on area alone the gauge loses. 2 WHY FEW BUILT THIS A linear, no-frills display giving a rich reading in a small space. It was designed specifically to replace the gauge. Three cases where the arc still survives that. When the range is genuinely bounded and familiar, so the endpoints mean something. When it is the only radial thing on the page and the contrast is doing the work. And when it mimics an instrument the operator already reads on real plant.
Wireframe — the pattern's anatomy, not any one product's version of it

Implementation

A gauge spends a lot of space on one number and is usually the wrong choice. It earns its place only where there is a fixed, known range and a person reading it at a distance.

Tokens
--foreground--card--muted--muted-foreground--border--chart-1--status-nominal--status-warn--status-critical

Gauge.tsxA half-circle arc with the number printed. The maximum is a required prop, and the arc takes its colour from the page's thresholds when it is given them.

type Props = {
  value: number;
  /** The real limit of the quantity, never a number someone picked. A gauge
   *  of "requests per second" has invented its own maximum and is lying
   *  about the scale, which is why there is no default. */
  max: number;
  min?: number;
  label: string;
  /** How the value prints. The number is always printed: an arc is a reading
   *  at a distance, and someone close up needs the figure. */
  format?: (v: number) => string;
  /** The same thresholds the page's other panels use, in the value's units.
   *  Without them the arc is one neutral colour. */
  thresholds?: { warn: number; critical: number };
  width?: number;
};

const R = 54;
const CX = 80;
const CY = 74;

/** A point on the half circle, `frac` of the way from the left end to the right. */
const point = (frac: number) => {
  const a = Math.PI * (1 - frac);
  return `${(CX + R * Math.cos(a)).toFixed(1)} ${(CY - R * Math.sin(a)).toFixed(1)}`;
};

/** A half circle, clockwise from the left end. Position within a bounded
 *  range is the one thing this shape encodes, and the only thing it does. */
export function Gauge({ value, max, min = 0, label, format = (v) => `${v}%`, thresholds, width = 160 }: Props) {
  const frac = Math.min(0.9999, Math.max(0, (value - min) / (max - min)));
  const status = !thresholds ? "none" : value >= thresholds.critical ? "critical" : value >= thresholds.warn ? "warn" : "nominal";
  const stroke = {
    none: "stroke-chart-1",
    nominal: "stroke-status-nominal",
    warn: "stroke-status-warn",
    critical: "stroke-status-critical",
  }[status];

  return (
    <figure className="m-0 inline-block" role="img" aria-label={`${label} ${format(value)} of ${format(max)}`}>
      <svg viewBox="0 0 160 90" width={width} height={(width * 90) / 160} aria-hidden="true">
        <path d={`M${point(0)} A ${R} ${R} 0 0 1 ${point(1)}`} fill="none" className="stroke-muted" strokeWidth="14" strokeLinecap="round" />
        <path d={`M${point(0)} A ${R} ${R} 0 0 1 ${point(frac)}`} fill="none" className={stroke} strokeWidth="14" strokeLinecap="round" />
        <text x={CX} y="66" textAnchor="middle" className="fill-foreground text-[17px] tabular-nums">{format(value)}</text>
        <text x="18" y="84" textAnchor="end" className="fill-muted-foreground text-[8px] tabular-nums">{min}</text>
        <text x="142" y="84" className="fill-muted-foreground text-[8px] tabular-nums">{max}</text>
        <text x={CX} y="88" textAnchor="middle" className="fill-muted-foreground text-[8px]">{label}</text>
      </svg>
    </figure>
  );
}

demo.tsxHow it is called: disk used, 61 of 100.

import { Gauge } from "./Gauge";

/**
 * Disk used is the case a gauge survives: the range is a real limit and
 * everyone reading it knows what full means.
 */
export default function Demo() {
  return (
    <div className="flex h-[140px] items-center justify-center rounded-lg border bg-card">
      <Gauge value={61} max={100} label="Disk used" />
    </div>
  );
}
What it renders. Identical markup in both panes, with only the token values changing.

Examples

Captures whose hotspots reference this pattern, grouped by product and dated. The dashed boxes are this pattern; hover any box for the note.

Ignition

A public SCADA demo running live simulated plant data, with a runtime toggle between simple and photorealistic pump and pipe rendering—the ISA-101 argument as a setting.

Ignition — Water Treatment / Overview
Process mimic. Flat two-dimensional shapes, values placed where the instrument is, and the flow ordered by process rather than by geography. Dense small-multiple layout. Nine filters, identical four-value panels. Reading one teaches you all nine, and the two stopped ones are found by shape. Gauge and dial. Tank level as a filled vertical scale—a bounded range where the endpoints are the physical tank, which is the case the gauge survives. Grayscale with alerts. Green for running, on every unit. The opposite of grey-at-rest, and it works only while stopped is the rare case. Process mimic. Pump and pipe appearance switchable between simple and photorealistic. The whole ISA-101 argument, shipped as a setting. Semantic status color. Stopped is grey and says Stopped. Colour and word together, so the state survives a monochrome screen.
Water Treatment / Overview September 11, 2026 Ignition Perspective public demo, Water Treatment (signed out) dense · dark · desktop-web
A real process mimic with live simulated plant data, and it settles two arguments from the entry. The first: the layout is topologically faithful and geometrically loose. Raw water pumps at the left, flash mixers, seven basins, nine filters, tanks, high service pumps, clearwell—the flow reads left to right because that is the process order, not because that is where the equipment stands. The second is where it departs from ISA-101, and the departure is deliberate. Green here means running. Every basin, every flocculator, every filter that is working is green, so most of the screen is coloured and the two stopped filters are the grey ones. That inverts the high-performance HMI rule—colour reserved for abnormal—and spends the budget on the ninety percent case. It is still readable, because the abnormal state is the absence of a colour everything else has, but it only works while "stopped" is rare. The pipe colours are a third channel again, encoding which fluid is in them rather than any state at all.
  • Process mimic Flat two-dimensional shapes, values placed where the instrument is, and the flow ordered by process rather than by geography.
  • Grayscale with alerts Green for running, on every unit. The opposite of grey-at-rest, and it works only while stopped is the rare case.
  • Dense small-multiple layout Nine filters, identical four-value panels. Reading one teaches you all nine, and the two stopped ones are found by shape.
  • Semantic status color Stopped is grey and says Stopped. Colour and word together, so the state survives a monochrome screen.
  • Gauge and dial Tank level as a filled vertical scale—a bounded range where the endpoints are the physical tank, which is the case the gauge survives.
  • Process mimic Pump and pipe appearance switchable between simple and photorealistic. The whole ISA-101 argument, shipped as a setting.
Show 3 more examples Hide the rest

Grafana

The reference implementation for panel grids, template variables, and stat panels; most other tools are defined by how they differ from it.

Examples / Gauge September 10, 2026 Grafana Play (signed out; no version string exposed) medium · dark · desktop-web
Nine gauges, and the page makes Few's argument against them without meaning to. The panel at bottom left holds seven arcs reading 30.6, 30.8, 30.8, 30.9, 30.9, 31.0 and 31.3 GB. Seven squares, seven needles, to say that seven disks are all about the same. The same seven values as a bullet graph would be seven short bars in a fraction of the height, and the one that was different would be obvious rather than requiring you to read each label. What the gauges do carry is a bounded range where the endpoints mean something, which is the case the pattern survives: these are percentages and capacities, not rates. The panel beside them is where it stops working—three circular gauges at 40.8, 20 and 48.6 GB, all with a red arc, so a value and another value two and a half times larger get the same verdict.
  • Gauge and dial Seven arcs to report that seven disks agree. This is the area argument in one panel.
  • Sparkline A sparkline inside the arc: the same series encoded twice in one square.
  • Sequential and diverging scales The arc runs pink through green with no perceptual order, so position on it means nothing without the number.
  • Semantic status color 40.8, 20 and 48.6 all arc red. The threshold fires for everything, so it says nothing.
  • Threshold line and region The coloured band around the rim is the threshold, drawn as a region rather than a line.

Netdata

Per-second charts, hundreds per node, with a per-chart anomaly ribbon instead of a band on the series.

Netdata — Metrics / System
Header KPI strip. Twelve tiles in two rows, in four different layouts. It reads as twelve things rather than one strip. Sidebar and canvas. The rail is the dashboard. A generated tree of every metric family the agent found. Gauge and dial. Arcs for disk reads and writes, where the maximum is invented—this is a rate, not a capacity. Dashboard builder. A query builder inline in the panel header: group by, aggregation, node and dimension count. Search across panels. 720 charts, so search is the navigation and the tree is the filing system nobody browses. Semantic grouping. Sections generated by the collector rather than chosen. Consistent, and about nothing in particular. Compare periods. Offered per chart rather than per dashboard, which is the scoping trap: one panel shifted, the rest not. Freshness indicator. Live 1, Stale 8. Most products would have drawn all nine and said nothing.
Metrics / System September 10, 2026 Netdata Agent v2.10.0-686-nightly (public registry node, signed out) dense · dark · desktop-web
Structurally the opposite of Grafana, and worth the comparison. Nobody built this page. The right rail says "showing 720 of total 720 charts" and the tree beneath it—System, Compute, Memory, Storage, Network, Hardware, Processes, then Apps, Users, Groups, O/S Services, and every application it found—is generated from what the agent collects. The canvas is the same hierarchy rendered downward, four levels deep, headings prefixed with dashes: System, then Compute, then CPU, then the chart. There is no editorial layer at all, which means nothing is missing and nothing is prioritised. The header also does something most products won't: it reports "Live 1, Stale 8" beside the node count, so eight of the nine machines behind this view are not currently reporting and the page says so rather than drawing their last known values.
  • Sidebar and canvas The rail is the dashboard. A generated tree of every metric family the agent found.
  • Search across panels 720 charts, so search is the navigation and the tree is the filing system nobody browses.
  • Header KPI strip Twelve tiles in two rows, in four different layouts. It reads as twelve things rather than one strip.
  • Gauge and dial Arcs for disk reads and writes, where the maximum is invented—this is a rate, not a capacity.
  • Semantic grouping Sections generated by the collector rather than chosen. Consistent, and about nothing in particular.
  • Freshness indicator Live 1, Stale 8. Most products would have drawn all nine and said nothing.
  • Dashboard builder A query builder inline in the panel header: group by, aggregation, node and dimension count.
  • Compare periods Offered per chart rather than per dashboard, which is the scoping trap: one panel shifted, the rest not.
Metrics / System › Compute › CPU September 10, 2026 Netdata Agent (public registry node, signed out) dense · dark · desktop-web
Further down the same generated page, and the section nesting is the thing to look at: "− Compute", then "−− CPU", then "−− Pressure Stall Information (PSI)", then "−−− CPU", then "−−−− Some Pressure". Four levels, each collapsible, each named by the collector rather than by a person, and the depth is signalled with leading dashes because there was no design pass to give them a hierarchy in type. It is consistent and completely unedited. Every chart also carries its own query builder in the header—group by, aggregation, node count, dimension count, sample interval—so a panel here is a live query you can re-scope in place rather than a saved configuration. Worth noting what is not in this shot: the sidebar has an Anomaly Rate toggle, switched off, and Netdata's answer to the anomaly problem is a separate derived rate per chart rather than a band drawn around the series. This capture shows the control, not the thing it draws.
  • Collapsible row Four levels of section, depth carried by leading dashes. Generated by the collector, and never edited.
  • Gauge and dial Six arcs. Two are percentages where the endpoints mean something; four are rates in KiB/s and kbit/s on an invented maximum.
  • Legend and series toggle The legend is a value table: steal 0.1, softirq 0, user 1.5113, system 0.9, iowait 0.1, each with its own bar.
  • Dashboard builder A query builder in every chart header, so the panel is a live query rather than a saved configuration.
  • Overview then detail System › Compute › CPU. The breadcrumb is the only thing telling you where in 720 charts you are.