Python

The Python SDK targets Python 3.8+ and uses only the standard library — no requests, no httpx, no transitive deps. It installs a sys.excepthook and a threading.excepthook at init time so unhandled exceptions on the main thread and worker threads are captured automatically.

Install

$ pip install tinymonpy

Or pin it in requirements.txt / pyproject.toml:

tinymon==0.1.0

init()

Call init() once, at the very top of your app's entry point:

import os
import tinymon

tinymon.init(
    dsn=os.environ['TINYMON_DSN'],
    environment='production',
    release='1.0.0',
    sample_rate=1.0,
)

Arguments

ArgumentTypeDescription
dsnstrRequired. The project DSN, e.g. tm_pub_….
endpointstr | NoneOverride the ingest URL. Defaults to https://console.tinymon.dev/api/ingest.
environmentstr | NoneFree-form tag — production, staging, etc.
releasestr | NoneVersion string for your app.
sample_ratefloat0 to 1. Default 1.0.
before_sendCallable[[dict], dict | None]Mutate or drop events. Return None to drop.

Capturing exceptions

import tinymon

try:
    risky_thing()
except Exception as e:
    tinymon.capture_exception(e)

# Or a plain message:
tinymon.capture_message('cron job took 28 seconds', level='warning')

Levels: 'error', 'warning', 'info'.

User & tag context

tinymon.set_user({'id': user.id})
tinymon.set_tag('plan', user.plan)
tinymon.set_tag('tenant_id', str(tenant.id))
Privacy. Only pass an identifier — not an email or name. The scope is module-global, not per-request, so for web frameworks see the per-framework section below.

Add short notes about what happened before an error. The last 30 are attached to the next event.

import time

tinymon.add_breadcrumb({
    'timestamp': time.time(),
    'category':  'http',
    'message':   'POST /api/orders → 500',
    'level':     'error',
})

Frameworks

Flask

import tinymon
from flask import Flask

tinymon.init(dsn=os.environ['TINYMON_DSN'])

app = Flask(__name__)

@app.errorhandler(Exception)
def on_error(e):
    tinymon.capture_exception(e)
    raise

Django

Add a small middleware:

class TinymonMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    def __call__(self, request):
        return self.get_response(request)
    def process_exception(self, request, exc):
        tinymon.capture_exception(exc)
        return None

FastAPI

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()

@app.exception_handler(Exception)
async def on_error(request: Request, exc: Exception):
    tinymon.capture_exception(exc)
    return JSONResponse({'error': 'internal'}, status_code=500)

Celery / background workers

Capture in the task's on_failure hook or wrap the task body in try/except. The SDK installs a threading.excepthook so untouched worker threads are also covered.