Errors API
Report errors to MiniAPM for tracking, grouping, and analysis.
Single Error
Section titled “Single Error”Endpoint
Section titled “Endpoint”POST /ingest/errorsHeaders
Section titled “Headers”| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <api_key> |
Content-Type | Yes | application/json |
Request Body
Section titled “Request Body”{ "exception_class": "RuntimeError", "message": "Something went wrong", "backtrace": [ "app/models/user.rb:42:in `save`", "app/controllers/users_controller.rb:15:in `create`" ], "fingerprint": "user_save_runtime_error", "request_id": "abc-123-def", "user_id": "123", "params": { "id": "999" }, "timestamp": "2024-01-01T12:00:00Z"}Fields
Section titled “Fields”| Field | Type | Required | Description |
|---|---|---|---|
exception_class | string | Yes | Exception class name |
message | string | Yes | Error message |
backtrace | array | Yes | Stack trace lines |
fingerprint | string | Yes | Grouping key for deduplication |
request_id | string | No | Request identifier |
user_id | string | No | User identifier |
params | object | No | Additional context data (JSON) |
timestamp | string | No | ISO 8601 timestamp (defaults to now) |
source_context | object | No | Source code context (see below) |
Response
Section titled “Response”Returns 202 Accepted on success with no response body.
Example
Section titled “Example”curl -X POST http://localhost:3000/ingest/errors \ -H "Authorization: Bearer proj_abc123..." \ -H "Content-Type: application/json" \ -d '{ "exception_class": "ActiveRecord::RecordNotFound", "message": "Could not find User with id=999", "backtrace": [ "app/controllers/users_controller.rb:10:in `show`", "lib/middleware/auth.rb:25:in `call`" ], "fingerprint": "users_controller_record_not_found", "params": { "id": "999" } }'Batch Errors
Section titled “Batch Errors”Report multiple errors in a single request.
Endpoint
Section titled “Endpoint”POST /ingest/errors/batchRequest Body
Section titled “Request Body”{ "errors": [ { "exception_class": "RuntimeError", "message": "Error 1", "backtrace": ["..."], "fingerprint": "fp1" }, { "exception_class": "NoMethodError", "message": "Error 2", "backtrace": ["..."], "fingerprint": "fp2" } ]}Response
Section titled “Response”Returns 202 Accepted on success. Returns 500 only if all errors fail to ingest.
Error Grouping
Section titled “Error Grouping”MiniAPM groups errors by fingerprint. The client is responsible for computing the fingerprint, typically from:
- Exception class name
- Error location (top stack frame)
- Normalized message
Errors with the same fingerprint are grouped together, showing:
- First seen timestamp
- Last seen timestamp
- Occurrence count
- Trend over time
Source Context
Section titled “Source Context”Include source code context for richer error display in the dashboard:
{ "exception_class": "RuntimeError", "message": "Invalid state", "backtrace": ["app/models/user.rb:42:in `save`"], "fingerprint": "user_save_invalid", "source_context": { "file": "app/models/user.rb", "lineno": 42, "pre_context": [" def save", " validate!"], "context_line": " raise 'Invalid' unless valid?", "post_context": [" end", ""] }}Source Context Fields
Section titled “Source Context Fields”| Field | Type | Required | Description |
|---|---|---|---|
file | string | Yes | File path |
lineno | integer | Yes | Line number |
context_line | string | Yes | The error line |
pre_context | array | No | Lines before the error |
post_context | array | No | Lines after the error |
Error Status
Section titled “Error Status”Errors can be managed through the dashboard:
- Open - New or active error
- Resolved - Fixed, but can reopen if it recurs
- Ignored - Won’t show in dashboard
Integration Examples
Section titled “Integration Examples”Ruby (manual)
Section titled “Ruby (manual)”begin risky_operationrescue => e MiniAPM.record_error(e, context: { user_id: current_user.id, params: request.params.except(:password) }) raiseendRuby (automatic)
Section titled “Ruby (automatic)”The miniapm gem captures exceptions automatically in Rails.
Python
Section titled “Python”import requests
def report_error(exception, context=None): import traceback
requests.post( 'http://localhost:3000/ingest/errors', headers={ 'Authorization': 'Bearer proj_abc123...', 'Content-Type': 'application/json' }, json={ 'exception_class': type(exception).__name__, 'message': str(exception), 'backtrace': traceback.format_exception(exception), 'fingerprint': f"{type(exception).__name__}_{traceback.extract_tb(exception.__traceback__)[-1].filename}", 'params': context or {} } )JavaScript
Section titled “JavaScript”async function reportError(error, context = {}) { await fetch('http://localhost:3000/ingest/errors', { method: 'POST', headers: { 'Authorization': 'Bearer proj_abc123...', 'Content-Type': 'application/json' }, body: JSON.stringify({ exception_class: error.name, message: error.message, backtrace: error.stack?.split('\n') || [], fingerprint: `${error.name}_${error.message}`, params: context }) });}