Skip to main content

Naijacloud Argus, Python SDK

pypi python dependencies license

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, requests or urllib3 as breadcrumbs, and inside a span, as child spans with a traceparent header.
  • 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 an except block, 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 return None to 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 logging records as Argus logs with init(capture_logs=True) (INFO and up), or a level: capture_logs=logging.WARNING. For some loggers only, add naijacloud_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; pass parent= a traceparent string to continue a trace from a queue message, and argus.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_on and variant wait for Argus on a cache miss. In async code use is_on_async and variant_async, which don't block the event loop.

Privacy

On by default:

  • The values of keys such as password, token, secret, authorization, cookie, bvn and card are 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), httpx and aiohttp (only http.client-based requests are traced);
  • Celery and RQ task tracing (use cron.monitor or trace in the task);
  • reporting logging.error() calls as error events (they are breadcrumbs, and with capture_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)

Source distribution for naijacloud-argus 0.1.0
File Size Uploaded Provenance
naijacloud_argus-0.1.0.tar.gz 69.7 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for naijacloud-argus 0.1.0
File Interpreter ABI Platform
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 log

Release 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 log

Security 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.

Select from 2 files

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 log

A 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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

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