Laminar Dashboards let you track key metrics and build visualizations from your trace, evaluation, and other data on the platform using SQL. Each project has pre-built dashboards that track key LLM metrics for your project. You can also create your own custom dashboards by writing custom SQL queries.

What you can do

  • Query your trace, evaluation, and other data using SQL
  • Create visualizations tailored to your needs
  • Add parameters to make charts interactive
Laminar Dashboard overview with example charts and filters

Getting Started

The Chart Builder workflow consists of the following steps:
  1. Query: Write Clickhouse SQL queries to retrieve your data
  2. Configure Parameters (optional): Set up dynamic parameters (start and end date, interval unit, etc.) for interactivity
  3. Query Data: Execute query to get data
  4. Build Chart: Configure chart type and visualization settings
  5. Export to Dashboard: Save your chart and add it to a dashboard
Chart Builder overview

Query

Start by writing a Clickhouse SQL query that returns the data you want to visualize. Here is an example query that returns the number of traces created over the last 30 days grouped by day:
SELECT
    -- Convert timestamp to start of day for daily grouping
    toStartOfDay(created_at) as date,
    COUNT(*) as total_traces
FROM traces
WHERE created_at >= now() - INTERVAL 30 DAY
GROUP BY date
ORDER BY date

Parameters

To make your chart interactive with dashboard controls, you can configure these in Parameters tab:
  • {start_time: DateTime64} - Start date from the date range picker
  • {end_time: DateTime64} - End date from the date range picker
  • {interval_unit: String} - Grouping interval (HOUR, DAY, WEEK, MONTH)
chart-builder-parameters
Example query with parameters:
SELECT
    toStartOfInterval(created_at, toInterval(1, {interval_unit: String})) as time_bucket,
    COUNT(*) as count,
    AVG(duration_ms) as avg_duration
FROM traces
WHERE created_at >= {start_time: DateTime64}
    AND created_at <= {end_time: DateTime64}
GROUP BY time_bucket
ORDER BY time_bucket
By default, if you save query of the chart with parameters, chart will be sensitive to built-in filters on dashboard page. This can be useful if you want to see your query over different periods of time, or groupings.
dashboard-parameters

Chart Settings

  • Ensure you run your query to retrieve the data before configuring your chart.
chart-builder-settings
Only Line Charts support multiple metrics visualization, using Break down lines by option. If you need to display multiple metrics, use a Line Chart or create separate charts for each metric.

Export to Dashboard

  • Once you’ve configured your chart, export it with a name to add it to your dashboard.
chart-builder-export

Customizing Charts

After adding your chart to the dashboard, you can resize it to fit your layout needs. Simply click and drag the corners or edges of the chart to adjust its dimensions.
Resizing charts on dashboard

More Examples

Trace average duration over time

SELECT
    -- Round start_time to the beginning of the specified interval (MINUTE, HOUR, DAY, WEEK, MONTH)
    toStartOfInterval(start_time, toInterval(1, {interval_unit:String})) AS time,
    -- Calculate average duration for each time bucket, defaulting to 0 if no data
    toFloat64(COALESCE(AVG(duration), 0)) AS value
FROM traces
WHERE
    -- Filter traces within the specified time range
    start_time >= {start_time:DateTime64}
  AND start_time <= {end_time:DateTime64}
GROUP BY time
ORDER BY time
-- Fill gaps in time series with zero values for missing intervals
WITH FILL
FROM toStartOfInterval({start_time:DateTime64}, toInterval(1, {interval_unit:String}))
    TO toStartOfInterval({end_time:DateTime64}, toInterval(1, {interval_unit:String}))
    STEP toInterval(1, {interval_unit:String})

Total tokens over time

SELECT
    -- Round start_time to the beginning of the specified interval (MINUTE, HOUR, DAY, WEEK, MONTH)
    toStartOfInterval(start_time, toInterval(1, {interval_unit:String})) AS time,
    -- Sum total tokens consumed across all LLM spans in each time bucket
    sum(total_tokens) AS value
FROM spans
WHERE
    -- Filter for LLM spans only (span_type = 1 indicates LLM calls)
    span_type = 1
  -- Filter spans within the specified time range
  AND start_time >= {start_time:DateTime64}
  AND start_time <= {end_time:DateTime64}
GROUP BY time
ORDER BY time
-- Fill gaps in time series with zero values for missing intervals
WITH FILL
FROM toStartOfInterval({start_time:DateTime64}, toInterval(1, {interval_unit:String}))
    TO toStartOfInterval({end_time:DateTime64}, toInterval(1, {interval_unit:String}))
    STEP toInterval(1, {interval_unit:String})

Learn More

For more advanced SQL capabilities, syntax references, and examples, check out the SQL Editor documentation.