Skip to content

Architecture

The Synthetic Exporter is built for enterprise reliability and addresses the common pitfalls of running headless browsers in containerized environments.

Background Worker Pattern

A common issue with Prometheus exporters that interact with headless browsers is scrape timeouts. If the exporter only launches the browser when Prometheus requests /metrics, a slow website can easily cause the scrape to exceed Prometheus's configured timeout (typically 10-15s), resulting in dropped metrics.

To solve this, the Synthetic Exporter utilizes a background worker pattern:

  1. Startup: playwright.Install() runs once to ensure browser binaries are present.
  2. Infinite Loop: A Go time.Ticker triggers the checks (HTTP endpoints + UI Journey) on a fixed interval (e.g., every 60 seconds).
  3. Instant Scrape: When Prometheus scrapes /metrics, the HTTP server instantly returns the latest cached metric values. No browser is launched during the scrape, ensuring sub-millisecond response times.

Docker & Process Management

Running headless Chromium inside Docker is notoriously difficult due to zombie processes. Every time Chromium launches a new tab or context, it spawns child processes. If the main process exits without cleaning them up, they become "zombies" and consume PID slots until the container crashes.

The Dockerfile employs best practices to mitigate this:

  1. dumb-init (PID 1): We use dumb-init as the container's entrypoint. It acts as a lightweight init system that aggressively reaps orphaned zombie processes and correctly forwards Linux signals (SIGTERM, SIGINT) to the Go binary.
  2. Multi-Stage Build: The Go binary is compiled statically (CGO_ENABLED=0) in a lightweight Alpine stage, keeping the final image lean.
  3. Official Base Image: The runtime image uses mcr.microsoft.com/playwright, ensuring all necessary system libraries (fonts, libnss3, etc.) are pre-installed.
  4. Least Privilege: The application executes under a non-root user (uid 10001), enhancing security.

Resource Limits & Memory Management

Headless browsers (Chromium/Playwright) consume significant memory and CPU, especially when opening modern JavaScript-heavy websites. Because the background worker executes UI scenarios periodically, it is critical to configure appropriate resource limits to prevent Out Of Memory (OOM) kills.

Best Practices for CPU/RAM Limits

  • Memory (RAM): Chromium can easily consume hundreds of megabytes of RAM per page. We recommend a minimum limit of 512Mi to 1Gi for the exporter container, depending on the complexity of your scenarios.
  • CPU: Running headless browser checks can be CPU intensive. Assigning at least 0.5 to 1 full CPU core is recommended to prevent interaction timeouts during scenarios.

Example Kubernetes Resources:

yaml
resources:
  requests:
    memory: "512Mi"
    cpu: "500m"
  limits:
    memory: "1Gi"
    cpu: "1000m"

If your container restarts unexpectedly or you see Exit Code 137, it is almost certainly being OOM-killed due to insufficient memory limits.

Released under the MIT License.