Schedule icon
Request icon
Get icon
Return icon
Set icon
Switch icon
Log icon
SlackIncomingWebhook icon

Mirth Connect Channel Health Sentinel

Check Mirth Connect channels on a schedule, change nothing, and alert Slack when a channel stops, a destination queue grows or new HL7 errors appear.

Categories
BusinessData

Hospitals move admissions, orders and lab results between systems through an integration engine, and Mirth Connect (NextGen Connect) is one of the most widely used. When a destination system goes down, a channel's queue silently grows; when a channel is stopped after maintenance, messages stop flowing; when a mapping breaks, messages end in ERROR. The Mirth dashboard shows all of it, but only to someone looking at it. This blueprint turns two read-only Mirth REST calls into a scheduled integration health gate: /api/channels/statuses returns every deployed channel and its state, /api/channels/statistics returns its counters, the KV store remembers the previous error counts, a single jq query works out what changed, and the result routes to a quiet log, an informational Slack note or a Slack page.

How it works

  1. fetch_channel_statuses (io.kestra.plugin.core.http.Request) reads /api/channels/statuses with basic authentication and the X-Requested-With header Mirth requires. It is a GET with a timeout, three retries, allowFailed: true and allowFailure: true, so an outage never aborts the flow.
  2. fetch_channel_statistics reads /api/channels/statistics: received, sent, error, filtered and queued for every channel. A runIf skips it when the statuses could not be read.
  3. load_previous_error_counts (io.kestra.plugin.core.kv.Get) reads the error counters the previous run saved, with errorOnMissing: false so the first run starts cleanly.
  4. classify_engine (io.kestra.plugin.core.debug.Return) normalises Mirth's JSON (a single channel comes back as an object, not a list), joins statuses, statistics and the previous counters, and computes for every channel its state, queue size and new errors since the last run (a counter that went down after a statistics reset counts from zero). Any channel not STARTED, a queue at critical_queued, or critical_new_errors new errors is CRITICAL; any new error or a queue at warning_queued is WARNING; no deployed channel, a non-200 code or a body that is not JSON is UNREACHABLE; otherwise HEALTHY.
  5. save_error_counts (io.kestra.plugin.core.kv.Set) stores this run's counters for the next run, and is skipped when Mirth could not be read, so an outage never resets the baseline.
  6. route_by_engine_status (io.kestra.plugin.core.flow.Switch) logs HEALTHY quietly, posts a Slack note for WARNING, pages Slack for CRITICAL and UNREACHABLE, and logs any unexpected value in defaults.
  7. log_audit_result writes one audit line per run with both HTTP codes and the classification. The flow-level errors block alerts Slack if the flow fails outright, and the engine_check trigger runs every 10 minutes and ships disabled: true.

What you get

  • A scheduled, read-only health check for every deployed Mirth channel, using only the REST API.
  • Alerts on new errors only: errors from yesterday, already handled, never page again, because the previous counters live in the KV store.
  • A status output (HEALTHY / WARNING / CRITICAL / UNREACHABLE) other flows can gate on, and an engine JSON output with channels, not_running, new_errors, max_queued, largest_queue and the channel names behind each.
  • Slack messages that name the channels, for example Not running: EHR feed (STOPPED). Largest queue: Lab results to EHR (4).

Who it's for

  • Hospital and health system integration teams running Mirth Connect or NextGen Connect.
  • Interface analysts who are on call for HL7 feeds between the EHR, laboratory, radiology and billing systems.
  • Data platform teams already using Kestra who want the same alerting for their integration engine.

Why orchestrate this with Kestra

Mirth can send alerts on errors from inside a channel, but it does not page you when a channel is stopped, when a queue keeps growing because a destination is down, or when the engine itself is unreachable, and its alerts have no memory of what was already reported. Kestra runs the same read-only check on a schedule, keeps the previous counters in its KV store, classifies the whole engine in one typed status, and keeps every run in the execution history, while the Switch branches are ready to grow into follow-up (a ticket for the interface team, a restart after an approval) without changing the check.

Prerequisites

  • A Mirth Connect or NextGen Connect server (3.x or 4.x) whose API port is reachable from Kestra.
  • A dedicated Mirth user for monitoring (with a role that can view channels and statistics on editions that support roles).
  • A Slack incoming webhook for the WARNING, CRITICAL, UNREACHABLE and flow-failure alerts.

Secrets

  • MIRTH_USERNAME and MIRTH_PASSWORD: credentials of the monitoring user (HTTP basic authentication).
  • SLACK_WEBHOOK: Slack incoming webhook used for every alert branch and the flow-failure alert.

In Kestra OSS (no Enterprise secrets backend), secrets are supplied as environment variables prefixed SECRET_ and base64-encoded, then read in flows with {{ secret('NAME') }}, for example SECRET_MIRTH_PASSWORD=$(echo -n '<password>' | base64).

Quick start

  1. To try it without a production engine, download Mirth Connect 4.5.2 (the last open-source release), start it with java -jar mirth-server-launcher.jar (change http.port in conf/mirth.properties if 8080 is taken), and create two channels: one that forwards to a second channel through a Channel Writer with queuing on, and that second channel.
  2. Add MIRTH_USERNAME, MIRTH_PASSWORD and SLACK_WEBHOOK as secrets, set mirth_url (for example https://localhost:8443), and run the flow once: it is HEALTHY and saves the error baseline.
  3. Stop the second channel and send a few messages to the first: they queue, and the next run is CRITICAL with the stopped channel named.
  4. Enable engine_check once pointed at the real server.

How to extend

  • Ignore channels that are stopped on purpose by keeping an allow-list of channel ids in the KV store and filtering them out in the jq query.
  • For each channel with new errors, read the errored messages with /api/channels/{channelId}/messages?status=ERROR and include the first error in the Slack message.
  • Alert only on state changes by storing the last status in the KV store.
  • Send each team its own channel by mapping channel names to Slack webhooks.

Inputs

  • mirth_url: type STRING, default "https://mirth.example.org:8443".
  • warning_queued: type INT, default 50.
  • critical_queued: type INT, default 500.
  • critical_new_errors: type INT, default 10.

Outputs

  • status: one of HEALTHY, WARNING, CRITICAL, UNREACHABLE.
  • engine: the full classification as JSON, for example {"channels":3,"not_running":1,"new_errors":0,"max_queued":4,"not_running_channels":"EHR feed (STOPPED)","error_channels":"none","queued_channels":"none","largest_queue":"Lab results to EHR (4)","status":"CRITICAL",...}.

Links

Pitfalls

  • Mirth's REST API rejects requests without the X-Requested-With header (cross-site request protection). Both requests set it; keep it if you add calls.
  • Mirth serves its API with a self-signed certificate out of the box, which Kestra rejects (the run reports UNREACHABLE). Install a certificate from your own CA. For a throwaway test server only, you can add ssl: { insecureTrustAllCertificates: true } under options of both requests.
  • Statistics are counters since the last reset. The flow only alerts on the difference to the previous run, so the first run after deploying the flow is a baseline and cannot report errors that happened before it.
  • Undeployed channels do not appear in the statuses at all. A channel that should exist but is missing is not reported; add an expected channel list if you need that.
  • The check only reads. It never starts, stops, redeploys or reprocesses channels or messages.
See How

New to Kestra?

Use blueprints to kickstart your first workflows.