@@ -5,26 +5,11 @@ description: "Create custom dashboards with real-time metrics powered by TRQL qu
55
66## Overview
77
8- Metrics allow you to build custom dashboards that visualize your run data in real-time. Each metric is powered by a TRQL query and can be displayed as charts, tables, or single values. Metrics automatically refresh to show the latest data .
8+ In the Trigger.dev dashboard we have built- in dashboards and you can create your own .
99
10- ## What are Metrics?
10+ Metrics dashboards are powered by [ TRQL queries ] ( /insights/query ) with widgets that can be displayed as charts, tables, or single values. They automatically refresh to show the latest data.
1111
12- Metrics are reusable query widgets that:
13-
14- - Execute TRQL queries against your run data
15- - Display results as charts, tables, or single values
16- - Auto-refresh at configurable intervals
17- - Support filtering by time range, tasks, queues, and tags
18- - Can be organized into custom dashboards
19-
20- ## Creating Metrics in the Dashboard
21-
22- 1 . Navigate to the Metrics page in your environment
23- 2 . Click "Add Metric" or "Add Widget"
24- 3 . Write your TRQL query
25- 4 . Choose a visualization type
26- 5 . Configure refresh interval and filters
27- 6 . Save and position on your dashboard
12+ ![ The built-in Metrics dashboard] ( /images/metrics-built-in.png )
2813
2914### Visualization types
3015
@@ -34,205 +19,25 @@ Metrics are reusable query widgets that:
3419- ** Table** - Show detailed data in rows
3520- ** Single value** - Display a single metric (count, sum, average, etc.)
3621
37- ## Query widget configuration
38-
39- Each metric widget is configured with:
40-
41- ``` typescript
42- type QueryWidgetConfig = {
43- // Visualization type
44- type: " line" | " bar" | " area" | " table" | " value" ;
45-
46- // For charts: which column to use for X-axis
47- xAxis? : string ;
48-
49- // For charts: which columns to plot as series
50- series? : string [];
51-
52- // For value widgets: which column to display
53- valueColumn? : string ;
54-
55- // Optional: format for displayed values
56- format? : {
57- type: " number" | " currency" | " duration" | " percentage" ;
58- decimals? : number ;
59- };
60- };
61- ```
62-
63- ## Using metrics programmatically
64-
65- While metrics are typically created in the dashboard, you can also fetch metric data programmatically using the Query API.
66-
67- ### Example: Fetch metric data via SDK
68-
69- ``` typescript
70- import { query } from " @trigger.dev/sdk" ;
71-
72- // Get run count by status (for a pie/bar chart)
73- const statusMetric = await query .execute (
74- ` SELECT
75- status,
76- count() AS count
77- FROM runs
78- GROUP BY status ` ,
79- { period: " 7d" }
80- );
81-
82- // Get runs over time (for a line chart)
83- const trendsMetric = await query .execute (
84- ` SELECT
85- timeBucket() AS time,
86- count() AS runs
87- FROM runs
88- GROUP BY time
89- ORDER BY time ASC ` ,
90- { period: " 30d" }
91- );
92-
93- // Get average duration by task (for a table)
94- const performanceMetric = await query .execute (
95- ` SELECT
96- task_identifier,
97- count() AS run_count,
98- avg(usage_duration) AS avg_duration_ms,
99- median(usage_duration) AS median_duration_ms
100- FROM runs
101- GROUP BY task_identifier
102- ORDER BY run_count DESC ` ,
103- { period: " 7d" }
104- );
105- ```
106-
107- ## Common metric examples
108-
109- ### Success rate over time
110-
111- ``` sql
112- SELECT
113- timeBucket() AS time ,
114- countIf(status = ' Completed' ) AS completed,
115- countIf(status = ' Failed' ) AS failed,
116- round(completed / (completed + failed) * 100 , 2 ) AS success_rate
117- FROM runs
118- WHERE status IN (' Completed' , ' Failed' )
119- GROUP BY time
120- ORDER BY time ASC
121- ```
122-
123- ** Visualization:** Line chart with ` time ` as X-axis and ` success_rate ` as series
124-
125- ### Task execution breakdown
126-
127- ``` sql
128- SELECT
129- task_identifier AS task,
130- count () AS runs,
131- countIf(status = ' Completed' ) AS completed,
132- countIf(status = ' Failed' ) AS failed,
133- round(avg (usage_duration) / 1000 , 2 ) AS avg_duration_sec
134- FROM runs
135- GROUP BY task
136- ORDER BY runs DESC
137- ```
138-
139- ** Visualization:** Table showing all columns
140-
141- ### Total runs today
142-
143- ``` sql
144- SELECT count () AS total
145- FROM runs
146- WHERE created_at >= toStartOfDay(now())
147- ```
148-
149- ** Visualization:** Single value widget showing ` total `
150-
151- ### Cost analysis by task
152-
153- ``` sql
154- SELECT
155- task_identifier,
156- sum (compute_cost) AS total_cost,
157- avg (compute_cost) AS avg_cost,
158- count () AS runs
159- FROM runs
160- WHERE compute_cost > 0
161- GROUP BY task_identifier
162- ORDER BY total_cost DESC
163- LIMIT 10
164- ```
165-
166- ** Visualization:** Bar chart with ` task_identifier ` as X-axis and ` total_cost ` as series
167-
168- ### Queue depth over time
169-
170- ``` sql
171- SELECT
172- timeBucket() AS time ,
173- queue,
174- countIf(status = ' Queued' ) AS queued_runs
175- FROM runs
176- WHERE status = ' Queued'
177- GROUP BY time , queue
178- ORDER BY time ASC
179- ```
180-
181- ** Visualization:** Area chart with multiple series (one per queue)
182-
183- ### Failed runs requiring attention
184-
185- ``` sql
186- SELECT
187- task_identifier,
188- run_id,
189- error,
190- attempt,
191- created_at
192- FROM runs
193- WHERE status = ' Failed'
194- AND created_at > now() - INTERVAL 1 HOUR
195- ORDER BY created_at DESC
196- LIMIT 20
197- ```
198-
199- ** Visualization:** Table showing recent failures
200-
201- ## Dashboard organization
202-
203- ### Time filters
204-
205- All widgets on a dashboard share common time filters:
206-
207- - ** Period shortcuts** - "Last hour", "Last 24 hours", "Last 7 days", "Last 30 days"
208- - ** Custom range** - Select specific start and end dates
209- - ** Live mode** - Continuously update with real-time data
210-
211- ### Additional filters
212-
213- Dashboards support global filters that apply to all widgets:
214-
215- - ** Tasks** - Filter to specific task identifiers
216- - ** Queues** - Filter to specific queues
217- - ** Tags** - Filter to runs with specific tags
218- - ** Status** - Filter by run status
22+ You can also add Titles to your dashboard.
21923
220- These filters are automatically injected into your TRQL queries.
24+ ## Filtering and time ranges
22125
222- ## Refresh intervals
26+ All widgets on a dashboard use the time range filter applied to the dashboard.
22327
224- Configure how often each widget refreshes :
28+ You can also filter the data by :
22529
226- - ** 30 seconds** - For monitoring critical metrics
227- - ** 1 minute** - For general monitoring
228- - ** 5 minutes** - For less time-sensitive data
229- - ** Manual only** - Disable auto-refresh
30+ - Scope: Environment, Project, Organization
31+ - Tasks
32+ - Queues
23033
231- Widgets use smart loading:
34+ ## Creating custom metrics dashboards
23235
233- - Only fetch when visible on screen
234- - Pause updates when tab is not active
235- - Debounce rapid filter changes
36+ 1 . In the sidebar click the + icon next to "Metrics".
37+ 2 . Name your custom dashboard.
38+ 3 . From the top-right you can "Add chart" or "Add title".
39+ 4 . For charts you write [ TRQL queries] ( /insights/query ) and choose a visualization type.
40+ 5 . You can resize and reposition widgets on your dashboards.
23641
23742## Performance considerations
23843
@@ -241,114 +46,28 @@ Widgets use smart loading:
241461 . ** Use time bucketing** - ` timeBucket() ` automatically groups by appropriate intervals
242472 . ** Limit result size** - Add ` LIMIT ` clauses, especially for table widgets
243483 . ** Use approximate functions** - ` uniq() ` instead of ` uniqExact() ` for faster approximate counts
244- 4 . ** Index-friendly filters** - Filter on ` created_at ` , ` status ` , ` task_identifier ` for best performance
245- 5 . ** Avoid expensive operations** - Be cautious with ` DISTINCT ` , complex ` JOIN ` s, or nested subqueries
246-
247- ### Good metric query
248-
249- ``` sql
250- -- Fast: Uses indexes and time bucketing
251- SELECT
252- timeBucket() AS time ,
253- count () AS runs
254- FROM runs
255- WHERE created_at > now() - INTERVAL 7 DAY
256- GROUP BY time
257- ORDER BY time ASC
258- ```
259-
260- ### Problematic metric query
261-
262- ``` sql
263- -- Slow: No time filter, expensive DISTINCT, no LIMIT
264- SELECT DISTINCT
265- task_identifier,
266- run_id,
267- (SELECT count () FROM runs r2 WHERE r2 .task_identifier = runs .task_identifier ) AS task_total
268- FROM runs
269- ```
270-
271- ## Sharing dashboards
272-
273- Dashboards are scoped to:
274-
275- - ** Environment** - Each environment has its own dashboards
276- - ** Project** - Share dashboard templates across environments (coming soon)
277- - ** Organization** - Organization-wide dashboard templates (coming soon)
27849
27950## Exporting metric data
28051
28152Export data from any metric widget :
28253
283541 . Click the widget menu (three dots)
284- 2 . Select "Export"
285- 3 . Choose format: JSON or CSV
286- 4 . Data exports include current filter state
287-
288- Or export programmatically via the SDK:
289-
290- ``` typescript
291- import { query } from " @trigger.dev/sdk" ;
292-
293- const result = await query .execute (" SELECT status, count() FROM runs GROUP BY status" , {
294- period: " 7d" ,
295- format: " csv" , // Export as CSV
296- });
297-
298- // Save to file
299- await fs .writeFile (" metrics.csv" , result .results );
300- ```
301-
302- ## Metric templates
303-
304- Common metric templates to get started:
305-
306- ### System health dashboard
307-
308- - Total runs today (single value)
309- - Success rate over time (line chart)
310- - Error rate by task (bar chart)
311- - Recent failures (table)
312- - Average duration by task (table)
313-
314- ### Cost monitoring dashboard
315-
316- - Total compute cost today (single value)
317- - Cost over time (area chart)
318- - Cost per task (bar chart)
319- - Most expensive runs (table)
320-
321- ### Performance dashboard
322-
323- - P50, P95, P99 latencies (single values)
324- - Duration distribution (histogram/bar chart)
325- - Duration over time by task (line chart)
326- - Slowest runs (table)
327-
328- ### Queue monitoring dashboard
329-
330- - Queued runs by queue (single values)
331- - Queue depth over time (area chart)
332- - Processing rate (line chart)
333- - Oldest queued run age (single value)
55+ 2 . Select "Copy JSON" or "Copy CSV"
33456
33557## Best practices
33658
337591 . ** Start simple** - Begin with basic metrics and iterate based on insights
338602 . ** Use meaningful names** - Give widgets clear, descriptive titles
339613 . ** Group related metrics** - Organize dashboards by theme (performance, costs, errors)
340- 4 . ** Set appropriate refresh rates** - Balance freshness with query cost
341- 5 . ** Test queries first** - Use the Query page to develop and test before adding to dashboards
342- 6 . ** Include context** - Add time ranges and filters to metric titles for clarity
343- 7 . ** Monitor query performance** - Check execution times and adjust queries that are too slow
62+ 4 . ** Test queries first** - Use the Query page to develop and test before adding to dashboards
34463
34564## Troubleshooting
34665
34766### Widget shows "No data"
34867
34968- Check that your query returns results in the Query page
35069- Verify time filters include the period with data
351- - Ensure task/queue/tag filters match existing runs
70+ - Ensure task/queue filters match existing runs
35271
35372### Widget is slow to load
35473
@@ -364,12 +83,14 @@ Common metric templates to get started:
36483- Ensure ` timeBucket() ` is used for time-series charts
36584- Review that series columns exist in query results
36685
367- ## Rate limits
86+ ## Limits
87+
88+ Metrics is powered by Query so have [ the same limits] ( /insights/query#limits ) as Query.
36889
369- Metric widgets share the same rate limits as Query API:
90+ There is a separate concurrency limits for metric widgets.
37091
371- - Concurrent queries per organization
372- - Query execution time limits
373- - Auto-refresh respects rate limits (pauses if limit reached)
92+ | Limit | Details |
93+ | :------------------------ | :------------- |
94+ | Concurrent widget queries | 30 per project |
37495
37596See [ Limits] ( /limits ) for details.
0 commit comments