DQL Fundamentals
DQL (Dynatrace Query Language) is the single query language for all data in Grail. Every dashboard tile, every alert, every notebook section uses DQL.
The Pipeline Pattern
Every DQL query is a pipeline โ data flows through commands connected by | (pipe):
fetch logs // 1. Load data
| filter loglevel == "ERROR" // 2. Keep only errors
| fields timestamp, content // 3. Select columns
| sort timestamp desc // 4. Order results
| limit 10 // 5. Limit output
Essential Commands
Command What It Does Example
โโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ
fetch Load data from Grail fetch logs
timeseries Load metrics as time series timeseries avg(dt.host.cpu.usage)
filter Keep rows matching condition filter loglevel == "ERROR"
filterOut Remove rows matching condition filterOut loglevel == "NONE"
fields Select specific columns fields timestamp, content
fieldsAdd Add computed columns fieldsAdd duration_ms = duration / 1000
sort Order results sort timestamp desc
limit Limit number of results limit 20
summarize Group and aggregate summarize count(), by:{loglevel}
dedup Remove duplicates dedup entity.name
parse Extract fields from text parse content, "JSON:log"
expand Flatten arrays into rows expand tags
describe Show schema of a data object describe dt.entity.host
Aggregation Functions
Function What It Calculates Example
โโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ
count() Number of records summarize cnt=count()
avg() Average value summarize avg(duration)
sum() Total summarize sum(bytes)
min() / max() Minimum / maximum summarize max(cpu)
percentile() Percentile value summarize p95=percentile(rt, 95)
countIf() Conditional count summarize errors=countIf(status >= 400)
โ ๏ธ You MUST alias aggregations before sorting: summarize cnt=count() | sort cnt desc. Writing sort count() desc directly will fail.
Hands-On: Try These Queries
// Count logs by level
fetch logs
| summarize cnt=count(), by:{loglevel}
| sort cnt desc
// Host CPU over time
timeseries avg(dt.host.cpu.usage), by:{dt.entity.host}
// Services with their type
fetch dt.entity.service
| fields entity.name, serviceType
// Errors in the last hour
fetch logs, from:now()-1h
| filter loglevel == "ERROR"
| summarize cnt=count()
๐ Try it: Open a Notebook โ paste each query in a separate DQL section โ run them. timeseries queries render as charts, fetch queries render as tables.
Key Rules
- Strings use double quotes โ
"ERROR"not'ERROR'(single quotes are not supported) - Sort BEFORE fields โ
sortneeds the column to exist,fieldsdrops columns - timeseries is a starting command โ for metrics only, not for logs/events
- makeTimeseries is a pipe command โ creates time series from fetched data (logs, events)
- describe shows all available fields for any data object
- Named parameters required โ
substring(content, from:0, to:100)notsubstring(content, 0, 100). Same forif(x > 10, then:"high", else:"low") - Backticks for special field names โ
`error-code`for fields with hyphens or special characters - array() for multi-value filters โ
filter in(loglevel, array("ERROR", "WARN", "SEVERE")) - Expand uses brackets โ after
expand arr, access fields viaarr[field]NOTarr.field