A free-form line. What the level helpers name an entry.
| Field | Value |
|---|---|
| Name | log |
| Severity | 1 to 24, whichever helper you called |
| Written by | Every SDK, from trace(), debug(), info(), warn(), errorLog() and fatal(). |
Whenever you write a line rather than record an occurrence of something. The sentence travels in the body attribute and the level is the severity, not a word inside the text.
A line still needs a name, because name is the column a board groups on, and every client spells that name the same way. It is what keeps lines separable from events without either of them needing a type: filter the name out and a board of your own events is unaffected by however much your server logs.
The browser tag has no level helpers, so it never writes this. Use log() there with a name and a severity of your own.
| Attribute | Type | What it holds |
|---|---|---|
| body | string | The line itself. OpenTelemetry has body as a top-level field; five columns are promoted here and no more, so it travels as an attribute under the spec's own name. |
Every entry also carries the resource its client sends once per batch: session.id, user.id once you have called user(), and the rest of the list on the overview. Anything you pass yourself lands in the same map, and your key wins on a collision.
No logger name, no file, no line number and no thread. Anything of that sort is yours to put in the attribute map, where it is filtered and grouped exactly like the keys we suggest.
A widget is a filter, a group by, an aggregate, a time bucket and a limit. These are those five parts written out, and every one of them is something you can build yourself.
| Question | The query |
|---|---|
| Warnings and worse, over time | Name is log . severity is at least 13 . count of entries . bucket by hour |
| The noisiest builds | Name is log . group by service.version . count of entries |
| One phrase, wherever it appears | Name is log . body contains timeout . count of entries . bucket by day |