Vigilon Python SDK
Official Python SDK for Vigilon.
Vigilon is application monitoring for SaaS applications, based on OpenTelemetry. Out of the box it provides RESTful service and endpoint health, error monitoring and alerting, end-to-end tracing, and background job monitoring.
The SDK sets up standard OpenTelemetry instrumentation for your app and exports it to Vigilon over OTLP, with no proprietary agent. One register() call, or the zero-code opentelemetry-instrument launcher, instruments FastAPI, Flask and Django, plus common HTTP and database clients.
Install
pip install vigilon
Requires Python 3.10 or later.
Quick start
Create an API key in the Vigilon dashboard under your project's Settings page, API Keys tab.
Then call register() as the first statement of your entrypoint, before application modules import the frameworks being instrumented:
import vigilon
vigilon.register(
api_key="your-api-key",
service_name="your-service-name",
environment="production",
service_version="1.2.3", # optional, recommended for deploy tracking
)
from app import create_app # import your app AFTER register()
app = create_app()
Optional environment variables:
VIGILON_OTEL_ENDPOINT— override the OTLP HTTP base endpoint (traces go to<endpoint>/v1/traces); useful for local collectors and tests.VIGILON_EXCLUDED_URLS— extra excluded-URL regexes, comma-separated (see below).
Full product documentation is at vigilon.io/docs.
Zero-code bootstrap
If you cannot (or would rather not) touch the entrypoint, launch the app under opentelemetry-instrument — the SDK registers itself through OpenTelemetry's distro/configurator hooks, driven entirely by environment variables:
VIGILON_API_KEY=your-api-key \
VIGILON_SERVICE_NAME=your-service-name \
VIGILON_ENVIRONMENT=production \
VIGILON_SERVICE_VERSION=1.2.3 \
opentelemetry-instrument python app.py
| Variable | Meaning |
|---|---|
VIGILON_API_KEY |
Required. Your Vigilon API key. |
VIGILON_SERVICE_NAME |
Required. Service name shown in Vigilon. |
VIGILON_ENVIRONMENT |
Required. Deployment environment (production, staging, …). |
VIGILON_SERVICE_VERSION |
Recommended — enables deploy tracking; the SDK warns when missing. |
VIGILON_OTEL_ENDPOINT |
Optional OTLP endpoint override. |
VIGILON_EXCLUDED_URLS |
Optional extra excluded-URL regexes, comma-separated. |
Notes:
- Pre-fork servers (gunicorn, uWSGI, Celery prefork) must not use this path — the SDK would start before the fork and lose its exporter thread in the workers. Use the per-worker
register()recipes below instead. - Django: export
DJANGO_SETTINGS_MODULEin the environment (not insidemanage.py) — it must be set beforeopentelemetry-instrumentinitializes, or Django is deliberately left uninstrumented. - If another OpenTelemetry distro package is installed in the same environment, pin ours explicitly with
OTEL_PYTHON_DISTRO=vigilon OTEL_PYTHON_CONFIGURATOR=vigilon. - A later in-process
register()call is safely ignored (one warning), so code that also runs outsideopentelemetry-instrumentkeeps working.
Instrumented libraries
register() (and the zero-code path) instruments whichever of these are installed — no configuration needed:
- Web frameworks: FastAPI, Flask, Django (Django only when
DJANGO_SETTINGS_MODULEis set — instrumenting without resolvable settings would break apps that configure Django later) - HTTP clients: requests, httpx, urllib3, aiohttp
- PostgreSQL: psycopg, psycopg2
- MySQL: mysql-connector-python, PyMySQL, mysqlclient
- Other datastores: Redis, PyMongo, SQLAlchemy (any driver, including async engines)
- AWS: Lambda flush handling (see below)
MySQL through SQLAlchemy is traced at both layers (an engine span with the driver span nested inside); async MySQL drivers (aiomysql, asyncmy) are traced via the SQLAlchemy async engine only.
App objects created before register()
FastAPI and Flask are instrumented by swapping the framework's app class, so an app object built before register() ran (usually an import-order problem you can't fix, e.g. inside a framework CLI) is left untouched. The escape hatch is the per-app instrumentor — pass your excluded URLs, since the merged defaults don't apply on this path:
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
FastAPIInstrumentor.instrument_app(app, excluded_urls="/health$,/ready$,/favicon\\.ico$")
(Flask: FlaskInstrumentor().instrument_app(app, excluded_urls=...).)
Pre-fork servers (gunicorn, uWSGI, Celery)
The SDK's exporter runs a background thread that does not survive fork(). Call register() once per worker, in the worker-startup hook — not at master/module import time:
# gunicorn.conf.py
def post_fork(server, worker):
import vigilon
vigilon.register(api_key=..., service_name=..., environment=...)
# uWSGI (run with --enable-threads)
from uwsgidecorators import postfork
@postfork
def start_vigilon():
import vigilon
vigilon.register(api_key=..., service_name=..., environment=...)
# Celery worker
from celery.signals import worker_process_init
@worker_process_init.connect
def start_vigilon(**kwargs):
import vigilon
vigilon.register(api_key=..., service_name=..., environment=...)
Excluded URLs
Health checks (/health, /ready, /favicon.ico) are excluded from instrumentation by default. Add your own patterns for uncovered health endpoints or long-lived SSE routes that would otherwise dirty service-level metrics:
vigilon.register(
...,
excluded_urls=["/internal/health$", "/events/stream$"],
)
Patterns are regexes matched against the full request URL and are merged with the defaults. Excluded routes produce no server span at all — they disappear from tracing and from request metrics, which is exactly what you want for SSE.
Recording errors
Unhandled exceptions are recorded automatically. For errors your code catches and converts into an error response itself — invisible to instrumentation — call record_error:
from vigilon import record_error
@app.get("/data")
async def get_data():
try:
return await load_data()
except Exception as error:
record_error(error)
return JSONResponse({"message": "failed"}, status_code=500)
If there is no active span, record_error is a no-op.
Background jobs
Wrap one execution of a background job — a cron tick, a queue processor, an interval loop — in with_job_monitor to report it as a Job Run. Each run starts its own trace, so database queries and outgoing requests made inside the job are attached to that run instead of being orphaned:
from vigilon import with_job_monitor
@with_job_monitor(name="sync-users", schedule="0 3 * * *")
async def sync_users(): ...
# Or as a context manager for inline blocks:
with with_job_monitor(name="refresh-cache"):
refresh_cache()
name is a required, stable identifier — never interpolate per-item values (sync-user-42 fragments one job into unbounded identities). schedule is an optional cron expression enabling last-run and stale-job detection. Sync and async functions are both supported; errors are recorded on the run and re-raised.
with_job_monitor must run after register() has started the SDK. If it runs earlier, the job itself still executes normally, but the run is not reported.
AWS Lambda
Vigilon detects the Lambda runtime via AWS_LAMBDA_FUNCTION_NAME and adds the AWS Lambda instrumentation automatically, which flushes traces at the end of each invocation. No extra configuration is needed.
Support
- Bugs and feature requests: GitHub Issues
- Security vulnerabilities: report them privately to security@vigilon.io instead of opening a public issue.
Contributing
Build, test, and release instructions are in CONTRIBUTING.md.
License
Release files for vigilon 0.1.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| vigilon-0.1.6.tar.gz | 21.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vigilon-0.1.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 37.1 kB
Release files / vigilon-0.1.6.tar.gz
| Download URL | vigilon-0.1.6.tar.gz |
|---|---|
| Size | 21.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0d612e79a59890672ca02bb15c382794d3834b0c8fc4bb074b0ec209d74eb5e2
|
|
BLAKE2b-256 checksum How to use checksums |
76087a98d17f388ab19ca2581360e8f952ab405cfb898324e81cfd0f3f1fedfc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / vigilon-0.1.6-py3-none-any.whl
| Download URL | vigilon-0.1.6-py3-none-any.whl |
|---|---|
| Size | 16.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f4f0a8daccc7da37c2644af693cc0e4dba9cb376cfddbd6410735ddca08af022
|
|
BLAKE2b-256 checksum How to use checksums |
2965a56de1851840ebdc3ef0c8554b9a38f11bbdc01442a2b867e79cea4aa1ba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|