DQL โ The One Language to Learn
DQL (Dynatrace Query Language) is the single replacement for metric expressions, USQL, entity selectors, and the Data Explorer. Learning DQL is the prerequisite for every migration step that follows.
๐ Try it now: Open your Dynatrace environment โ press Ctrl+K โ type "Notebooks" โ open a new Notebook. This is where you'll write DQL.
The Pipeline Pattern
Every DQL query follows the same pattern โ a pipeline of commands connected with | (pipe):
Two Starting Commands
Every query starts with one of two commands:
fetch โ rows of data (logs, events, entities, spans, problems)
timeseries โ metrics over time (for charts)
Your First Queries
Open a Notebook and try these one by one:
1. See your hosts
fetch dt.entity.host
| fields entity.name, osType, cpuCores
| limit 10
๐ Try it: Paste this into a Notebook DQL section. You should see your hosts with their OS and CPU count.
2. Check your logs
fetch logs, from:now() - 1h
| filter loglevel == "ERROR"
| fields timestamp, content, dt.process.name
| sort timestamp desc
| limit 20
3. See CPU over time (chart)
timeseries avg(dt.host.cpu.usage), by:{dt.entity.host}
๐ก In Notebooks, timeseries queries automatically render as line charts. fetch queries render as tables. You can change the visualization type in the UI.
4. Count problems by category
fetch dt.davis.problems, from:now() - 7d
| filter not(dt.davis.is_duplicate) and event.status == "ACTIVE"
| summarize problem_count = count(), by:{event.category}
| sort problem_count desc
Common Gotchas
โ ๏ธ These will bite you. Memorize them:
WRONG RIGHT
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
filter log.level == "ERROR" filter loglevel == "ERROR"
(no dot โ it's loglevel) โ
sort count() desc summarize cnt=count() | sort cnt desc
(must alias aggregations) โ
fields name, id | sort name sort name | fields name, id
(sort BEFORE fields!) โ
filter status in ["A","B"] filter in(status, "A", "B")
(no bracket syntax) โ
fetch metrics timeseries avg(dt.host.cpu.usage)
(no "fetch metrics") โ
What You Can Query
Data Object What's In It Example Query Start
โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ
dt.entity.host Hosts fetch dt.entity.host
dt.entity.service Services fetch dt.entity.service
logs Application & system logs fetch logs
events Davis events fetch events
dt.davis.problems Davis problems fetch dt.davis.problems
spans Distributed traces fetch spans
bizevents Business events fetch bizevents
dt.system.events Billing & usage fetch dt.system.events
user.sessions RUM sessions fetch user.sessions
user.events RUM events fetch user.events
๐ก Discovery trick: Run describe dt.entity.host in a Notebook to see ALL available fields for any data object. This is how you explore the schema.
๐ก Davis CoPilot: In a Notebook, add a Prompt section and ask in plain English: "Show me error logs from the last hour grouped by service". CoPilot generates and runs the DQL for you โ great for learning the syntax.
Advanced Commands (Power User)
Command What It Does Example
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
lookup Enrich data from another table lookup [load dt.entity.host], sourceField:id, lookupField:id
join Correlate two data sources join [fetch logs], on:{dt.entity.host}
append Combine results from two queries append [fetch dt.entity.service]
makeTimeseries Create time chart from non-metric data makeTimeseries count(), by:{loglevel}, interval:15m
expand Flatten arrays into rows expand tags
Lookup: Enrich with Context
// Add host names to log records
fetch logs, from:now() - 1h
| lookup [fetch dt.entity.host | fields id, entity.name], sourceField:dt.entity.host, lookupField:id, prefix:"host."
| fields timestamp, host.entity.name, content
๐ก Lookup tables: Dynatrace now supports uploading CSV files as lookup tables in Grail. Use load to query them โ perfect for enriching data with business context (cost centers, team owners, SLA tiers).
makeTimeseries: Charts from Any Data
// Error rate chart from logs (not metrics!)
fetch logs, from:now() - 2h
| makeTimeseries count(), by:{loglevel}, interval:15m
โ ๏ธ makeTimeseries works on fetched data (logs, events, spans). timeseries works on metrics. Don't confuse them โ timeseries is a starting command, makeTimeseries is a pipe command.
โ ๏ธ Named parameters required โ many DQL functions need named params, not positional:
WRONG: substring(content, 0, 100) RIGHT: substring(content, from:0, to:100)
WRONG: if(x > 10, "high", "low") RIGHT: if(x > 10, then:"high", else:"low")
๐ก HTTP error rates: status == "ERROR" is unreliable for HTTP services. Use countIf(http.response.status_code >= 500) instead.