Install · Django · Flask · FastAPI · Errors · Logs, metrics, traces · Crons · Flags · Privacy
naijacloud-argus
The official Python SDK for Argus, Naijacloud's monitoring. One package sends errors, logs, metrics, traces, cron check-ins and feature-flag checks, with one key: your app's DSN.
It has no dependencies, supports Python 3.9 and newer, implements the Argus SDK
contract argus.sdk/1, and works for apps hosted anywhere, not only on
Naijacloud.
Already using Sentry's library? Keep it. Argus accepts it: change the dsn
line and you're done. Switch to this SDK when you want logs, metrics, cron
check-ins and flags through the same setup.
Install
pip install naijacloud-argus
Copy the DSN (your app's key) from the source in Argus. It looks like
https://<key>@argus-in.naijacloud.com/<number>.
import naijacloud_argus as argus
argus.init(dsn="https://<key>@argus-in.naijacloud.com/<id>")
Call it once, as early as you can: at the top of your entry file, settings.py,
wsgi.py or asgi.py. That's it. You get:
- Uncaught exceptions, on the main thread and in other threads. Python still prints the traceback and exits the way it would without Argus.
- Logging records as breadcrumbs on the next error. Your logging setup is
untouched: no handler is added, so a later
logging.basicConfig()still works. - Outgoing HTTP made through
urllib,requestsorurllib3as breadcrumbs, and inside a span, as child spans with atraceparentheader. - A final flush at exit, so a short script's data is not lost.
init() reads ARGUS_DSN, ARGUS_RELEASE and ARGUS_ENVIRONMENT, falling
back to SENTRY_DSN, SENTRY_RELEASE and SENTRY_ENVIRONMENT. Without a DSN
it does nothing. Apps hosted on Naijacloud get these variables set when the
Argus tab is on, so there argus.init() with no arguments is enough.
Web frameworks catch your errors themselves, so add their integration too.
Django
# settings.py
import naijacloud_argus as argus
argus.init()
MIDDLEWARE = [
"naijacloud_argus.integrations.django.ArgusMiddleware", # first
# ...
]
Every request is traced and named after its URL pattern
(GET /orders/<int:pk>/). View errors are reported before Django turns them
into a 500 page. It works under WSGI and ASGI, with sync and async views.
Flask
import naijacloud_argus as argus
from naijacloud_argus.integrations.flask import init_app
argus.init()
app = init_app(Flask(__name__))
Requests are traced and named after the URL rule. Unhandled view errors are
reported; errors your own @app.errorhandler handles are not.
FastAPI and Starlette
import naijacloud_argus as argus
from naijacloud_argus.integrations.fastapi import instrument
argus.init()
app = instrument(FastAPI())
Requests are traced and named after the route (GET /items/{item_id}), with
http.route set. Unhandled errors are reported; HTTPExceptions are answers,
not errors, and are not.
Any other WSGI or ASGI app (Pyramid, Bottle, Falcon, Quart, Litestar):
from naijacloud_argus.integrations.wsgi import ArgusWSGIMiddleware
from naijacloud_argus.integrations.asgi import ArgusASGIMiddleware
app = ArgusWSGIMiddleware(app) # or ArgusASGIMiddleware(app)
In every integration a traceparent header from the caller continues its
trace, and each request gets its own scope: set_user() inside one request
never leaks into another, on threads or on an event loop. None of them imports
its framework until you use it.
Errors
import naijacloud_argus as argus
try:
charge_card(order)
except PaystackError as err:
argus.capture_exception(err, tags={"provider": "paystack"}, extra={"order_id": order.id})
argus.capture_message("Webhook signature mismatch", "warning")
argus.set_user({"id": user.id})
argus.set_tag("region", "af-west")
argus.add_breadcrumb(category="auth", message="signed in")
- The handled exception:
capture_exception()with no argument, inside anexceptblock, sends the one being handled. - Causes:
raise … from …and the implicit context are sent too, with stack frames and the source lines around each. - Duplicates: the same exception object is sent once, however many handlers see it.
before_send(event, hint)lets you change an event, or returnNoneto drop it.hint["exc_info"]is the original exception.- Your own scope:
with argus.new_scope():keeps a user or tags you set inside it from leaking out, for background jobs and queue workers.
Logs, metrics and traces
import naijacloud_argus as argus
argus.log.info("order placed", order_id="ord_81", total=18500)
argus.log.error("paystack timed out", attempt=3)
argus.metrics.count("orders.placed", 1, {"method": "card"})
argus.metrics.gauge("queue.depth", len(jobs))
argus.metrics.distribution("checkout.ms", elapsed, unit="ms")
with argus.trace("charge card", {"provider": "paystack"}) as span:
span.set_attribute("amount", 18500)
paystack.charge(order)
@argus.trace("nightly report") # or bare @argus.trace, named after the function
async def build_report(): ...
- Logs are sent in batches every 5 seconds. A log written inside a request
or span carries its trace id. Attribute names that aren't Python identifiers
go in a dict:
argus.log.info("slow", {"http.route": "/pay"}). - Ship your
loggingrecords as Argus logs withinit(capture_logs=True)(INFO and up), or a level:capture_logs=logging.WARNING. For some loggers only, addnaijacloud_argus.ArgusHandler()to them instead. - Metrics are added up in your process and sent every 10 seconds.
- Spans join the request or span they run in, and are marked failed when
the block raises (the exception still propagates).
argus.start_span()gives you one to end yourself; passparent=atraceparentstring to continue a trace from a queue message, andargus.get_traceparent()to send one on. - Sample traces with
traces_sample_rate(0–1, default 1).
Cron check-ins
Create a cron monitor in Argus first, then report runs by its slug:
import naijacloud_argus as argus
@argus.cron.monitor("nightly-invoices")
def send_invoices(): ...
# or as a block:
with argus.cron.monitor("nightly-invoices"):
send_invoices()
# or by hand:
argus.cron.check_in("nightly-invoices", "start")
argus.cron.check_in("nightly-invoices", "ok") # or "error", or an exit code
monitor reports the start, then success or failure, and re-raises your
job's error. A sys.exit(code) inside it reports that exit code. Async
functions work too.
Feature flags
import naijacloud_argus as argus
if argus.flags.is_on("new-checkout", user.id):
...
theme = argus.flags.variant("theme", user.id, "light")
# in async code:
if await argus.flags.is_on_async("new-checkout", user.id):
...
- Caching: answers are cached for 30 seconds per user.
- Fallback: if Argus can't be reached within
flags_timeout(2 seconds), or the flag doesn't exist, you get the default you passed. - Blocking:
is_onandvariantwait for Argus on a cache miss. In async code useis_on_asyncandvariant_async, which don't block the event loop.
Privacy
On by default:
- The values of keys such as
password,token,secret,authorization,cookie,bvnandcardare replaced with[Filtered], at any depth. - Card numbers, bearer tokens, JWTs and
password=…pairs are filtered inside strings, including exception messages and log lines. - Query strings are removed from URLs in breadcrumbs, requests and spans.
- Request bodies and cookies are never sent.
- The user's IP address is not sent unless you set
send_default_pii=True.
Argus filters again on arrival.
Options
| Option | Default | |
|---|---|---|
dsn |
ARGUS_DSN, then SENTRY_DSN |
Without one, nothing is sent. dsn="" turns the SDK off |
release |
ARGUS_RELEASE, then SENTRY_RELEASE |
Your app's version, like 1.4.2 or a git commit |
environment |
ARGUS_ENVIRONMENT, then SENTRY_ENVIRONMENT, else production |
|
service_name |
ARGUS_SERVICE_NAME, then OTEL_SERVICE_NAME, else app |
Shown on logs, metrics and traces |
server_name |
the host name | |
sample_rate |
1 |
Share of errors sent |
traces_sample_rate |
1 |
Share of traces sent |
send_default_pii |
False |
Send the user's IP address |
max_breadcrumbs |
100 |
|
before_send / before_breadcrumb |
(event, hint): change or drop an event or crumb |
|
capture_logs |
False |
Also send logging records as logs: True (INFO+) or a level |
breadcrumb_level |
logging.INFO |
logging records from this level become breadcrumbs |
default_integrations |
True |
False installs no hooks (excepthooks, logging, http.client, atexit) |
flags_timeout |
2.0 |
Seconds a flag evaluation may wait |
shutdown_timeout |
2.0 |
Seconds the exit flush may take |
debug |
False |
Print what the SDK does to stderr (or ARGUS_DEBUG=1) |
enabled |
True |
Turn the SDK off without removing it |
argus.flush(timeout=2.0) sends what's queued and returns whether it all went
out; argus.close() flushes and stops. Long-running servers need neither.
How it sends
Nothing is sent on your thread. Each endpoint has its own queue (at most 100
requests and 1 MB) and its own background thread, using only the standard
library's urllib. Network errors and 5xx are retried with backoff, a 429
waits for Retry-After, and a refused key stops that endpoint until restart.
SDK code never raises into yours.
It is safe under fork() (gunicorn --preload, multiprocessing): a child
process rebuilds its queues on first use. Proxies come from HTTPS_PROXY,
HTTP_PROXY and NO_PROXY; system proxy settings are not read, because on
macOS that lookup crashes a forked child.
Not in this version
These are planned, and not done yet:
- automatic spans for database clients (
psycopg, SQLAlchemy, the Django ORM),httpxandaiohttp(onlyhttp.client-based requests are traced); - Celery and RQ task tracing (use
cron.monitorortracein the task); - reporting
logging.error()calls as error events (they are breadcrumbs, and withcapture_logs, logs); - local variables in stack frames.
License
MIT
Metadata
Release files for naijacloud-argus 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| naijacloud_argus-0.1.0.tar.gz | 69.7 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| naijacloud_argus-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 120.1 kB
Release files / naijacloud_argus-0.1.0.tar.gz
| Download URL | naijacloud_argus-0.1.0.tar.gz |
|---|---|
| Size | 69.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2842321c0cd93fa78f3da2b1e421e6fde14a962635467f4e8157be296bce7ef9
|
|
BLAKE2b-256 checksum How to use checksums |
b6ebbf0556ca58e157a4724cec4e69da8eb049a7ff96961bd9cecd532b85cbec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Oct 26, 2026.
Transparency logRelease files / naijacloud_argus-0.1.0-py3-none-any.whl
| Download URL | naijacloud_argus-0.1.0-py3-none-any.whl |
|---|---|
| Size | 50.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f6ac43c2b8b617f2221b081c912338cc78ff6df398368496276a65b100b6a439
|
|
BLAKE2b-256 checksum How to use checksums |
7a69655223486ffee2a0b8a2057e24f309c63884cac9191a560fe5dc24f5741d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Oct 26, 2026.
Transparency logSecurity for naijacloud-argus 0.1.0
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for naijacloud_argus-0.1.0.tar.gz
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 Oct 26, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.