Skip to main content

Execution monitoring reference

Requirements​

Apache Hop2.x, in Putki or Apache Hop. Tested with 2.18 and 2.19
PostgreSQL12 or later. The bundle runs 16
Docker Compose2.20 or later, for the bundled stack
Grafana10 or later, for your own Grafana. The bundle runs 13.1
jqFor install-logging.sh --environment-file

Bundle contents​

PathWhat it is
docker-compose-monitoring.ymlGrafana, the optional PostgreSQL, and the one-off schema job
docker-compose-monitoring.join.ymlOverlay that attaches to an existing Putki stack's network
docker-compose-monitoring.logs.ymlOverlay that forwards container logs to Loki, OpenSearch or Splunk. 2026.12 and later
alloy/Its Grafana Alloy configuration: docker.alloy, and one file per platform
.env.exampleTemplate for .env, the only file you edit
init-env.shWrites .env from .env.example and fills in the required settings: asks, or --generate makes up the passwords. Never changes a value already set
install-logging.shInstalls the Hop side into a project
hop/The logging pipelines and metadata the installer copies
sql/init-logging.sqlThe schema. Idempotent: creates and migrates, never deletes
grafana/datasources/datasources.ymlThe logging datasource, configured from environment variables
grafana/dashboards/The two dashboards and their provider definition
grafana/alerting/, grafana/plugins/Empty. The alert rules are written at start, into a copy
bin/putki-entrypoint.shStarts Grafana: writes the alert rules and contact points, sets up single sign-on
bin/putki-alerting.sh, bin/putki-sso.shUsed by the entrypoint; the same files the Putki stack's Grafana image runs
VERSIONThe bundle version, for support requests

.env settings​

SettingDefaultMeaning
GRAFANA_ADMIN_PASSWORDrequiredPassword of Grafana's admin user, applied on first start only
LOGGING_DB_PASSWORDrequiredPassword of the logging database user, which Hop writes with
GRAFANA_DB_PASSWORDrequiredPassword of Grafana's read-only database user
GRAFANA_DB_USERgrafana_readerGrafana's read-only database user, created by logging-db-init
COMPOSE_PROFILESlogging-dbRemove to use your own PostgreSQL instead of the bundled one
LOGGING_DB_HOSTlogging-dbHost of the logging database, as Grafana sees it
LOGGING_DB_PORT5432Port of the logging database, as Grafana sees it
LOGGING_DB_NAMEloggingDatabase name. Hop always writes to logging
LOGGING_DB_USERhop_loggingDatabase user Hop writes with; also creates the tables and Grafana's user
LOGGING_DB_SSLMODEdisablerequire or verify-full for a remote database
LOGGING_DB_PUBLISHED_PORT5432Host port of the bundled database, for Hop outside Docker
LOGGING_DB_BIND_ADDR127.0.0.1Interface the bundled database listens on
GRAFANA_PORT3000Host port of Grafana
GRAFANA_BIND_ADDR127.0.0.1Interface Grafana listens on
GRAFANA_ROOT_URLhttp://localhost:3000/Public URL, when behind a proxy
GRAFANA_SERVE_FROM_SUB_PATHfalsetrue when the public URL has a path
GRAFANA_COOKIE_SECUREfalsetrue when served over HTTPS
GRAFANA_ANONYMOUSfalsetrue for read-only access without login
GRAFANA_EXPLORE_ENABLEDfalsetrue to allow ad-hoc SQL in Explore
GRAFANA_THEMElightDefault theme for new users
MONITORING_NETWORKputki-monitoringName of the Docker network the stack creates
PUTKI_NETWORKputki-netWith the join overlay: the Putki stack's network
COMPOSE_PROJECT_NAMEputki-monitoringNames the containers and data volumes

Alerts​

See Get alerts in Slack or Google Chat.

SettingDefaultMeaning
PUTKI_ALERT_SLACK_WEBHOOK_URLSlack incoming webhook to send alerts to
PUTKI_ALERT_GOOGLE_CHAT_WEBHOOK_URLGoogle Chat space webhook to send alerts to
PUTKI_ALERT_SLOW_FACTOR3A run is much slower, or stuck, at this many times its usual time
PUTKI_ALERT_MIN_HISTORY5Successful runs of a name needed before its usual time counts
PUTKI_ALERT_MIN_SECONDS60Runs shorter than this are never slow
PUTKI_ALERT_STUCK_HOURS6A run without history is stuck after this many hours
PUTKI_ALERT_VOLUME_FACTOR10A run wrote an unusual number of rows at this many times more, or fewer, than usual. 2026.12 and later
PUTKI_ALERT_MIN_ROWS1000Below this many rows, for the run and its usual, the volume is never unusual. 2026.12 and later
PUTKI_ALERT_WINDOW_MINUTES10How recent the end of a run must be to alert
PUTKI_ALERT_REPEAT4hHow often an alert that stays active is sent again
PUTKI_ALERTStruefalse installs no alert rules

