Skip to content

Commit dcd9c90

Browse files
committed
Metrics docs improved
1 parent c661a9d commit dcd9c90

File tree

3 files changed

+44
-313
lines changed

3 files changed

+44
-313
lines changed

docs/images/metrics-built-in.png

711 KB
Loading

docs/insights/metrics.mdx

Lines changed: 26 additions & 305 deletions
Original file line numberDiff line numberDiff line change
@@ -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:
24146
1. **Use time bucketing** - `timeBucket()` automatically groups by appropriate intervals
24247
2. **Limit result size** - Add `LIMIT` clauses, especially for table widgets
24348
3. **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

28152
Export data from any metric widget:
28253

28354
1. 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

33759
1. **Start simple** - Begin with basic metrics and iterate based on insights
33860
2. **Use meaningful names** - Give widgets clear, descriptive titles
33961
3. **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

37596
See [Limits](/limits) for details.

0 commit comments

Comments
 (0)