LINEARJEPH SDKs
The LINEARJEPH SDKs connect your application to the maintenance service: unhandled errors become grouped issues with release tracking, request timings become performance charts, cron jobs report heartbeats, and your installed packages feed the dependency audit.
There are three SDKs. All have zero runtime dependencies, never throw into your application, send in the background through a bounded queue, retry with backoff and flush when the process exits.
- Python: Django, Flask, FastAPI and any ASGI app. Python 3.8 or newer.
- Node.js: Express and any Node 18+ service, CommonJS, ESM and TypeScript types.
- Go:
net/httpmiddleware, Go 1.21 or newer. - Ingest HTTP API: the three endpoints the SDKs call, for any other language.
Get your ingest key
Every application you add under Dashboard > Maintenance > Applications has its own ingest key. Open the application, choose Reveal key, and copy the key (it looks like lj_app_...) together with the install snippet for your stack. Rotate the key from the same panel if it leaks; SDKs using the old key stop reporting until you update them.
Treat the key like a password: keep it in an environment variable or secret store, not in source control. One key belongs to one application, so use a separate application per environment you want to track on its own (production, staging), or set environment in the SDK to tell them apart.
Error tracking and heartbeats need an active maintenance plan. Performance monitoring and the dependency audit are included from the Professional plan.
Install
| Language | Install | Import |
|---|---|---|
| Python | pip install https://linearjeph.cc/sdk/linearjeph-1.0.0.tar.gz | import linearjeph |
| Node.js | npm install https://linearjeph.cc/sdk/linearjeph-sdk-1.0.0.tgz | require("@linearjeph/sdk") or import ... from "@linearjeph/sdk" |
| Go | go get github.com/kingtechies/linearjeph-sdk/go | import linearjeph "github.com/kingtechies/linearjeph-sdk/go" |
Every release is also downloadable from LINEARJEPH, so installs never depend on a third-party registry: pip install https://linearjeph.cc/sdk/linearjeph-1.0.0.tar.gz, npm install https://linearjeph.cc/sdk/linearjeph-sdk-1.0.0.tgz. Source code: github.com/kingtechies/linearjeph-sdk (MIT).
Quickstart
import linearjeph
linearjeph.init("lj_app_YOUR_KEY", release="1.4.2", environment="production")require("@linearjeph/sdk").init({ key: "lj_app_YOUR_KEY", release: "1.4.2" });linearjeph.Init(linearjeph.Options{Key: "lj_app_YOUR_KEY", Release: "1.4.2"})
defer linearjeph.Flush(5 * time.Second)From here uncaught exceptions are reported automatically, and the framework middleware adds request timings. The default endpoint is https://linearjeph.cc.
Concepts
Errors and issues
Each captured exception is sent as an error event. LINEARJEPH groups events into issues using a fingerprint: the exception type plus the three innermost in-app stack frames (file and function, with numbers in file names normalised). When there are no in-app frames the fingerprint uses the exception type and message with numbers normalised. Frames from site-packages, node_modules and the Go standard library or module cache are marked as not in-app.
An issue is new, regressed, resolved or ignored. A new issue and a regression each send one alert email to the account's billing recipients. Resolving an issue records the release it was resolved in.
capture_message (Python), captureMessage (Node) and CaptureMessage (Go) send a message as an event of type Message; messages with the same text group into one issue.
LINEARJEPH keeps every raw event for the first 20 occurrences of an issue and then one in ten, so issue counts stay exact while storage stays bounded. Events are kept 90 days.
Releases
Set release to something that changes with every deploy: a version number (1.4.2) or a build number. The first release an issue is seen in is recorded. If a resolved issue appears again in a newer release it becomes regressed. Release comparison is numeric-aware (1.10.0 is newer than 1.9.0). Release strings that are not version-like (for example a bare git SHA) cannot be ordered, so any different release counts as newer; prefer 1.4.2+abc1234 or a build number when you want reliable regression detection.
In CI, pass the release in an environment variable and read it in your init call:
# GitHub Actions
env:
LINEARJEPH_RELEASE: ${{ github.ref_name }}-${{ github.run_number }}Performance
Transactions are timed operations (usually one HTTP request). The service keeps hourly rollups per transaction name and shows count, errors, p50, p95 and throughput for the last seven days. Use stable names such as GET /items/<id> (the framework integrations use the route pattern, not the raw URL). Transactions need the Professional plan or above; on Essential they are accepted by the endpoint but not stored.
Heartbeats
A heartbeat is a check-in from a cron job or worker: ok or error. The first check-in with a new name creates a heartbeat monitor automatically (up to 20 per application) and records the expected interval. If no check-in arrives within the interval plus a 5 minute grace period, or a check-in reports error, an incident opens and an alert is sent. The next ok closes it.
Dependency audit
report_packages / reportPackages / ReportPackages send the packages your application actually uses (installed Python distributions, the package-lock.json tree, or the Go build info). The dependency audit checks them against the OSV vulnerability database daily and reports findings with severity and fixed versions. Each call replaces the previously reported list for that ecosystem, so call it on deploy rather than per request. Needs the Professional plan or above.
Common behaviour
| Behaviour | Detail |
|---|---|
| Never crashes your app | Every public function catches its own failures. Without init they do nothing. |
| Non-blocking | Events go on a bounded queue (default 100) drained by one background worker. A full queue drops new items and counts them. |
| Batching | Up to 20 events per request (configurable to 100). |
| Retries | 429, 5xx and network errors retry up to 4 times with exponential backoff and jitter; a Retry-After header on 429 is honoured. |
| Bad key | A 401 disables sending (and logs once) so a rotated key does not cause retry storms. |
| Oversized | A 413 on a batch splits it in half; a single oversized event is dropped. |
| Flush on exit | Python atexit, Node beforeExit, Go Flush (call it yourself). |
| Sampling | sample_rate for errors and traces_sample_rate for transactions, 0 to 1. |
before_send | Inspect, change or drop each event right before it is queued. |
| Scrubbing | Tag values under keys containing password, secret, token, authorization, auth, cookie, api_key, session, csrf, bearer, credential or private_key are replaced by [Filtered], and password=... or Bearer ... text in messages is masked. Add your own with scrub_keys. The SDKs never send request headers, bodies or cookies. |
| Limits | Events carry at most 20 tags (key 50 chars, value 200), exception message 500 chars, 50 stack frames, one user id (100 chars). |
See Ingest HTTP API for the exact payloads and response codes.
Troubleshooting
- Nothing appears. Enable debug logging (
debug=True,debug: true,Debug: true) and check the key. A 401 means the key is wrong or was rotated. - Errors appear but no performance data. Transactions need the Professional plan or above, and the framework middleware must be installed.
- Events accepted but count is 0. The endpoint answers 202 with
accepted: 0when the plan is inactive, the monthly event allowance is used up, or an event fails validation. - Short-lived scripts lose events. Flush before exit: Python and Node do it automatically on normal exit; call
flush()/Flush()yourself beforeos._exit,process.exitor in short-lived handlers. - Too many transaction names. Pass route patterns, not raw URLs with ids.