Generic JSON API — monitor any HTTP/JSON endpoint without writing a plugin

Hi everyone :waving_hand:

I’ve just published a new plugin on the Checkmk Exchange and wanted to share it here: Generic JSON API.

Exchange: Checkmk Exchange
Source & docs: GitHub - otAAAh/checkmk-json-agent: Generic Checkmk special agent for polling JSON status APIs and turning fields into monitored services. · GitHub

What it does

It’s a generic special agent that turns any HTTP/JSON API into Checkmk services — no custom Python, no per-integration MKP. Point it at a /health, /status
or /actuator/health endpoint, tell it which fields to watch, and it creates services with thresholds, metrics and graphs, all from one Setup rule.

Features

  • GET or POST over HTTP/HTTPS, custom headers and an optional request body
  • Multiple endpoints per rule — each with its own method/headers/auth/timeout/fields; an unreachable endpoint only affects its own services
  • Auth: none, HTTP basic, or bearer token — secrets go through the Checkmk password store, never in clear text on the command line
  • Dotted path extraction: status, components.db.status, items[0].count
  • [*] array auto-discovery: e.g. nodes[*].status creates one service per element (labelled by a field you pick); nested wildcards expand the cartesian
    product
  • Thresholds (WARN/CRIT upper & lower) with metrics/graphs and selectable units (count / bytes / seconds / percent)
  • Regex string matching for non-numeric values
  • TLS verification on by default, plus a per-endpoint Follow-redirects toggle to harden against redirect-based SSRF
  • Unreachable endpoints / non-JSON responses surface as UNKNOWN on the affected services — never a crash

Try it before you configure

The repo ships a standalone, dependency-free JSON API Explorer web page: paste a sample JSON response, click the fields you want, set thresholds/labels, and it
generates the ready-made rule config (agent CLI blob, rules.mk value, and a REST API request + curl). Nothing is uploaded anywhere — it runs entirely in your
browser.

:point_right: JSON API Explorer — checkmk-json-agent

Requirements

  • Checkmk 2.4.0 or newer, any edition
  • Built against the current stable plugin APIs (cmk.agent_based.v2, cmk.rulesets.v1, cmk.server_side_calls.v1, cmk.graphing.v1)

Quick start

After installing the MKP, create a rule under Setup → Agents → Other integrations → Generic JSON API.

Feedback, bug reports and feature ideas very welcome — either here or on GitHub. Hope it saves someone the “yet another one-off JSON check” work it was born out of!

5 Likes

Looks very interesting - love the API Explorer. Thanks for sharing Benni :slight_smile: Will test this!

How much of the claude LLM is in the commits?

1 Like

Claude was used for generating all of the code.
With the clear plugin API this is quite easy.
Never the less before generating, i had several hours of investigation for scope and boundaries.
And in the end… tested it manually on 2.4 and 2.5 sites.

1 Like

Hello Benni,

I just tested it with some of my JSON endpoints and it works really well.
I had only 1 issue and 1 suggestion for improvement.

Macros like $HOSTNAME$ in the URL are not working for me.-> Failed to resolve '$hostname$

In the “Summary” and especially in the “Details” result of the check you could display a bit more information, e.g., the extracted JSON path.

Thank you very much for your efforts!

BR
Mario

Quick update — v0.3.0 is out :tada:

Thanks again for all the feedback in this thread — a big part of this release came straight from it, especially the points @Mario_Sommer raised:

  • Checkmk macros are now resolved in the endpoint URL, request body and headers ($HOSTNAME$, $HOSTADDRESS$, custom host macros, …), so a single rule can now be
    reused across many hosts. :raising_hands:
  • Richer check details: the monitored JSON path and the source URL now show up in the service’s Details output, so it’s obvious where each value came from.
  • Under the hood, the pytest suite now runs inside the official Checkmk container in CI for more realistic testing.