Log forwarding​

2026.12 and later, with docker-compose-monitoring.logs.yml. See Forward logs to Loki, OpenSearch or Splunk.

SettingDefaultMeaning
LOG_FORWARD_SINKrequiredloki, opensearch or splunk: which file in alloy/ Alloy loads
LOG_FORWARD_URLrequiredLoki push URL; for OpenSearch, host:port of the Data Prepper OTLP source; for Splunk, the HEC URL
LOG_FORWARD_USERBasic-auth user, Loki and OpenSearch. Empty for none
LOG_FORWARD_PASSWORDIts password or token; for Splunk, the HEC token
LOG_FORWARD_TENANTLoki: X-Scope-OrgID, for a multi-tenant Loki
LOG_FORWARD_INDEXSplunk: the index. Empty for the token's default
LOG_FORWARD_CONTAINERSallRegular expression on container names; only matching containers are forwarded
LOG_FORWARD_HOSTAlloy's container idThe host label on every line

Single sign-on​

See Sign in with Google, Microsoft or your SSO.

SettingMeaning
GRAFANA_GOOGLE_CLIENT_ID, _SECRETGoogle OAuth client. Callback <GRAFANA_ROOT_URL>login/google
GRAFANA_ENTRA_TENANT_ID, GRAFANA_ENTRA_CLIENT_ID, _SECRETMicrosoft Entra ID app registration. Callback <GRAFANA_ROOT_URL>login/azuread
GRAFANA_OIDC_ISSUER, GRAFANA_OIDC_CLIENT_ID, _SECRETAny OpenID Connect provider. Callback <GRAFANA_ROOT_URL>login/generic_oauth
GRAFANA_OIDC_NAMEText on the sign-in button. Default Single sign-on
GRAFANA_OIDC_AUTH_URL, _TOKEN_URL, _API_URLEndpoints, for providers whose paths differ from Keycloak's
GRAFANA_OIDC_INTERNAL_URLThe issuer as Grafana's server reaches it, when that differs from the browser's address
GRAFANA_SSO_ALLOWED_DOMAINSComma-separated e-mail domains allowed to sign in. Required with Google
GRAFANA_SSO_ALLOW_ANY_ACCOUNTtrue to use Google without allowed domains
GRAFANA_SSO_ADMINS, GRAFANA_SSO_EDITORSComma-separated e-mail addresses that get the Admin or Editor role
GRAFANA_SSO_DEFAULT_ROLERole of everyone else: Viewer (default) or None
GRAFANA_SSO_ROLE_ATTRIBUTE_PATHA JMESPath over the user's claims, instead of the lists
GRAFANA_SSO_ONLYtrue hides the username and password form

install-logging.sh options​

OptionMeaning
--project-home DIRRequired. The Hop project folder, containing project-config.json
--project-name NAMEWritten to every run and listed in the dashboard's Project filter
--environment-file FILEHop environment file to add the LOGGING_* variables to. Repeatable
--logging-host HOSTLOGGING_HOSTNAME. Default warehouse-db
--logging-port PORTLOGGING_PORT. Default 5432
--logging-user USERLOGGING_USERNAME. Default developer
--logging-password VALUELOGGING_PASSWORD, plain or in Hop's Encrypted … form
--no-promptNever ask; use the defaults for anything not given
--no-clobberKeep existing copies of the installed files
--dry-runReport what would change, change nothing

The defaults are the Putki compose stack's values. Run in a terminal, the installer asks for any LOGGING_* value you did not pass; otherwise it uses the default and says so. It never changes a variable that is already in the environment file, and re-running it reports files as unchanged.

It installs five files into the project:

FileRole
logging/pipeline-log.hplRuns at the start and end of every pipeline; records it and its transforms
logging/workflow-log.hplThe same for workflows and their actions
metadata/rdbms/logging.jsonThe logging database connection, built from the variables below
metadata/pipeline-log/pipeline-log.jsonTells Hop to run pipeline-log.hpl
metadata/workflow-log/workflow-log.jsonTells Hop to run workflow-log.hpl

