Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Watchpost – code-driven monitoring checks for Checkmk

Watchpost is a small framework for writing monitoring checks as Python code and integrating them with Checkmk. It helps you configure checks through a simple function decorator, handles running checks across and against multiple environments, and supports you in gathering data from external systems.

Example

Install Watchpost in your project:

pip install 'watchpost[cli]'

You can now write a basic Watchpost application like this:

import urllib.error
import urllib.request

from watchpost import CheckResult, EnvironmentRegistry, Watchpost, check, crit, ok

ENVIRONMENTS = EnvironmentRegistry()
PRODUCTION = ENVIRONMENTS.new("production")


@check(  # (1)
    name="example.com HTTP status",
    service_labels={},
    environments=[PRODUCTION],
    cache_for="5m",
)
def example_com_http_status() -> CheckResult:
    try:
        with urllib.request.urlopen("https://www.example.com", timeout=10) as response:
            status_code = response.status
    except urllib.error.HTTPError as e:
        status_code = e.code

    if status_code != 200:
        return crit(  # (2)
            "example.com returned an error",
            details=f"Expected status: 200\nActual status: {status_code}\n",
        )

    return ok("example.com is up")  # (3)


app = Watchpost(
    checks=[
        example_com_http_status,  # (4)
    ],
    execution_environment=PRODUCTION,
)
  1. Use the @check decorator to define your check:

    • A human-friendly name that will appear as the service name in Checkmk.
    • Optional service labels to attach to the Checkmk service.
    • The environments this check targets.
    • A cache duration that controls how long a result is kept before the check runs again.
  2. If the check fails, return crit(...). The details will be shown in the Checkmk service to help troubleshooting.

  3. If everything is fine, return ok(...).

  4. Register the check with the application.

Assuming this is saved as example.py, you can run it locally as such using the watchpost CLI:

$ watchpost --app example:app run-checks
                       Check Execution Results
┏━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓
┃ State ┃ Environment ┃ Service Name            ┃ Summary           ┃
┡━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩
│  OK   │ production  │ example.com HTTP status │ example.com is up │
└───────┴─────────────┴─────────────────────────┴───────────────────┘

The Checkmk integration makes use of HTTP to retrieve the check results from the Watchpost application. To support this, Watchpost is a valid ASGI web application which you can run with any ASGI server, for example uvicorn:

$ pip install uvicorn
$ uvicorn example:app
INFO:     Started server process [12345]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

Capabilities at a glance

  • Checks and results
    • @check decorator, multiple result modes (single, multiple, yielded, builder)
    • Result helpers: ok, warn, crit, unknown, metrics, thresholds
  • Environments and scheduling
    • Target vs. execution environments, pluggable scheduling strategies with validation
  • Datasources
    • Simple base class (Datasource) and factory pattern to share configuration
  • Execution and streaming
    • Key‑aware executor, error aggregation, Checkmk output generation
  • Caching
    • In‑memory, disk, and optional Redis backends; memoization helper
  • ASGI / HTTP
    • Starlette app; routes: /, /healthcheck, /executor/statistics, /executor/errored

Execution and timeouts

HTTP polls share one outstanding execution per check and target environment, including checks with cache_for=None. A completed result remains available until pickup; the following poll can start a fresh execution. Caching controls how long picked-up results are reused, independently of overlap prevention. For a fixed application, pending work is bounded by its check/environment pairs. Direct users of CheckExecutor.submit(resubmit=True) explicitly opt into overlap. The flag is not needed to run a check again after collecting its previous result. For example, an uncached check that takes 30 seconds and is polled every 10 seconds runs once during that interval. After a poll collects its result, the following poll starts a new execution; intervening polls do not queue extra jobs.

Checks must configure timeouts on external I/O. Watchpost does not impose an implicit execution deadline or terminate blocked Python threads. Async checks can use asyncio.timeout() to bound a whole operation; synchronous checks should use their client's connect/read timeouts. A stuck check occupies its own pending slot instead of accumulating a new job on every poll.

