Log event reference

One row shape for errors, events and measurements, and the conventions we suggest.

An error, an event and a measurement are the same row. They differ in the severity they carry and the attributes they fill in, never in where they go.

What you write

FieldWhat it is
timeWhen it happened. Stamped by the client, and what every query buckets on.
nameWhat happened. Any string up to 128 characters.
severity1 to 24. A number, not a word. See the ladder below.
distinct_idThe anonymous id that client generated for itself. Required.
attributesEverything else, as JSON. Up to 64 keys, 4 levels deep.

Names follow ^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$. : and > are reserved, because internal query keys are delimited with them.

What the server adds

FieldWhat it is
project_idResolved from your source key. Never sent, never claimed.
firstrun.source.idWhich source the event arrived through.
ingested_atArrival time. Debugging only: nothing sorts or buckets on it.

Severity

The OpenTelemetry ladder: six bands of four. The band is what you filter on; the four steps inside it are there so a logger with nine levels of its own can map onto this one without losing the order.

BandNumbersWhat it means
TRACE1 to 4Step-by-step detail nobody reads until something is wrong.
DEBUG5 to 8Developer detail.
INFO9 to 12Ordinary things happening. Every event helper lands here.
WARN13 to 16Something recovered, or is about to stop recovering.
ERROR17 to 20Something threw. The error helper lands here.
FATAL21 to 24The process is going down.

Conventional names

Suggestions, not law. Any other name you send is stored, indexed and queried identically, and no event is ever rejected for the name it carries.

NameUsually written by
page_viewBrowser tag, or you
session_startBrowser tag
app_installDesktop SDK, first run only
app_launchDesktop SDK, every run
identifyAny client, on identify()
page_leaveBrowser tag
outbound_clickBrowser tag
file_downloadBrowser tag
form_submitBrowser tag
exceptionAny client, on error()
web_vitalBrowser tag
http.requestServer SDKs
measurementYou, for a numeric sample

Conventional attributes

The OpenTelemetry semantic conventions where they exist, and firstrun.* where they do not. These are the keys the pickers offer before your project has written anything.

KeyWhat it holds
exception.typeThe class of the thrown thing.
exception.messageThe message on it.
exception.stacktraceThe formatted stack, as one string.
session.idThe visit or the run this belongs to.
user.idWhatever you passed to identify(). Never anything else.
service.versionThe build of your software that wrote this.
os.typewindows, darwin, linux, ios, android.
host.archThe machine architecture.
url.pathThe path alone. What a breakdown by page groups on.
url.fullThe whole URL, query string included.
http.routeThe route template, not the resolved path.
http.response.status_codeThe status that went back.
browser.languageThe BCP-47 tag the client reported.
firstrun.referrer.hostThe referring host alone.
firstrun.utm.sourceAlso .medium, .campaign, .term, .content.
firstrun.channelstable, beta, nightly.
firstrun.duration_msHow long something took.
firstrun.metricWhat a numeric sample is called: LCP, queue_depth.
firstrun.valueThe sample itself, as a number.
firstrun.unitThe unit it is in, when that is not obvious.

Any other key works identically. Write order.total or tenant or rows_exported and it is stored, filtered, grouped and aggregated exactly like the ones above. Following a convention buys you a suggestion in a picker and a shared spelling with the next project. It buys nothing else, and skipping one costs nothing.

Limits

  • 64 top-level attribute keys, nested 4 levels deep, 128 items per array or object.
  • Keys up to 128 characters, string values up to 4096.
  • Values are JSON: strings, numbers, booleans, null, arrays and objects. A number stays a number.