Hop variables​

VariableMeaning
LOGGING_HOSTNAMEHost of the logging database, as Hop sees it
LOGGING_PORTPort of the logging database
LOGGING_USERNAMEDatabase user; needs SELECT, INSERT and UPDATE on both tables
LOGGING_PASSWORDIts password. The Encrypted … form is obfuscation, not encryption
PROJECT_NAMEInformational. The name written to each run is set in the pipelines at install time

All four LOGGING_* variables must be defined in the environment a project runs under. In the Putki stack (2026.12) the Hop containers get them from the stack's .env, so a project there needs none of them in its environment files.

Tables​

log_object: one row per workflow, pipeline, action and transform run.

ColumnTypeMeaning
channel_idvarchar(36)Hop's unique ID for the run. Primary key
parent_channel_idvarchar(36)The run that started this one; empty for a top-level run
namevarchar(255)Workflow, pipeline, action or transform name
statusvarchar(32)Hop's status text, such as Finished or Stopped (with errors)
start_date, end_datetimestamptzWhen the run started and ended
typetextWORKFLOW, PIPELINE, ACTION or TRANSFORM
rows_processedintegerFor a transform: the rows it wrote. Empty for pipelines, workflows and actions
time_processedintegerDuration in seconds
svgvarcharRendered image of the workflow or pipeline
projectvarchar(255)The --project-name it was installed with

log_detail: the log text of a run, for rows that produced any. channel_id references log_object and is deleted with it.

Dashboards​

A run is a pipeline or workflow execution that no other workflow started: parent_channel_id is empty and type is PIPELINE or WORKFLOW. Its outcome comes from Hop's status:

OutcomeStatus
SucceededFinished
FailedFinished (with errors), Stopped (with errors)
StoppedStopped
Runninganything else, such as Running or Waiting: not ended, or its end was never logged

Putki monitoring (putki-monitoring). Filters: Project, Runs (top-level runs, or every execution including the pipelines and workflows a run started), Name, Outcome, Log search and the time range.

PanelShows
Runs, Succeeded, Failed, RunningRuns started in the time range, by outcome
Success %Succeeded out of the runs that are no longer running
Rows written per dayPer pipeline execution, the most rows any one of its transforms wrote, summed per day. Counts each row once, not once per transform. Follows Project only
Run time per dayTotal duration of the runs that finished, by the day they started
Failed runs, All runsRuns with their outcome, status, duration and rows written, newest first, at most 1000. Click a name to open its log
Log searchExecutions whose log contains the Log search text, ignoring case, with the text around it. Empty while the search is empty

Execution log detail (putki-log-detail). One run: its outcome and duration, the executions it started, and its log.

Both are provisioned: Grafana restores the shipped version when it restarts. Save a copy under a new name to customise one.

Alert rules​

In the Putki folder, group Putki runs, evaluated every minute. Each alert carries the labels project and name and links to the dashboard.

RuleFires for a run that
Run failedEnded Failed in the last PUTKI_ALERT_WINDOW_MINUTES
Run much slower than usualEnded in that window, ran at least PUTKI_ALERT_MIN_SECONDS, and took more than PUTKI_ALERT_SLOW_FACTOR times the median of its previous 10 successful runs (with at least PUTKI_ALERT_MIN_HISTORY of them)
Run still running long after its usual timeStarted in the last 7 days, has not ended, and has been running more than PUTKI_ALERT_SLOW_FACTOR times its usual time, or PUTKI_ALERT_STUCK_HOURS without history
Run wrote no rowsEnded successfully in that window having written 0 rows, while the median of its previous 10 successful runs (at least PUTKI_ALERT_MIN_HISTORY) is above 0. 2026.12 and later
Run wrote an unusual number of rowsEnded successfully in that window having written more than PUTKI_ALERT_VOLUME_FACTOR times that median, or less than that median divided by it; not when both are below PUTKI_ALERT_MIN_ROWS. 2026.12 and later
Login refused during a runEnded in that window, with or without errors, and the log text of the run or of anything it ran contains a refused-login message (list in bin/putki-alerting.sh, AUTH_MESSAGES). Indicative: matched on text. 2026.12 and later

Rows written by a pipeline are the largest rows_processed of its transforms (Hop's lines written), as on Rows written per day. A workflow's are the sum over the pipelines below it, followed through parent_channel_id across actions and child workflows. A run whose pipelines recorded no transforms has no row count, and the two row rules leave it out.