Homeโ€บ๐Ÿ” Phase 1: Learn DQLโ€บModule 52 min read ยท 6/21

Migrate Metric Expressions โ†’ timeseries

Hands-on

Metrics in Gen3: timeseries

In Gen2, you used metric expressions like builtin:host.cpu.usage:avg:splitBy("dt.entity.host"). In Gen3, you use the timeseries command.

builtin:host.cpu.usage:avg:splitBy("dt.entity.host") Gen2 metric expression โ†’ timeseries avg(dt.host.cpu.usage), by:{dt.entity.host} Gen3 DQL timeseries

Basic Patterns

// Single metric
timeseries avg(dt.host.cpu.usage), by:{dt.entity.host}

// Multiple metrics together
timeseries {
  cpu = avg(dt.host.cpu.usage),
  memory = avg(dt.host.memory.usage),
  disk = avg(dt.host.disk.used.percent)
}, by:{dt.entity.host}

// With time range
timeseries avg(dt.host.cpu.usage), by:{dt.entity.host}, from:now()-2h

๐Ÿ›  Try it: Open a Notebook โ†’ add DQL section โ†’ paste the multi-metric query above. You'll get a chart with CPU, memory, and disk on the same timeline.

Key Metric Names

Gen2 Metric Key                         Gen3 Metric Key
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
builtin:host.cpu.usage                  dt.host.cpu.usage
builtin:host.mem.usage                  dt.host.memory.usage
builtin:host.disk.used                  dt.host.disk.used.percent
builtin:service.response.time           dt.service.request.response_time
builtin:service.requestCount.total      dt.service.request.count
builtin:service.errors.total.count      dt.service.request.failure_count

โš ๏ธ dt.service.request.response_time is in microseconds, not milliseconds. Divide by 1000 for ms.

Aggregation Functions

avg()          โ€” average
sum()          โ€” total
min() / max()  โ€” extremes
percentile(metric, 95)  โ€” P95 (great for response time)
count()        โ€” number of data points

Post-Processing Timeseries Results

timeseries cpu = avg(dt.host.cpu.usage), by:{dt.entity.host}
| fieldsAdd avg_cpu = arrayAvg(cpu), max_cpu = arrayMax(cpu)
| filter avg_cpu > 50

๐Ÿ’ก Timeseries results are arrays. Use arrayAvg(), arrayMax(), arraySum() to aggregate them into single values for filtering or sorting.

Metric Discovery

// Find all metrics containing "cpu"
timeseries avg(dt.host.cpu.usage)
// Then try: dt.host.cpu.idle, dt.host.cpu.system, dt.host.cpu.user

๐Ÿ›  Try it: In a Notebook, start typing timeseries avg(dt.host. โ€” the autocomplete will show you all available host metrics.

Advanced Timeseries Parameters

The timeseries command has powerful parameters beyond the basics:

Parameter    What It Does                              Example
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
filter:{}    Filter entities INSIDE the command         filter:{dt.entity.host == "HOST-123"}
shift:       Compare with a past period                 shift:-7d (overlay last week)
default:     Replace null values                        default:0 (no gaps in charts)
nonempty:    Return results even when no data matches   nonempty:true
scalar:      Collapse array to single value              scalar:true (for tables)
union:       Include entities with no data               union:true
interval:    Time bucket size                            interval:1h, interval:5m
// Week-over-week comparison with shift
timeseries current = avg(dt.host.cpu.usage),
  previous = avg(dt.host.cpu.usage, shift:-7d),
  by:{dt.entity.host}

// Scalar for table output (single value per entity)
timeseries usage = avg(dt.host.cpu.usage, scalar:true), by:{dt.entity.host}
| sort usage desc
| limit 5

๐Ÿ’ก filter:{} inside timeseries is more performant than | filter after the pipe โ€” it filters at the data source level. Use it for entity filtering.

๐Ÿ”ง Migration Step: Convert Your Metric Expressions

For each Gen2 metric expression in your dashboards and alerts, convert using this pattern:

Gen2 Metric Expression                              Gen3 DQL Timeseries
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
builtin:host.cpu.usage:avg                          timeseries avg(dt.host.cpu.usage)
builtin:host.cpu.usage:avg:splitBy("dt.entity.host") timeseries avg(dt.host.cpu.usage), by:{dt.entity.host}
builtin:service.response.time:percentile(95)        timeseries percentile(dt.service.request.response_time, 95)
builtin:host.mem.usage:max:splitBy():sort(value,    timeseries m=max(dt.host.memory.usage, scalar:true),
  descending):limit(5)                                by:{dt.entity.host} | sort m desc | limit 5
(metricA - metricB) / metricA * 100                 Use built-in SLO templates (arithmetic fails in SLIs)

๐Ÿ›  Migration shortcut: Open a Notebook โ†’ add a DQL section โ†’ start typing timeseries avg(dt.host. โ€” autocomplete shows all available metrics. You don't need to memorize the new metric names.