And in case anyone missed v0.2.0 since the first post, that one already brought a fair bit:

  • Multiple endpoints per rule — each with its own method/headers/auth/timeout/fields, merged into one section (an unreachable endpoint only affects its own services)
  • Nested [] array wildcards via cartesian-product expansion (pods[].containers[*].ready) with composite labels
  • Bracket-quoted path segments for keys containing . or [, e.g. data[‘foo.bar’].value
  • Per-field metric units and naming
  • A per-endpoint “follow redirects” toggle (on by default; turn it off to harden against redirect-based SSRF)
  • Checkmk 2.4 support via version-adaptive secret resolution, plus a batch of robustness fixes (regex crash, silent levels, timeout option, POST content-type
    default, unique service names)

Grab it from the Exchange / GitHub as usual:

mkp add json_api-0.3.0.mkp
mkp enable json_api 0.3.0

Keep the feedback coming — it’s shaping the roadmap directly. :slightly_smiling_face:

1 Like

Hi all,

Two releases have landed since my last post here — 0.4.0 and 0.5.0 — both now on the Releases page. If you’re on 0.3.0, jump straight to 0.5.0; it’s a clean drop-in,
no rule changes needed.

0.4.0 — hardening & robustness

  • Special agent hardening: a response-size cap (a huge/runaway API body can no longer blow up the check), stricter secret isolation, and safer concurrency.
  • Check/ruleset edge cases fixed: URL-scheme validation, non-numeric level values, and inf/nan no longer trip things up.
  • JSON API Explorer brought up to full feature parity with the plugin, so the standalone path-tester matches what the agent actually does.
  • Localized Setup UI (German to start).

0.5.0 — correctness fixes

  • Misconfigured levels now surface even when the expected string match fails — a failed regex match no longer masks a bad WARN/CRIT config.
  • A malformed blob or extraction error stays confined to its own endpoint — with multiple endpoints per rule, one bad response no longer takes out the healthy
    endpoints’ services.
  • No Content-Type header on a GET with no body — keeps stricter APIs happy.
  • Case-insensitive URL schemes (HTTPS://… is accepted).

Upgrade as usual, as the site user:

mkp add json_api-0.5.0.mkp
mkp enable json_api 0.5.0

Existing rules carry over untouched — nothing to reconfigure. Full details in the CHANGELOG. As always, feedback and edge cases welcome — several of these fixes came
straight out of configs people shared here. Thanks! :folded_hands:

Great! @mimimi - didn’t you want this? :slight_smile:

Generic JSON API — v0.6.0 is out :tada:

A polish-and-trust release, built on your feedback:

  • :globe_showing_europe_africa: The Setup UI now speaks every Checkmk-supported language — the rule form and help texts are fully localized, so the special agent configures just as cleanly in
    your language as in English.
  • :white_check_mark: Tested on both Checkmk 2.4 and 2.5 in CI, so upgrades and mixed fleets are covered.
  • :locked: Supply-chain hardening — the .mkp is now built with signed build provenance, GitHub Actions are pinned by SHA, and CodeQL + Dependabot run on every change.
  • :compass: The JSON API Explorer can’t drift anymore — a CI guard keeps the standalone Explorer in lockstep with the plugin’s config schema, so the rules it generates
    always import cleanly.

Grab it from the Checkmk Exchange or the GitHub release. Full changelog in CHANGELOG.md.

Thanks for the reports and feature requests — keep them coming! :folded_hands:

Generic JSON API — v0.7.0 released :tada:

Small but useful release for the Generic JSON API special agent (monitor any HTTP/JSON API in Checkmk, no custom code — one Setup rule).

What’s new in 0.7.0

  • :compass: [] wildcard now expands over JSON objects/maps, not just arrays. So a Spring Boot Actuator /health like {“components”: {“db”: {“status”: “UP”}, “diskSpace”:
    {“status”: “UP”}}} — where the entries are keys, not a list — auto-discovers one service per component with components[
    ].status. Previously [*] only worked on
    arrays.
  • :memo: Added a contributing guide and issue templates — bug reports and feature requests are very welcome.
  • :package: Refreshed the Exchange listing to cover object-map discovery and multi-endpoint rules.

As a reminder, the agent already does: multiple endpoints per rule, path extraction (components.db.status, items[0].count), basic/bearer auth via the password store,
WARN/CRIT thresholds + graphs, and a bundled field picker.

Requirements: Checkmk 2.4+ (any edition), tested on 2.4 and 2.5.

Get it: grab the .mkp from the Releases page, then mkp add json_api-0.7.0.mkp / mkp enable json_api 0.7.0 (or upload via Setup → Extension packages).

Feedback and bug reports appreciated!

Yes, nice extension!
I have waited for that for years, JFYI now others delivered as well:

Generic JSON API — v0.8.0

Monitor any HTTP/JSON API in Checkmk without writing a line of code. Point the
special agent at a /health, /status, or metrics endpoint, pick the fields you
care about by path, and each becomes a Checkmk service with thresholds, metrics
and alerts. One Setup rule, any API — no per-integration MKP development.

Works on Checkmk 2.4+, any edition.

What’s new in 0.8.0

  • Count elements :1234: — instead of a value, monitor how many elements a path
    holds: array length or number of object keys. Great for queue length, number of
    unhealthy nodes, etc. The count is a number, so units, WARN/CRIT levels, the
    transform and a metric all apply to it. (Where a [*] wildcard fans a
    collection out into one service per element, count collapses it into a single
    “how many” service.)

  • String matching, two ways :input_latin_letters: — either require a value to fully match a regex
    (and choose the state when it doesn’t — default CRIT), or map the value straight
    to a state by matching it against separate OK / WARN / CRIT regexes (tried in
    that order, first full match wins, configurable state when nothing matches).
    Ideal for fields like ready / degraded / failed.

  • Transform the numeric value :abacus: — an optional arithmetic expression over the
    variable value, applied before levels and the metric, e.g. value / 1024 / 1024
    (bytes → MiB) or (value - 32) * 5 / 9 (°F → °C). Only numbers, parentheses and
    + - * / are allowed, and it’s evaluated safely — never eval.

  • New: in-site Explorer wizard :compass: (optional companion package,
    json_api_explorer, Checkmk 2.5+) — a guided setup under
    Setup → Quick setup → Generic JSON API that fetches your endpoint’s live
    response, lets you point-and-pick fields with a preview of the resulting service
    states, and creates the rule for you. Install it alongside the agent package.

Fixes

  • The check no longer crashes on a blank/whitespace transform expression — a
    blank value is correctly treated as “no transform”.
  • The agent now flushes stdout, so its section shows up when you copy the program
    call out of cmk -D <host> and run it by hand on a terminal.

Install

As the site user:

mkp add json_api-0.8.0.mkp
mkp enable json_api 0.8.0

…or upload it under Setup → Extension packages. For the guided wizard on
2.5+, install the companion json_api_explorer package the same way after the
agent.

Links

Feedback, bug reports and feature ideas are very welcome — happy monitoring! :slightly_smiling_face:

1 Like

[Release] Generic JSON API v0.9.0 — Checkmk labels + a per-folder threshold ruleset

Hi all,

New release of the Generic JSON API special agent — the plugin that lets you monitor any HTTP/JSON API (a /health, /status, or metrics endpoint) as Checkmk services,
thresholds and graphs included, from a single Setup rule. No per-integration Python, no MKP building.

Download: Release v0.9.0 · otAAAh/checkmk-json-agent · GitHub (or grab it from the Checkmk Exchange). Works on Checkmk 2.4+, any edition.

What’s new in 0.9.0

:label: Checkmk labels from your JSON
You can now turn API fields into labels:

  • Service labels — mark an extracted field as a label and it becomes json_api/ on that service. With a [*] wildcard each per-element service gets its own value,
    so you can slice/filter services by, say, region, tier, or version straight out of the response.
  • Host labels — endpoint-level fields (resolved from the response root, decoupled from services) get attached to the host. A [*] path emits one label per element —
    handy as set-membership tags (e.g. “this host runs component X”).

This plugs your APIs straight into label-based host/service filtering, rules, and views.

:level_slider: New check-parameters ruleset — override thresholds per folder/host/service
Until now, WARN/CRIT levels and string matching lived only in the special-agent rule, which is first-match-wins and doesn’t merge — so you couldn’t tune them per
folder the standard Checkmk way. There’s now a proper check-parameters ruleset (checkgroup_parameters:json_api). The levels you set in the special-agent rule become
the service’s discovered defaults, and a check-params rule overrides them with normal Checkmk precedence (plugin defaults < discovered < rule). Existing single-rule
setups keep working unchanged — nothing to migrate.

:compass: Explorer / in-site wizard fixes

  • Fixed a packaging bug where the released json_api_explorer MKP shipped without its wizard bundle and crashed on load — the Explorer companion (Checkmk 2.5+) now
    builds and installs correctly. If you tried the Explorer on an earlier release and it broke, this is the one to install.
  • Quicksetup wizard improvements: an “Apply to the whole target folder” option, a cleaner step-2 split into Services / Host labels, and a hover-reveal “+ Add” picker
    (Monitor / Host label) in the JSON tree.

Small stuff

  • The configured unit (bytes/seconds/percent) now shows in the check summary, not just the graph.
  • Renamed the confusing “Item label path” field to “Per-element name suffix”.

Full changelog: checkmk-json-agent/CHANGELOG.md at main · otAAAh/checkmk-json-agent · GitHub

As always, feedback, bug reports, and feature requests are very welcome — either here or on GitHub. Enjoy! :slightly_smiling_face:

PS: some teasing screen of the explorer in the QickSetup:

1 Like

Hi all,

I’ve just released v0.10.0 of checkmk-json-agent — a generic special agent for monitoring any HTTP/JSON API. You point it at a /health, /status or similar endpoint,
extract fields by a dotted path, and turn them into Checkmk services with thresholds, metrics and graphs. No custom Python and no per-integration MKP development —
it’s all one Setup rule.

It targets Checkmk 2.4+ and the current stable plugin APIs (cmk.agent_based.v2, cmk.rulesets.v1, cmk.server_side_calls.v1, cmk.graphing.v1).

:sparkles: New in 0.10.0

  • Filter elements by a condition — restrict a [*] wildcard (or a count) to just the elements whose sub-field matches. E.g. one service per node whose status is not
    ok, or count only the pods that aren’t Running (equals / not-equals / regex / not-regex).
  • Custom CA bundle + client certificate (mTLS) — trust a private CA and authenticate with a client cert, in addition to the existing TLS on/off toggle.
  • HTTP proxy support per endpoint — environment variables, an explicit proxy URL, or bypass — for APIs only reachable through a corporate egress proxy.
  • Accept non-2xx status codes — opt specific codes in per endpoint, e.g. accept 503 to read a health endpoint that reports its problems with a 503 and a JSON body.
  • –debug flag on the special agent for easier troubleshooting.
  • Plus dependency/CI housekeeping.

:package: Downloads

Grab the .mkp from the Releases page:

  • json_api-0.10.0.mkp — the special agent (Checkmk 2.4+)
  • json_api_explorer-0.10.0.mkp — an optional in-site Explorer/wizard UI to build and preview rules (Checkmk 2.5+)

Install:

mkp add json_api-0.10.0.mkp
mkp enable json_api 0.10.0

Feedback, bug reports and feature ideas are very welcome — either here or on GitHub.

Cheers!

Hi all,

v0.11.0 of checkmk-json-agent is out — the generic special agent for monitoring any HTTP/JSON API. You point it at a /health, /status or metrics endpoint,
extract fields by a dotted path, and turn them into Checkmk services with thresholds, metrics and graphs. No custom Python and no per-integration MKP development —
it’s all one Setup rule.

Still Checkmk 2.4+ and the current stable plugin APIs (cmk.agent_based.v2, cmk.rulesets.v1, cmk.server_side_calls.v1, cmk.graphing.v1).

This release is about the three things people kept having to work around: counters, timestamps, and collections.

New in 0.11.0

  • Aggregate a collection into one value — the old count elements switch grew into a choice: count / sum / average / minimum / maximum. Point the path at an
    array or object (jobs) or at a [*] wildcard over the values (queues[*].depth) — the wildcard then yields one service instead of one per element. Combine it
    with the existing condition to aggregate only part of a collection, e.g. sum the load of the nodes that aren’t ok. Existing rules using the old switch are
    migrated automatically, nothing to change.

  • Counters → per-second rate — mark a field as a counter and the check monitors its change per second instead of an ever-growing total. requests_total: 184203219 becomes Rate: 212/s, with a rate metric of its own so it never mixes into the absolute value’s history. (The first check after a counter reset has
    nothing to compare against, so it keeps the service’s previous state and says so.)

  • Timestamps → age — mark a field as a timestamp and the check monitors how old it is, so upper levels alert on stale data: {"last_backup": "2026-07-28T02:00:00Z"}Age: 1 day 2 hours, WARN once the backup is older than 26 h. Unix epoch seconds, epoch milliseconds and ISO 8601 are all accepted and
    auto-detected; a timestamp without a time zone is read as UTC.

  • Every endpoint now monitors itself — besides the field services, each endpoint gets a JSON API <name> service reporting the request: HTTP status,
    response time and response size, with the URL (and the redirect target, if any) in the Details. It needs no field configuration at all, and its thresholds live
    in a check-parameters ruleset of its own (Generic JSON API endpoint), where you can also soften the CRIT to WARN for an endpoint that’s allowed to be down.

  • Plus the usual dependency/CI housekeeping.

:bulb: Heads-up for existing users: after upgrading, the next service discovery will show one new JSON API … service per configured endpoint. That’s the new
endpoint monitoring — keep it, or drop it with a Disabled services rule.

Downloads

Grab the .mkp from the Releases page:

  • json_api-0.11.0.mkp — the special agent (Checkmk 2.4+)
  • json_api_explorer-0.11.0.mkp — the optional in-site Explorer/wizard to build and preview rules (Checkmk 2.5+)

Install:

mkp add json_api-0.11.0.mkp
mkp enable json_api 0.11.0

The Setup UI is localized into all Checkmk UI languages, so the new options show up in your language too.

Feedback, bug reports and feature ideas are very welcome — either here or on GitHub.

Cheers!

Generic JSON API 0.12.0 — one Checkmk host per array element, TLS cert expiry, response caching

Version 0.12.0 of the Generic JSON API
special agent is out. It monitors any HTTP/JSON API from one Setup rule — no custom
Python, no MKP per integration.

This release is mostly about the things you asked for once the basics worked: turning a
JSON collection into real Checkmk hosts, watching the certificate of the API you
are already polling, and not hammering a rate-limited API to death.

🖧 One Checkmk host per array element

Until now a [*] wildcard gave you one service per element: nodes[*].health on a
fleet of 50 became one host carrying JSON Health node-01node-50.

Now you can point a field at a host name inside each element instead, and every
element becomes a Checkmk host of its own:

nodes[*].health   +   "one host per element, named by: name"

  →  host web-1 :  JSON Health
     host web-2 :  JSON Health
     host web-3 :  JSON Health

Set the same field on several fields of that endpoint (nodes[*].load,
nodes[*].version) and they all land on those same hosts.

Why bother, when the services already told you the same thing? Because a host is a
first-class object in Checkmk and an array element is not. Each element now gets its own
downtimes, acknowledgements, contact and host groups, availability report, parent/child
relationships and place in the folder tree. That is the difference between monitoring an
API and monitoring the fleet the API describes.

:warning: One thing to know before you enable it: this uses piggyback, so the standard
Checkmk rule applies — data for a host that does not exist in Checkmk is stored and
never monitored.
No error, no warning, nothing on the polling host. Create the hosts
first (by hand, or with Dynamic host management), then run a discovery. If you switch it
on and see nothing at all, that is why.

:locked_with_key: TLS certificate expiry, for free

Every endpoint already gets a JSON API <name> service reporting the request itself —
HTTP status, response time, response size. It now also reports how long the TLS
certificate is still valid
, with optional lower levels in days:

JSON API frontend    OK
  HTTP 200
  Response time: 31 ms
  Certificate expires in: 42 days

It is read from the connection the agent is already making, so there is no extra request
and no second check_http rule against the same URL with the TLS settings configured
twice and drifting apart.

Only for HTTPS endpoints with certificate verification enabled — otherwise nothing about
the certificate is reported. That is absent, not expired, and never alerts.

:turtle: Rate-limited or expensive API? Cache it

Every check interval, on every host using the rule, the agent requested every endpoint.
For a cheap /health that is right. For an API with a request quota — or one rule shared
across fifty hosts — it is how monitoring becomes the outage it was supposed to detect.

Give an endpoint a TTL (“Re-read at most every N seconds”) and the agent reuses the
last response while it is younger than that.

It is deliberately strict about the honest cases:

  • It never hides a failure. A failing request is not answered from an expired cache
    — the endpoint goes CRIT as usual. A cache makes an endpoint less frequently polled,
    not more available.
  • It never caches an error. Only a response that parsed as JSON is stored.
  • It never reports a response time it did not measure. While a cached body is served
    the service says from cache (N old) and records no response-time metric. So gaps in
    that graph are intervals where nothing was measured, not intervals where the API was
    slow.

Also in this release

  • Two endpoints can no longer be given the same name — the name is a service item, and
    a collision could only be resolved positionally, so reordering endpoints silently
    swapped two services’ history.
  • Fixes: a future timestamp with unit seconds crashed the check (negative duration);
    count over a [*] path now counts the same elements the other aggregations do; an
    API key in a URL’s query string no longer lands in a service description; the
    wizard’s review step no longer previews a pre-filter element count.
  • New UPGRADING.md
    — the operator-facing notes (service renames, new services appearing, changed results)
    now travel with each release, because a generated changelog can only say what changed in
    the code, not what it means for a running site.

:warning: Two behaviour changes worth reading

Both are in the upgrade notes, and both are one-time:

  1. Endpoints without a name take their service item from the URL, now without the
    query string
    — so a credential passed as ?api_key=… no longer ends up in a service
    description (which reaches notifications, availability reports and the metric paths).
    Those services are renamed once. Naming your endpoints avoids this entirely.
  2. count over a [*] path that names a field now counts only the elements that
    actually have that field, matching what sum/avg/min/max always did. If the
    field is sometimes absent the number drops; if no element has it (usually a typo in the
    path) the service goes UNKNOWN instead of silently reporting the element count.

Get it

mkp add json_api-0.12.0.mkp
mkp enable json_api 0.12.0

On Checkmk 2.5+ there is also the optional companion package Generic JSON API –
Explorer (extra)
(json_api_explorer): a guided in-site wizard under Setup → Quick
setup
that fetches your API’s real response, lets you click the fields to monitor, and
writes the rule for you. It covers the new per-element-hosts option too. There is a
dependency-free browser version in the repo (explorer/index.html) if you would rather
not install anything.

Feedback and bug reports very welcome — especially on the per-element hosts, which is the
biggest change in how this plugin can be used.

0.13.0 is out. Four additions, and the first one changes what this plugin is
allowed to do with a field — so it leads, because it is also the one most likely to
have you asking where your service went.

:clipboard: A field can be a fact instead of a service

Plenty of what an API tells you about itself is not a state at all: a version, a build,
a region, a licence tier, the list of nodes in a cluster. Until now the only thing this
plugin could do with those was make a service that is OK forever — a service slot and a
check every interval to report something that changes twice a year.

Point such a field at an inventory tree node instead:

version   +   "write into the HW/SW inventory: software.applications.json_api"

  →  Host → Inventory → Software → Applications → json_api
       version   4.2.1

A [*] wildcard becomes a table, one row per element, keyed by the element’s own
label — so nodes[*].version and nodes[*].role fill in two columns of the same rows:

nodes[*].version  →  name    version   role
                     web-1   4.2.1     leader
                     web-2   4.2.1     follower

The reason to bother is the thing services cannot do: the inventory is searchable
across hosts. “Which of our 300 API hosts still run a version below 4.2?” is one
query against the inventory and no query at all against a service summary. It also keeps
its own change history.

:warning: The one thing to know: an inventory field creates no service — that is the
point of it, but it means turning it on for a field that already is a service removes
that service on the next discovery, and its metric history goes with it. If you want
both, tick “Also create a service for this field” in the same edit. Inventory also
runs on its own, slower schedule, so a newly configured field turns up at the next
inventory run, not the next check.

:key: API keys from the password store

Basic auth and bearer tokens always went through the Checkmk password store. A plain
API keyX-API-Key, PRIVATE-TOKEN, apikey, whatever the vendor calls it — did
not, because there was no auth choice for it. The only way was Additional request
headers
, which stores the key in clear text in the rule, puts it on the agent’s command
line, and prints it in --debug output.

There are now two proper choices: API key in a request header (you name the header)
and API key in a query parameter. Both take the key from the password store, so it
is rotated in one place and never written into the configuration.

The query-parameter one is redacted from every URL the agent reports — the endpoint
service’s final URL, request errors, debug output. It still travels inside the URL to
the server, so prefer a header where the API offers one.

:repeat_button: Retry a request instead of alerting on a blip

A connection reset, a DNS hiccup, or a 502 from an ingress during a rolling restart used
to be an unreachable endpoint: CRIT, notification, RECOVERY a minute later, nothing
learned.

An endpoint can now retry (1–5 times, with a doubling backoff). What gets retried is
decided per failure rather than by a blanket count:

connection error, timeout, HTTP 429/5xx retried
HTTP 4xx, a body that is not JSON, an oversized response never — they answer the same however often you ask

It does not hide what it absorbs: the endpoint service reports “succeeded after N
retries”
, and you can set that to WARN. A retry policy that quietly turned a degrading
API into a permanently green service would be worse than the noise it removes.

Off by default. Worst case is (1 + retries) × timeout plus the waits, and total backoff
is capped at 30 s.

:speech_balloon: Show the reason next to the value

Health endpoints rarely put the whole story in one field:

{"status": "DEGRADED", "message": "replica lag 42s", "leader": "db-3"}

Monitoring status gave you Value: DEGRADED and nothing else; the explanation the API
already returned needed a second service, which then alerted separately and arrived in
notifications as an unrelated line.

A field now takes an optional summary text with {path} placeholders:

{message} (leader {leader})

  →  JSON DB status   CRIT   Value: DEGRADED, replica lag 42s (leader db-3)

Paths resolve within the current [*] element, so the text describes that node. It is
presentation only — it never changes the state, the levels or the metric.

Upgrading

Both notes are in
UPGRADING.md and
both are one-time:

  1. Sending an existing field to the inventory takes its service away (above).
  2. Cached endpoints refetch once. The response cache now keys entries on the
    credential as well as the URL — without it, several rules polling the same
    multi-tenant URL with a different API key each shared one cache entry. One extra
    request per endpoint, once.

Nothing else changes for an existing rule: all four additions are opt-in.

Get it

mkp add json_api-0.13.0.mkp
mkp enable json_api 0.13.0

On Checkmk 2.5+ the optional companion package Generic JSON API – Explorer (extra)
(json_api_explorer) is updated too: its review step now tells you which fields will
become inventory entries rather than services, and counts them separately, so the
“where did my service go” question is answered before you create the rule. The
dependency-free browser version in the repo (explorer/index.html) covers all four
additions as well.

As ever, feedback and bug reports welcome — particularly on the inventory side, which is
the biggest change in what a field can be.

3 Likes

Hi Benni,

Great plugin, very much appreciated.

It really shows what’s possible in Checkmk when someone pushes things a bit further :+1:.

One small detail though: it seems you may also have fallen victim to Checkmk’s legendary “tiny input field syndrome” :grinning_face_with_smiling_eyes:

Even with fairly short URLs or filenames, you already have to scroll horizontally inside the field just to read the full value, for example:

https://app.ab.bliblablub.prod.dideldidum.shared-ad.ch/health

It would be great if input fields in Checkmk were generally sized according to realistic string lengths, so values remain readable unless they are unusually long. Especially nowadays, strings tend to be longer than they used to be.

Thanks again for the plugin and the effort behind it.

Lars

1 Like

Hey Lars,

thx for your reply and the feedback.

I will have a look on input fields. However the trap is using the builtin form specs.

BR
Benni

0.14.0 is out. Three additions and one fix. The additions all come from the same
place: the response has more in it than the body, and a field is rarely interesting on
its own.

:divide: A value measured against another value

Almost no API returns a percentage. They return a pair — used and total,
current and limit, active and max_connections — and leave the division to you.
Until now the transform could only see the field it was attached to, so the only way to
alert on “the pool is 90% full” was to hard-code the capacity into the expression and
edit the rule whenever it changed.

A field can now name a second path, available to the transform as other:

JSON path     pools[*].used
Second path   total
Transform     value / other * 100      unit: %      upper levels 80 / 90
{"pools": [{"id": "sda", "used": 25, "total": 100},
           {"id": "sdb", "used": 180, "total": 200}]}
JSON Pool sda    OK     Value: 25.00%
JSON Pool sdb    CRIT   Value: 90.00%

The second path is resolved inside the same element as the value, so every element
is measured against its own total — not against the first one’s. That is the whole
reason it is resolved by the agent rather than the check: only the agent has the
document and knows which element it is looking at.

If the second path is missing for some element, that service reports the calculation as
failed rather than substituting a value. A missing total silently becoming 1 would
produce a number that looks entirely plausible and is entirely wrong.

:receipt: Monitor a response header, not just the body

An API tells you things outside the JSON. The most useful is how much of your quota is
left — which this plugin, whose entire job is calling APIs on a schedule, could not see.

Prefix a path with @header.:

@header.X-RateLimit-Remaining   lower levels 100 / 20   →  the budget, before it runs out
@header.Last-Modified           as a timestamp          →  how stale the data is
@header.Retry-After                                     →  how long the API wants you to back off

Header names are matched case-insensitively, and none of the body path syntax ([*],
aggregation, filters) applies to them — a header is a single scalar.

Last-Modified and a date-form Retry-After are HTTP-dates
(Wed, 21 Oct 2015 07:28:00 GMT), which is neither a number nor ISO 8601, so the
auto timestamp format learned to read them. :warning: That widening is the one upgrade note
in this release — see below.

Both Explorers offer the headers for picking, so you are not typing a name from
memory. The in-site wizard has a Headers tab beside the field picker: the Checkmk
server made the request, so it already has them. The browser-only Explorer makes no
request at all, so it has a Response headers paste area instead — paste curl -sSi
output and it lists the names to click. The status line and the body below it are
ignored, so you can paste the whole dump.

:label: Label the hosts a [*] rule creates

Pointing a wildcard field at a piggyback host turns 50 array elements into 50 Checkmk
hosts. Those hosts arrived with no labels at all, so there was no way to target them with
a folder rule, a view or a filter — you got 50 hosts and no way to say anything about
them as a group.

An element’s own fields can now become host labels on the host it becomes:

JSON path              nodes[*].health
One host per element   name
Labels for that host   region,  role → key "tier"

  →  host node-01   json_api/region:eu-west   json_api/tier:worker
     host node-02   json_api/region:us-east   json_api/tier:leader

Each host is labelled from its own element. Several fields placed on the same host
contribute to one set of labels rather than fighting over it.

There are now three kinds of label in the rule, and it is worth knowing which is which:

attaches to resolved from
Labels for that host (new) the created piggyback host the [*] element
Service labels the individual service the [*] element
Host labels (on the endpoint) the polling host the response root

The last one is unchanged and stays on the polling host — it describes the API, not any
element inside it.

:lady_beetle: Fixed: the rule form crashed when a required field was emptied

Reported by @lasoe (#161) —
thank you, the crash report made this a five-minute diagnosis.

Clearing a required field (a service name or a JSON path) and clicking Save took out the
whole Setup page with TypeError: Unexpected extraction value: None instead of
highlighting the offending box. The rule was fine; you just could not edit it any more
without the form breaking.

The cause was ours: after a failed save Checkmk re-renders the form, and the emptied
entry arrives at the plugin’s migration hook as None, which it treated as a programming
error and raised on. A migration runs while the form is being drawn — there is nothing
there to catch an exception and tie it to a field, so raising costs you the entire form.
Both migration hooks now degrade to an empty row instead, which is the box that needs
your attention anyway.

If you saw the form appear twice below Fields to monitor after a failed save, that
was the same bug — the exception fired part-way through drawing it.

Upgrading

One note, and it is narrow:

A timestamp field with format auto now reads HTTP-dates. If you have a field
configured as a timestamp whose value is an HTTP-date, it was reporting UNKNOWN
(Not a valid timestamp) and will now resolve to a real age — so with upper levels set
it can go WARN or CRIT where it previously sat UNKNOWN. The explicit ISO 8601 format
is unchanged and stays strict. Full text in
UPGRADING.md.

Everything else is opt-in and nothing changes for an existing rule.

Get it

mkp add json_api-0.14.0.mkp
mkp enable json_api 0.14.0

On Checkmk 2.5+ the optional companion package Generic JSON API – Explorer (extra)
(json_api_explorer) is updated too — that is where the Headers tab lives. The
dependency-free browser version in the repo (explorer/index.html) covers all three
additions as well.

Feedback and bug reports welcome, and keep them coming — one of the four items above is
here because someone filed a good one.

1 Like