BugsRadar for Python
Updated 1 October 2026 · BugsRadar team
One package from PyPI for Python 3.9 and later: the standard logging module, loguru, uncaught exceptions and direct calls, with no dependencies outside the standard library.
You need a BugsRadar project with a channel and the project's API key first: see Get started.
The API key is secret: use it only in code that runs on your servers. Never put it in a desktop app you ship to others - PyInstaller, PySide or PyQt builds - or in a public repository: anyone can take the key out of them. Where the key may go
Install the package
pip install bugsradar
Set it up
Call init once, at the start of the program:
import os
import bugsradar
bugsradar.init(
api_key=os.environ["BUGSRADAR_KEY"],
environment="Production", # optional
)
init connects BugsRadar to logging and to uncaught exceptions. It adds no handlers, so your logging setup works as before. Keep the key out of the source, for example in an environment variable. The key is required: an empty one raises ValueError.
logging, loguru and frameworks
Each integration has a page of its own:
- logging - records at
ERRORand above from every logger, with the format string as the message template. - loguru - one sink added after your own loguru setup.
- Django, Flask and FastAPI - one
initcall is enough; the pages show where it goes.
Uncaught exceptions
init sets sys.excepthook and threading.excepthook. An exception that ends the program or a thread is reported, BugsRadar waits up to shutdown_timeout for the report to leave, and then the previous hook runs as before: the traceback is still printed. Pass capture_uncaught=False to turn this off.
Direct calls
try:
create_order(order_id)
except Exception as error:
bugsradar.send_exception(error, module="Orders")
# or the full event
bugsradar.send(
exception=error,
message_template="Order {order_id} failed",
message=f"Order {order_id} failed",
properties={"order_id": order_id},
module="Orders",
)
send and send_exception queue the event and return at once, so reporting an error never adds network time to your code. Nothing raises: delivery problems are logged as warnings by the bugsradar logger, which BugsRadar itself never sends anywhere.
Before the program exits
init registers an atexit hook that waits up to shutdown_timeout for queued reports. In a short script you can also wait yourself:
bugsradar.flush() # waits up to shutdown_timeout
How events travel
- Events go to a queue and are sent by a background thread; your code never waits for the network.
- Repeats of the same error within
repeat_interval(5 seconds) are folded into one request with a count. A crash loop costs one request every few seconds, not thousands per second. - The same exception object seen twice - logged and reported by hand - is sent once.
- On
429the client waits as long as the server asks; on5xxand network failures it retries three times.
Configuration
Argument of init | Default | Meaning |
|---|---|---|
api_key | - | Project API key from app.bugsradar.com. Required. |
environment | None | Environment name for events (Production, Staging). |
host | socket.gethostname() | Host for events. |
app_version | None | Version of your application. Not used for grouping. |
logging_level | logging.ERROR | Lowest level of the log records that go to BugsRadar; None leaves logging alone. |
capture_uncaught | True | Report exceptions that end the program or a thread. |
repeat_interval | 5 s | Repeats within this interval travel as one request. |
queue_capacity | 1000 | Queued events beyond this are dropped with a warning. |
shutdown_timeout | 5 s | How long flush(), the exit hook and an uncaught exception wait for the queue. |
request_timeout | 15 s | One request to the server. |
api_url | api.bugsradar.com | Change it only for a self-hosted BugsRadar. |
Something doesn't arrive? Write to support@bistriy.com and include the warnings of the bugsradar logger.