Reporting Events

This feature is currently in preview. Please contact us to request access for testing.

Your newline-delimited JSON payload should be submitted as the body of a POST request to https://api.honeybadger.io/v1/events with the following headers:

  • X-API-Key: The API key from your project settings page
  • Accept: application/json
  • User-Agent: "{{ Client name }} {{ client version }}; {{ language version }}; {{ platform }}"

Regarding the format of the User-Agent header, you can see an example of how that's generated in our Ruby implementation here, which generates a string like this: HB-Ruby 2.1.1; 2.2.7; x86_64-linux-gnu. If you don't have all this information available to send, that's OK, but the more the merrier. :)

If all went well with your POST, you'll get a response with the status code 201 and information about the just-logged error as a JSON hash.

If all didn't go well, you could get a response with one of these status codes:

Status Code Description
403 Either the API key is incorrect or the account has been deactivated
413 The payload size was too large. The maximum acceptable size is 102,400 bytes
422 The payload couldn't be processed.
429 The API key was valid, but the payload was not accepted because you hit a rate limit (i.e., we have received too much traffic for this API key).
500 Our bad! :)

Sample Payloads

Each line of the payload must be a single JSON object. The structure of the events you send to this endpoint is up to you, based on your use case. For example, if you wanted to send lines from an unstructured log, you could send a payload like this:

javascript
{"ts": "2023-08-31T09:19:30Z", "message": "This is a log line"} {"ts": "2023-08-31T09:19:30Z", "message": "This is another log line"}

We strongly recommend you send structured logs to make querying a better experience:

javascript
{"ts": "2023-08-31T16:17:57Z", "level": "info", "action": "health", "controller": "PagesController", "method": "GET", "path": "/health", "status": 200, "duration": 322}

Sending events in this way would make it easy to do analytical queries like average request duration, counts by request path, etc.

Of course, you aren't limited to logs — you can track any kind of event that makes sense for your application:

javascript
{"ts": "2023-08-31T14:31:05Z", "event": "user.signup", "user": {"id": 42, "source": "Daring Fireball Ad"}} {"ts": "2023-08-31T14:33:05Z", "event": "company.created", "project": {"id": 54, "name": "Spacely Space Sprockets", "shared": true}}

You do not need to include a ts element in each JSON object, but if you do, it must be an RFC3339-formatted timestamp. If ts is omitted, or if it can't be parsed as a timestamp, it will be added or replaced with the value of the current time as of the payload being processed.

Sending events from log files and other sources

If you have existing log files that have events that you'd like to send to the API, you can use Vector to watch those files and send the events. Here's a sample configuration that will encode the log lines into the newline-delimited JSON format that the API expects: Vector supports all kinds of input sources, such as Docker logs, Redis metrics, etc.

If you are using something like Lograge to emit JSON-formatted logs (and you should — it's awesome), you can have Vector replace the message field with a JSON payload:

yaml
sources: app: type: "file" include: ["/home/app/shared/log/*.log"] transforms: parse_logs: type: "remap" inputs: ["app"] source: | payload, err = parse_json(string!(.message)) if err == null { .payload = payload del(.message) } sinks: honeybadger_events: type: "http" inputs: ["parse_logs"] uri: "https://api.honeybadger.io/v1/events" request: headers: X-API-Key: "Your project API key" encoding: codec: "json" framing: method: "newline_delimited"

Or if you are using logfmt-style logs, like "controller=pages action=index", then you can add a transform that parses that into JSON:

yaml
... transforms: parse_logs: type: "remap" inputs: ["app"] source: | payload, err = parse_key_value(string!(.message)) if err == null { .payload = payload del(.message) } ...

Again, we highly recommend structured logging. 😉

Limits

Nested JSON structures are supported, but limiting the nesting to 2 or 3 levels is best. Each event must be less than 100kB, and the total request size must be less than 5MB.