SDK Protocol

Send events from any language to brakit's ingest endpoint.

Overview

Brakit isn't limited to Node.js. For deeper instrumentation of non-Node.js backends (database queries, logs, errors), any language can POST events to the ingest endpoint.

The stores, analysis engine, and dashboard are completely reused. A Python or Go SDK is a few hundred lines that feed events into the same pipeline.

Endpoint

POST http://localhost:<BRAKIT_PORT>/__brakit/api/ingest

Returns 204 No Content on success, 400 on invalid payload.

Payload Format

{
  "_brakit": true,
  "version": 1,
  "sdk": "brakit-python/0.1.0",
  "events": [
    {
      "type": "db.query",
      "requestId": "uuid-from-x-brakit-request-id-header",
      "timestamp": 1708000000000,
      "data": {
        "operation": "SELECT",
        "table": "users",
        "duration": 45,
        "source": "django-orm",
        "sql": "SELECT * FROM users WHERE id = %s",
        "rowCount": 1
      }
    }
  ]
}

Event Types

TypeRequired fieldsOptional fields
db.queryoperation, table, durationsql, source, rowCount, model
fetchurl, method, statusCode, duration-
loglevel, message-
errorname, messagestack
auth.checkproviderresult

duration is in milliseconds. level is one of log, warn, error, info, debug. operation is one of SELECT, INSERT, UPDATE, DELETE, OTHER.

Request Correlation

For request correlation, your SDK should generate a unique ID per incoming request and include it in all events. Your SDK should:

  1. Generate or read a unique ID for each incoming HTTP request.
  2. Store it in a request-scoped context (thread-local, context var, etc.).
  3. Include it as requestId in every event emitted during that request.

This is how database queries, fetch calls, and logs are correlated back to the HTTP request that triggered them.

Batching

Buffer events and flush periodically (every 50–100ms) or when the buffer reaches a threshold (20 events). Use fire-and-forget HTTP. Don't block on the response. If brakit isn't running, silently drop events.

The SDK should never interfere with your application's behavior. If brakit isn't running, everything should work exactly the same. events are just dropped.

Minimal SDK Structure

brakit-<language>/
  src/
    transport     # Batched HTTP POST to ingest endpoint
    context       # Request-scoped storage for requestId
    middleware    # HTTP middleware to extract x-brakit-request-id
    adapters/
      django      # Patches Django ORM query execution
      sqlalchemy  # Patches SQLAlchemy engine.execute

The SDK should auto-detect installed libraries and patch only those found. The same pattern as the Node.js adapter registry.

Example: Python

import requests
import json
import threading
from queue import Queue

class BrakitTransport:
    def __init__(self, port):
        self.url = f"http://localhost:{port}/__brakit/api/ingest"
        self.buffer = Queue()
        self._start_flush_timer()

    def emit(self, event):
        self.buffer.put(event)
        if self.buffer.qsize() >= 20:
            self.flush()

    def flush(self):
        events = []
        while not self.buffer.empty():
            events.append(self.buffer.get_nowait())
        if not events:
            return
        try:
            requests.post(self.url, json={
                "_brakit": True,
                "version": 1,
                "sdk": "brakit-python/0.1.0",
                "events": events,
            }, timeout=1)
        except Exception:
            pass  # Fire and forget