ASGI shutdown cancels pending async checks and queued thread jobs, then releases Watchpost's internally created executor. Running synchronous checks must finish using their own I/O timeouts. Executors supplied to Watchpost(executor=...) are caller-owned and must be closed by the caller. For standalone use, call app.shutdown() after finishing. Direct executor users can drain work with shutdown(wait=True) or request cancellation with cancel_futures=True.

Generated checks use their qualified function name and service name as the stable execution/cache identity. If a factory generates checks sharing both, assign distinct @check(id="...") values per target environment. Duplicate identities fail configuration validation. Identity changes invalidate cached results. The versioned identity keys intentionally ignore older name-only cache entries, causing a fresh execution after upgrading.

Each resolved (hostname, service_name) must be unique across all collected Watchpost results. The Checkmk plugin discovers one service for a duplicate identity and reports UNKNOWN with the conflicting results, instead of selecting one result and hiding the others. Use distinct names, result suffixes, or hosts.

Datasource construction failures follow the same result policy as failures in check functions: DatasourceUnavailable produces UNKNOWN (or an available prior cached result with failure details), while other exceptions produce CRIT. Error handlers still expand those results, and unrelated checks continue running.

The synthetic Watchpost: executed checks service reports the number of check/environment pairs eligible to run in the current poll (SCHEDULE). This includes cached results and checks already running; it excludes SKIP and DONT_SCHEDULE. It counts pairs, not emitted services or completed invocations.

Documentation

Start with the quickstart, follow the Checkmk integration guide, and read the deployment and runtime guide for polling, caching, worker behavior, timeouts, and shutdown.

Maintainers can follow RELEASING.md to prepare RCs and final releases, publish matching Checkmk images, and handle interrupted releases.

License

Watchpost is licensed under the Apache License, Version 2.0, (see LICENSE or https://www.apache.org/licenses/LICENSE-2.0).

Watchpost internally makes use of various open-source projects. You can find a full list of these projects and their licenses in THIRD_PARTY_LICENSES.md.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Watchpost by you, as defined in the Apache-2.0 license, shall be licensed under the Apache License, Version 2.0, without any additional terms or conditions.

We make use of Lefthook for pre-commit and pre-push hooks that verify your code is valid. To set up the hooks, run uv run lefthook install.

Affiliation

This project has no official affiliation with Checkmk GmbH or any of its affiliates. "Checkmk" is a trademark of Checkmk GmbH.

History

This project is a fork of takkt-ag/watchpost.

Metadata

Release files for watchpost 0.2.0rc1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for watchpost 0.2.0rc1
File Size Uploaded
watchpost-0.2.0rc1.tar.gz 61.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for watchpost 0.2.0rc1
File Interpreter ABI Platform
watchpost-0.2.0rc1-py3-none-any.whl Python 3 none any Details

Total release size: 141.4 kB

Release files / watchpost-0.2.0rc1.tar.gz

Download URL watchpost-0.2.0rc1.tar.gz
Size 61.8 kB
Tags Source
SHA-256 checksum
How to use checksums
765414e53f2bce474b06af3831c7c935856a779bc9c1280a82ad0a8e78f1d635
BLAKE2b-256 checksum
How to use checksums
8c61c5a3f376dcb972dd478a6dd7133808f3433bb91d73ed5c41e7e2dbc7046d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.

Transparency log

Release files / watchpost-0.2.0rc1-py3-none-any.whl

Download URL watchpost-0.2.0rc1-py3-none-any.whl
Size 79.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ca0d14016124f0bd8d935c0b0f8912f7d1f166835537243cba90657d87d1d0a0
BLAKE2b-256 checksum
How to use checksums
b87d02a46e930d4b7c97f53a2d2349c49c111c7fabe243bde8776ce3307ef8ef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0rc1 This release

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page