Query icon
OutputValues icon
Return icon
Switch icon
Log icon
SlackIncomingWebhook icon
If icon
Loop icon
Request icon
Fail icon
Schedule icon

Dremio Reflection & Job Health Gate

Audit Dremio Reflections and running jobs via sys.reflections and sys.jobs, alert Slack on failures, and cancel stuck jobs through the REST API.

Categories
DataInfrastructure

A Dremio Reflection that stops refreshing does not fail loudly, queries that used to hit the accelerated Reflection silently fall back to a full scan of the raw dataset, and nobody notices until a dashboard that used to load in two seconds takes two minutes. Likewise, a query job stuck in RUNNING for hours quietly holds an engine slot that a real workload needs. This blueprint queries Dremio's own sys.reflections and sys.jobs system tables on a schedule, flags any Reflection that is FAILED, CAN_ACCELERATE_WITH_FAILURES, or has accumulated failures, flags any job still RUNNING past a runtime threshold, pages Slack the moment one is found or Dremio cannot be queried, and can cancel the stuck jobs through Dremio's REST API, then re-query to verify none remain RUNNING. plugin-jdbc-dremio ships only Query, Queries, and Trigger, there is no SQL statement to cancel a job in Dremio, so cancellation calls Dremio's own POST /api/v3/job/{id}/cancel REST endpoint directly, the same pattern Dremio's own REST client uses.

How it works

  1. probe_reflections (io.kestra.plugin.jdbc.dremio.Query) selects Reflections that are already FAILED, CAN_ACCELERATE_WITH_FAILURES, or at or above reflection_failure_threshold failures, read-only, with allowFailure: true.
  2. probe_stuck_jobs selects every job currently RUNNING; the runtime threshold is applied afterward, not in SQL, also read-only with allowFailure: true.
  3. findings (io.kestra.plugin.core.output.OutputValues) combines the failed Reflections with the jobs whose computed runtime exceeds stuck_job_after_minutes into one findings array, each entry tagged REFLECTION_FAILED or STUCK_JOB.
  4. classify_status (io.kestra.plugin.core.debug.Return) returns UNREACHABLE when either probe's rows field is not defined, AT_RISK when the findings array is non-empty, otherwise CLEAN.
  5. route_by_status (io.kestra.plugin.core.flow.Switch) branches on that string:
    • CLEAN: logs a quiet confirmation.
    • AT_RISK: alert_at_risk posts every finding to Slack. cancel_gate runs only when auto_cancel_stuck_jobs is true, dry_run is false, and at least one STUCK_JOB finding exists: cancel_loop (concurrencyLimit: 1) sends one REST cancel request per stuck job, reread_stuck_jobs re-queries sys.jobs for those job IDs, and verify_cancel fails the flow if any of them is still RUNNING. Failed Reflections are always report-only, there is no automated fix for a broken Reflection from this flow.
    • UNREACHABLE: alert_unreachable posts a separate Slack message.
  6. log_audit_status records a status line on every run regardless of branch.
  7. The errors block alerts Slack separately if the flow itself fails outright.
  8. The dremio_health_gate_schedule trigger polls every 15 minutes with explicit input overrides, shipped disabled: true and always in safe mode (auto_cancel_stuck_jobs: false, dry_run: true).

What you get

  • A scheduled, system-table-native audit of Dremio's acceleration layer and job queue with zero custom client code.
  • A three-way status output (CLEAN / AT_RISK / UNREACHABLE) you can chart or gate other flows on.
  • A Slack page naming every failed Reflection and every stuck job with its runtime, with cancellation applied and verified behind auto_cancel_stuck_jobs and dry_run.
  • A standing audit log line per run and a separate failure channel for the gate flow itself.

Who it's for

  • Data platform teams running self-hosted Dremio as a semantic and acceleration layer over a lakehouse, who need to know when a Reflection silently stops accelerating queries.
  • Teams who have had a runaway or stuck query hold an engine slot for hours with nobody noticing until concurrency ran out.
  • Teams evaluating the Dremio plugin who want an example of sys.reflections and sys.jobs used together for a Day 2 operations check, beyond a basic Query and transform.

Why orchestrate this with Kestra

A one-off look at the Dremio UI's Jobs or Reflections tab proves the state for one moment. This flow keeps every audit in the execution history, turns the result into a typed output other flows can depend on, and gives you a branch to grow into real remediation, cancelling a stuck job, rebuilding a broken Reflection's dataset, or opening a ticket, without rewriting the audit itself.

