Homeโ€บ๐Ÿ” DQL & Data Accessโ€บModule 51 min read ยท 6/21

Metrics: Expressions โ†’ Timeseries

Hands-on3 exercises

Metric Expressions โ†’ DQL Timeseries

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

Side-by-Side Comparison

GEN2 Metric Expression                  GEN3 DQL Timeseries
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
builtin:host.cpu.usage                  timeseries avg(dt.host.cpu.usage)
  :avg                                    avg() is the aggregation
  :splitBy("dt.entity.host")              by: {dt.entity.host}
  :fold(avg)                              (use arrayAvg() after)
  :filter(eq("tag","prod"))               | filter ... (before timeseries)
  :names                                  | fieldsAdd name = getNodeName(...)
  :limit(10)                              | limit 10

Common Metric Migrations

// GEN2: builtin:host.cpu.usage:avg:splitBy("dt.entity.host")
// GEN3:
timeseries cpu = avg(dt.host.cpu.usage), by:{dt.entity.host}

// GEN2: builtin:service.response.time:percentile(95):splitBy("dt.entity.service")
// GEN3:
timeseries p95 = percentile(dt.service.request.response_time, 95),
  by:{dt.service.name}

// GEN2: builtin:host.disk.usedPct:max:splitBy("dt.entity.host")
// GEN3:
timeseries disk = max(dt.host.disk.used.percent), by:{dt.entity.host}

// GEN2: builtin:service.errors.total.count:avg:splitBy("dt.entity.service")
// GEN3:
timeseries errors = sum(dt.service.request.failure_count),
  by:{dt.service.name}
๐Ÿ›  Try it

Convert this Gen2 metric expression to Gen3 DQL: builtin:host.cpu.usage:avg:splitBy("dt.entity.host")

extension.yamlYAML
Loading...

Multiple Metrics in One Query

Gen3 lets you query multiple metrics together โ€” something Gen2 couldn't do easily:

timeseries {
  cpu = avg(dt.host.cpu.usage),
  memory = avg(dt.host.memory.usage),
  disk = avg(dt.host.disk.used.percent)
}, by:{dt.entity.host}
| fieldsAdd avg_cpu = arrayAvg(cpu), avg_mem = arrayAvg(memory)
| filter avg_cpu > 80 or avg_mem > 80

Metric Discovery

Don't know the metric key? Search for it:

fetch metric.series, from:now() - 1h
| filter contains(metric.key, "cpu")
| summarize count(), by:{metric.key}
| sort `count()` desc

Key Metric Name Changes

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.usedPct              dt.host.disk.used.percent
builtin:service.response.time           dt.service.request.response_time
builtin:service.errors.total.count      dt.service.request.failure_count
builtin:service.requestCount.total      dt.service.request.count

Note: Response time in Gen3 is in microseconds, not milliseconds. Divide by 1000 for ms.