Skip to main content

Documentation Index

Fetch the complete documentation index at: https://laminar.sh/docs/llms.txt

Use this file to discover all available pages before exploring further.

Dashboards are a grid of charts you build over your traces, spans, and signal events. Mix line charts, bar charts, horizontal bars, and tables on one canvas, resize each card, and every chart shares the same time range so you read everything against the same window.
A Laminar dashboard showing a mix of line, bar, horizontal bar, and table charts

Start from a preset

The + Chart button opens a preset picker grouped by data source: Traces, Spans, Signals, plus Custom for the blank chart builder. Pick one and you land in the chart editor with the query already shaped; tweak filters, group-bys, or the name before saving.
Chart presets popover with Custom option and Traces/Spans/Signals tabs
Presets that ship today:
  • Traces: Trace p90 cost, Trace p90 duration, New traces, Total duration, Expensive traces, Longest traces.
  • Spans: Total cost, Total tokens, Tokens by model, Top span names, Expensive spans, Longest spans.
  • Signals: Signal events, Signal events table.

Chart types

Chart type dropdown showing Line Chart, Bar Chart, Horizontal Bar, and Table
  • Line Chart: time series. Data is grouped by an interval that auto-adjusts to the selected time range.
  • Bar Chart: time series as vertical bars. Useful when you want to emphasize individual buckets.
  • Horizontal Bar: ranked comparisons. Clicking a bar opens the underlying trace or span in a side panel.
  • Table: a SQL-backed data dump with sortable columns, infinite scroll, and column order, width, and visibility that persist on the chart. Rows render an inline link in the trace_id or id column that opens the trace.

Click and drag to narrow a time range

Drag across any time-series chart to highlight a range. The same range overlays every other chart on the dashboard via a shared sync, so you can see the selection land across every panel at once.
Drag selection across dashboard charts with a Zoom to selection and Open in traces toolbar
When you release the drag, a floating toolbar shows the selected window and its duration, plus two actions:
  • Zoom to selection rewrites the dashboard’s startDate and endDate so every chart re-queries against the narrower window.
  • Open in traces opens the Traces page in a new tab, pre-filtered to the same window.

Open a trace from a chart

Horizontal bar rows and table rows are clickable. Clicking a bar or an id or trace_id cell opens the trace in a side panel so you can jump from a metric straight to the run that produced it, with no need to copy an ID into the Traces page. This works because the chart editor auto-injects the relevant id column into the query when you pick a table that has one (traces, spans, signal_events). The injected column is hidden from the chart’s visual output but carries through to the click handler.

Building a chart

To create a chart from scratch, click + Chart and choose Custom.
Building a chart in the editor
The editor asks for:
  1. Type: line, bar, horizontal bar, or table (see above).
  2. Table: traces, spans, or signal_events.
  3. Metric: one of count, sum, avg, min, max, p90, p95, p99 on a column, or Custom SQL for an arbitrary expression (covered below). Tables use a column picker instead of a metric.
  4. Filters: narrow rows before aggregation.
  5. Group By: break the metric down by a dimension (e.g. model, provider, span_type).
  6. Order By and Limit: relevant to horizontal bar and table.
  7. Display Value: covered below.
For the full reference on tables, columns, and SQL semantics, see the SQL Editor reference.

Custom SQL metrics

If the built-in aggregations don’t cover what you need, pick Custom SQL from the metric dropdown. The column picker is replaced by a small SQL editor with schema-aware autocomplete for the selected table. Whatever you type is inserted as the <expr> in:
SELECT <expr> FROM <table>
So write it as a single projection: either a bare aggregation (countIf(status = 'ERROR'), avg(total_tokens), quantile(0.95)(duration)) or any ClickHouse expression that returns one value per group. Group-by dimensions and filters are applied by the rest of the chart builder around your expression, so you don’t need a GROUP BY or WHERE clause inside it. A few patterns that come up often:
  • Conditional counts: countIf(span_type = 'LLM' AND status = 'ERROR') to count only error LLM spans.
  • Ratios: countIf(status = 'ERROR') / count() * 100 to chart an error rate as a percentage.
  • Custom percentiles: quantile(0.75)(duration) when the built-in p90/p95/p99 aren’t the cut you want.
  • Expressions over multiple columns: sum(input_cost + output_cost).
The schema autocomplete knows which columns exist on each table. For the full list of tables (traces, spans, signal_events, evaluation_results, etc.) and their columns, see the SQL editor table schemas reference.

Custom columns on tables

Tables don’t aggregate, so instead of a metric they take a list of columns. Each row is either a column from the table or, via the Custom SQL option in the same dropdown, an arbitrary SQL expression evaluated per row. Custom columns are useful when the column you want doesn’t exist as-is on the table:
  • Combine fields: concat(name, ' (', model, ')').
  • Pull a value out of a JSON attribute: JSONExtractString(attributes, 'gen_ai.request.model').
  • Compute a derived value: total_tokens / duration for tokens per second per span.
  • Format a value: formatReadableSize(input_tokens).
Custom columns render as a regular column in the output table; the header is a stable auto-generated alias (e.g. column_ab12cd) so reordering or removing other columns doesn’t rename it. Rename it by editing the chart’s column list. The same schema autocomplete and table reference apply: see the SQL editor table schemas reference for what’s queryable on each table.

Display Value

Line and bar charts can render a headline number above the plot: the total across the visible window, the average across buckets, or nothing.
Display Value dropdown with None, Total, Average
The displayed value uses smart unit formatting: cost columns render with a $ prefix, duration columns render with a seconds suffix, everything else renders as a plain number.

Examples

Total tokens by model

See which models consume the most tokens, and how that breakdown shifts over time.
Total tokens by model chart
  • Type: Line Chart
  • Table: spans
  • Metric: total_tokens with sum
  • Group By: model
  • Filter: span_type = LLM

p90 cost by provider

Track what your p90 (the cost of your more expensive requests) looks like across providers, so you can spot cost regressions early.
p90 cost by provider chart
  • Type: Line Chart
  • Table: spans
  • Metric: cost with p90
  • Group By: provider