Prerequisites

  • A self-hosted Dremio OSS coordinator, not Dremio Cloud, reachable from the Kestra Worker on its JDBC port (31010 by default) and its REST/web port (9047 by default). At least one Reflection configured so sys.reflections has rows.
  • For local testing: docker run -d --name dremio -p 9047:9047 -p 31010:31010 -p 32010:32010 dremio/dremio-oss:latest, then connect it to your Kestra worker's Docker network so dremio_jdbc_url and dremio_rest_base_url resolve: docker network connect YOUR_KESTRA_NETWORK dremio (run docker network ls to find the real network name). The flow reaches Dremio on its container-internal ports over that network; the published host ports are only for browsing the Dremio UI from your own machine, after completing Dremio's first-run admin setup at http://localhost:9047.
  • A Dremio Personal Access Token (generate it from Account Settings in the Dremio UI) for the REST cancel call.
  • A Slack incoming webhook for the at-risk and unreachable alerts.

Secrets

  • DREMIO_PASSWORD: password used by every Query task against Dremio's JDBC port.
  • DREMIO_PAT: Dremio Personal Access Token, sent as a Bearer token to the job-cancel REST endpoint.
  • SLACK_WEBHOOK_URL: Slack incoming webhook used for the at-risk alert, the unreachable alert, and the flow-failure alert.
  • OSS note: if your Kestra instance reads secrets from environment variables instead of a secrets backend, set them as base64, for example echo -n "<your-password>" | base64 exported as SECRET_DREMIO_PASSWORD, and likewise for SECRET_DREMIO_PAT and SECRET_SLACK_WEBHOOK_URL.

Inputs

Input Default Purpose
dremio_jdbc_url jdbc:dremio:direct=dremio:31010 JDBC URL of the coordinator
dremio_username dremio JDBC username
dremio_rest_base_url http://dremio:9047 REST base URL, used only to cancel a job
reflection_failure_threshold 1 num_failures at or above which a Reflection is flagged
stuck_job_after_minutes 30 Runtime past which a RUNNING job is flagged
auto_cancel_stuck_jobs false Allow the REST cancel call to run
dry_run true Must be false for a cancel to apply

Quick start

  1. Add the DREMIO_PASSWORD, DREMIO_PAT, and SLACK_WEBHOOK_URL secrets.
  2. Point dremio_jdbc_url and dremio_rest_base_url at your coordinator.
  3. Run the flow once and read status.
  4. Run it with auto_cancel_stuck_jobs: true and dry_run: false while a long-running job is active to confirm it gets cancelled and verified.
  5. Enable the dremio_health_gate_schedule trigger, which always runs in safe mode.

Outputs

  • status (STRING): the classified outcome, {{ outputs.classify_status.value }}, also exposed as the flow-level output {{ outputs.status }}.
  • {{ outputs.findings.values.items }}: a JSON array of every finding, each with kind, id, name, dataset, status, and detail.

Pitfalls

  • This blueprint has not been executed against a live Dremio coordinator; the exact set of sys.jobs status values and the availability of sys.reflections columns can vary by Dremio version. Verify both against your own deployment before enabling the schedule.
  • Querying sys.reflections and sys.jobs requires a user with sufficient privileges; a restricted user may see an empty or partial result that reads as falsely CLEAN.
  • A coordinator with no Reflections configured at all audits zero entries and always reads CLEAN for that half of the check; configure at least one Reflection to exercise the AT_RISK branch.
  • stuck_job_after_minutes is evaluated against submitted_epoch_millis, the time the job entered the system, not execution start; a job queued for a long time behind a busy engine before it starts running is not counted as stuck by this definition.
  • Cancelling a job through the REST API stops it but does not roll back any side effects of a CREATE TABLE AS or similar DDL/DML job that had already written partial results.

How to extend

  • Loop over a list of coordinators with a Loop task to audit a multi-coordinator Dremio deployment from one flow.
  • Parse considered_count, matched_count, and accelerated_count from sys.reflections to alert on a Reflection nobody's queries actually use, a cost-cleanup candidate, not just an outright failure.
  • Chain a downstream task after cancel_failed to escalate to the dataset owner instead of only failing the flow.
  • Add an OAuth2 or API-key secret type instead of a long-lived PAT once your Dremio deployment supports it.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.