Skip to content

Quickstart

This guide walks you through creating your first Watchpost application and running a simple check. The guide also explains how you will integrate your Watchpost application with Checkmk.

This guide uses the uv package manager for commands and examples. You can use pip or another tool if you prefer. If you need to install uv, see the uv installation guide.

Create a Watchpost application

  1. Initialize a new Python project:

    uv init --app --package ./my-watchpost
    

    You can omit --package if you prefer a single-file project. Using a package layout is recommended because it keeps your application organized as it grows.

  2. Add Watchpost to your project:

    cd my-watchpost
    uv add 'watchpost[cli]'
    

    We recommend installing Watchpost with the cli extra. It adds a watchpost command that makes it easy to list and run checks during development.

  3. Edit my-watchpost/src/my_watchpost/__init__.py to create a minimal application:

    from watchpost import EnvironmentRegistry, Watchpost
    
    ENVIRONMENTS = EnvironmentRegistry()
    PRODUCTION = ENVIRONMENTS.new("production")
    
    app = Watchpost(
        checks=[],
        execution_environment=PRODUCTION,
    )
    
  4. Verify that the app starts and contains no checks yet

    $ uv run watchpost --app my_watchpost:app list-checks  # (1)
    $ uv run watchpost --app my_watchpost:app run-checks
                Check Execution Results
    ┏━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━┓
    ┃ State ┃ Environment ┃ Service Name ┃ Summary ┃
    ┡━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━┩
    └───────┴─────────────┴──────────────┴─────────┘
    
    1. There is no output because the application does not define any checks yet.

Now let’s add a first check that verifies whether https://www.example.com is reachable and returns a 200 OK status code.

  1. Add a HTTP client dependency.

    We use httpx2 and its AsyncClient to demonstrate async checks, but you can use any HTTP client (async or sync) for your own checks.

    uv add httpx2
    
  2. Edit my-watchpost/src/my_watchpost/__init__.py to:

    1. Add a new datasource that provides the http client.
    2. Add a check that verifies the status code of https://www.example.com.
    3. Register the check with the application.
    4. Register the datasource with the application.
    from contextlib import asynccontextmanager
    
    import httpx2
    
    from watchpost import check, crit, ok, Datasource, EnvironmentRegistry, Watchpost
    
    ENVIRONMENTS = EnvironmentRegistry()
    PRODUCTION = ENVIRONMENTS.new("production")
    
    
    class Httpx2ClientFactory(Datasource):  # (1)
        scheduling_strategies = ()
    
        @asynccontextmanager
        async def client(self):
            async with httpx2.AsyncClient(timeout=10.0) as client:
                yield client
    
    
    @check(  # (2)
        name="example.com HTTP status",
        service_labels={},
        environments=[PRODUCTION],
        cache_for="5m",
    )
    async def example_com_http_status(
        client_factory: Httpx2ClientFactory,  # (3)
    ):
        async with client_factory.client() as client:
            response = await client.get("https://www.example.com")
    
        if response.status_code != 200:
            return crit(  # (4)
                "example.com returned an error",
                details=(
                    f"Expected status: 200\n"
                    f"Actual status: {response.status_code}\n"
                    f"Response: {response.text}"
                ),
            )
    
        return ok("example.com is up")  # (5)
    
    
    app = Watchpost(
        checks=[
            example_com_http_status,  # (6)
        ],
        execution_environment=PRODUCTION,
    )
    app.register_datasource(Httpx2ClientFactory)  # (7)
    
    1. Define a datasource that constructs httpx2 clients. You may wonder why this is a separate class instead of creating the client directly inside the check. In real projects your datasources often encapsulate more context (for example, which environment the client can run in) or wrap an API with domain-specific helpers. Keeping that logic in a datasource makes your checks simpler and easier to test.

    2. Use the @check decorator to define your check:

    3. A human-friendly name that will appear as the service name in Checkmk.

    4. Optional service labels to attach to the Checkmk service.
    5. The environments this check targets.
    6. A cache duration that controls how long a result is kept before the check runs again.

    7. To use a datasource in a check, add a parameter annotated with the datasource type. Watchpost injects the instance automatically when the check runs.

    8. If the check fails, return crit(...). The details will be shown in the Checkmk service to help troubleshooting.
    9. If everything is fine, return ok(...).
    10. Register the check with the application.
    11. Register the datasource with the application.
  3. List and run the check

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

Checkmk integration

Continue with the Checkmk integration guide to install the plugin, configure HTTP collection, create piggyback target hosts, and discover services. Use my_watchpost:app wherever that guide uses integration_example:app. This application's default target host is example.com-http-status-production; verify it with:

uv run watchpost --app my_watchpost:app get-check-hostnames

Before running the application continuously, review the deployment guide for polling, caching, worker limits, HTTP access, and resource shutdown.