Agent skill

Dt Dql Essentials

by Dynatrace in Dynatrace/dynatrace-for-ai

Core DQL syntax, pitfalls, query patterns, and query optimization.

Apache-2.0Auto-check passedDatabases

Install Dt Dql Essentials

skills CLI
$ npx skills add Dynatrace/dynatrace-for-ai --skill dt-dql-essentials -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install Dynatrace/dynatrace-for-ai dt-dql-essentials --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/Dynatrace/dynatrace-for-ai.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/dt-dql-essentials .claude/skills/dt-dql-essentials && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
dt-dql-essentials
GitHub stars
161
Token cost
~9.3k tokens
SKILL.md length
3,122 words
Files
34 (incl. references)
Skills in repo
33
Repo updated
First seen
Licence
Apache-2.0

At a glance

Core DQL syntax, pitfalls, query patterns, and query optimization.

  • Explain an existing query
  • SKILL.md covers When to Load References, DQL Reference Index, Syntax Pitfalls and Fetch Command → Data Model, plus 11 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • Answer product questions

What it does

Dt Dql Essentials is an agent skill from Dynatrace/dynatrace-for-ai. Core DQL syntax, pitfalls, query patterns, and query optimization. Load to write, build, fix, or OPTIMIZE a DQL query — prevents syntax errors and makes queries faster, more efficient, and cheaper (less data scanned = lower query consumption/cost per run). Covers fetch commands, data models, field namespaces, time alignment, entity/smartscape patterns, metric discovery, and performance/cost optimization (filter early, bucket filters, short time ranges, field selection, sampling, cardinality). Trigger…

Its SKILL.md is about 9.3k tokens, which your agent loads only when the skill is triggered. The skill folder holds 35 other files, including reference files (for example `references/discovery.md`, `references/dql/dql-commands.md` and `references/dql/dql-data-types.md`).

It sits in Databases, covering Query optimization. The repository describes itself as: Skills, prompts, and instructions for building AI agents on top of Dynatrace production context. The licence is Apache-2.0.

When your agent uses it

  • Explain an existing query
  • Answer product questions

Example prompts

  • “write/build/fix a DQL query”
  • “DQL syntax”
  • “query logs/spans/metrics”
  • “/dt-dql-essentials”

What it can do on your machine

Read from SKILL.md and the folder at commit 4f9aa71. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are dql and dql-snippet).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Dt Dql Essentials loads about 9.3k tokens when it runs, and up to ~57k if it reads all its reference files. Until then it costs about 250 tokens; SKILL.md has 3,122 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~250
When it runs · the whole SKILL.md, loaded when a task matches
~9.3k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~57k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from Dynatrace/dynatrace-for-ai at commit 4f9aa71, republished under its Apache-2.0 licence (© Dynatrace). 3,122 words, ~9,262 tokens.

Download SKILL.mdSave it as .claude/skills/dt-dql-essentials/SKILL.md (or your agent's skills folder). This skill also uses 33 other files; get the full folder from GitHub.
name
dt-dql-essentials
description
Core DQL syntax, pitfalls, query patterns, and query optimization. Load to write, build, fix, or OPTIMIZE a DQL query — prevents syntax errors and makes queries faster, more efficient, and cheaper (less data scanned = lower query consumption/cost per run). Covers fetch commands, data models, field namespaces, time alignment, entity/smartscape patterns, metric discovery, and performance/cost optimization (filter early, bucket filters, short time ranges, field selection, sampling, cardinality). Trigger: "write/build/fix a DQL query", "DQL syntax", "query logs/spans/metrics", "create a timeseries", "optimize my DQL", "make my query faster/cheaper", "reduce DQL cost/consumption/scanned data", "keep DQL cost under control". Do NOT use to explain an existing query or answer product questions. For MONITORING a tenant's ACTUAL query consumption/billing (how much queries cost, who scanned most, cost trends) use dt-platform-costs — this tunes the query text, not billing data.
license
Apache-2.0

DQL Essentials Skill

DQL is a pipeline-based query language. Queries chain commands with | to filter, transform, and aggregate data. DQL has unique syntax that differs from SQL — load this skill before writing any DQL query.


When to Load References

Before working on specific tasks, load the relevant reference:

TaskRequired Reading
Discovering datareferences/discovery.md
Field names, namespaces, data models, stability levels, query patternsreferences/semantic-dictionary.md
Query optimization — make a query faster / more efficient / cheaper, reduce consumption & scanned data (filter early, bucket filters, time ranges, field selection, sampling, cardinality)references/optimization.md
Smartscape topology navigation for discovering relationships between entitiesreferences/smartscape-topology-navigation.md
summarize and makeTimeseries patterns (bucketing, calendar months)references/summarization.md
Array and timeseries manipulation (arrayFilter, collectArray, iterative)references/iterative-expressions.md
Conditional logic (if/else chains), coalesce, string/date helpersreferences/useful-expressions.md
in operator (subquery), full @ time alignment unit tablereferences/operators.md
matchesValue, matchesPhrase, matchesPattern, in() — string pattern matching, regex, array matching, wildcards, case sensitivityreferences/string-matching.md

DQL Reference Index

Use this index to route from a function group (e.g. time functions, conversions) to its detailed spec, or from a function name to its spec file.

DescriptionItems
Data Typesarray, binary, boolean, double, duration, long, record, string, timeframe, timestamp, uid
Parameter Value Typesbucket, dataObject, dplPattern, entityAttribute, entitySelector, entityType, enum, executionBlock, expressionTimeseriesAggregation, expressionWithConstantValue, expressionWithFieldAccess, fieldPattern, filePattern, identifierForAnyField, identifierForEdgeType, identifierForFieldOnRootLevel, identifierForNodeType, joinCondition, jsonPath, metricKey, metricTimeseriesAggregation, namelessDplPattern, nonEmptyExecutionBlock, prefix, primitiveValue, simpleIdentifier, tabularFileExisting, tabularFileNew, url
Commandsappend, data, dedup, describe, expand, fetch, fields, fieldsAdd, fieldsFlatten, fieldsKeep, fieldsRemove, fieldsRename, fieldsSnapshot, fieldsSummary, filter, filterOut, join, joinNested, limit, load, lookup, makeTimeseries, metrics, parse, search, smartscapeEdges, smartscapeNodes, sort, summarize, timeseries, traverse
Functions — Aggregationavg, collectArray, collectDistinct, correlation, count, countDistinct, countDistinctApprox, countDistinctExact, countIf, max, median, min, percentRank, percentile, percentileFromSamples, percentiles, stddev, sum, takeAny, takeFirst, takeLast, takeMax, takeMin, variance
Functions — ArrayarrayAvg, arrayConcat, arrayCumulativeSum, arrayDelta, arrayDiff, arrayDistinct, arrayFirst, arrayFlatten, arrayIndexOf, arrayLast, arrayLastIndexOf, arrayMax, arrayMedian, arrayMin, arrayMovingAvg, arrayMovingMax, arrayMovingMin, arrayMovingSum, arrayPercentile, arrayRemoveNulls, arrayReverse, arraySize, arraySlice, arraySort, arraySum, arrayToString, vectorCosineDistance, vectorInnerProductDistance, vectorL1Distance, vectorL2Distance
Functions — BitwisebitwiseAnd, bitwiseCountOnes, bitwiseNot, bitwiseOr, bitwiseShiftLeft, bitwiseShiftRight, bitwiseXor
Functions — Booleanexists, in, isFalseOrNull, isNotNull, isNull, isTrueOrNull, isUid128, isUid64, isUuid
Functions — CastasArray, asBinary, asBoolean, asDouble, asDuration, asIp, asLong, asNumber, asRecord, asSmartscapeId, asString, asTimeframe, asTimestamp, asUid
Functions — Constante, pi
Functions — ConversiontoArray, toBoolean, toDouble, toDuration, toIp, toLong, toSmartscapeId, toString, toTimeframe, toTimestamp, toUid, toVariant
Functions — Createarray, duration, ip, record, smartscapeId, timeframe, timestamp, timestampFromUnixMillis, timestampFromUnixNanos, timestampFromUnixSeconds, uid128, uid64, uuid
Functions — CryptographichashCrc32, hashMd5, hashSha1, hashSha256, hashSha512, hashXxHash32, hashXxHash64
Functions — EntitiesclassicEntitySelector, entityAttr, entityName
Functions — Time series aggregation for expressionsavg, count, countDistinct, countDistinctApprox, countDistinctExact, countIf, end, max, median, min, percentRank, percentile, percentileFromSamples, start, sum
Functions — Flowcoalesce, if
Functions — GeneraljsonField, jsonPath, lookup, parse, parseAll, type
Functions — GetarrayElement, getEnd, getHighBits, getLowBits, getStart
Functions — IterativeiAny, iCollectArray, iIndex
Functions — Mathematicalabs, acos, asin, atan, atan2, bin, cbrt, ceil, cos, cosh, degreeToRadian, exp, floor, hexStringToNumber, hypotenuse, log, log10, log1p, numberToHexString, power, radianToDegree, random, range, round, signum, sin, sinh, sqrt, tan, tanh
Functions — NetworkipIn, ipIsLinkLocal, ipIsLoopback, ipIsPrivate, ipIsPublic, ipMask, isIp, isIpV4, isIpV6
Functions — SmartscapegetNodeField, getNodeName
Functions — Stringconcat, contains, decodeBase16ToBinary, decodeBase16ToString, decodeBase64ToBinary, decodeBase64ToString, decodeUrl, encodeBase16, encodeBase64, encodeUrl, endsWith, escape, getCharacter, indexOf, lastIndexOf, levenshteinDistance, like, lower, matchesPattern, matchesPhrase, matchesRegex, matchesValue, punctuation, replacePattern, replaceString, splitByPattern, splitString, startsWith, stringLength, substring, trim, unescape, unescapeHtml, upper
Functions — TimeformatTimestamp, getDayOfMonth, getDayOfWeek, getDayOfYear, getHour, getMinute, getMonth, getSecond, getWeekOfYear, getYear, now, unixMillisFromTimestamp, unixNanosFromTimestamp, unixSecondsFromTimestamp
Functions — Time series aggregation for metricsavg, count, countDistinct, end, max, median, min, percentRank, percentile, start, sum

Syntax Pitfalls

❌ Wrong✅ RightIssue
filter field in ["a", "b"]filter in(field, {"a", "b"})[ and ] wrap sub-queries in DQL but do not wrap static array literals. Use {} or array() for static values.
filter: { in(field, [sub-query]) } (e.g. in timeseries filter:)filter: { field in [sub-query] }in() does not accept execution blocks as arguments. When the right-hand side is a sub-query (execution block), use the in operator: field in [execution block].
by: severity, statusby: {severity, status}List of fields must be grouped by curly braces in by: clauses (summarize, makeTimeseries, etc.).
contains(toLowercase(field), "err")contains(field, "err", false)Don't wrap in lower() for case-insensitive matching. contains() has a built-in third positional caseSensitive parameter (default true).
filter name == "*serv*9*"filter matchesValue(name, "*serv*") and matchesValue(name, "*9*")== does not support wildcards. matchesValue() supports * wildcards but only at the beginning and/or end of the pattern—split mid-string wildcard intent into multiple calls combined with and.
matchesValue(field, "prod") on string fieldcontains(field, "prod")Without wildcards, matchesValue() performs an exact (case-insensitive) match — it will not find "production". Use contains() for substring matching (or matchesValue(field, "*prod*") for wildcard matching).
iAny(matchesValue(arr[], "x") OR matchesValue(arr[], "y"))matchesValue(arr, {"x", "y"})matchesValue accepts an array field in the first param and an array literal {} in the second — no iAny or [] needed. The same applies when consolidating multiple contains(f, x) OR contains(f, y) on the same field: use matchesValue(f, {"*x*", "*y*"}).
iAny(matchesPhrase(arr[], "phrase"))matchesPhrase(arr, "phrase")matchesPhrase iterates array fields natively — drop iAny( and []. Note: the second parameter must be a static string; matchesPhrase(f, array("a","b")[]) is a runtime error.
contains(field, "pip") on a short or common tokenmatchesPhrase(field, "pip")contains is a pure substring match — "pip" also fires on "pipenv", "gripping". matchesPhrase tokenizes the string and matches whole words only, giving fewer false positives.
iAny(in(lower(arr[]), array("a", "b")))matchesValue(arr, {"a", "b"}, caseSensitive: false)matchesValue is case-insensitive by default — no lower(), in(), or iAny wrapper needed. caseSensitive: false shown explicitly here only to mirror the intent of the lower() it replaces.
iAny(f1[] == "a" AND f2[] == "b") iterating two separate arraysin(f1, "a") AND in(f2, "b")Multi-array iAny is pairwise, not a cross-product: element i of f1[] is tested against element i of f2[]. If the arrays differ in length the result is null. Use independent in() checks instead. See references/iterative-expressions.md.
toLowercase(field)lower(field)The function is lower(), not toLowercase(). Only type-casting functions use the to prefix (toString(), toLong(), etc.).
arrayAvg(field[]) or arraySum(field[])arrayAvg(field) or field[]field[] = element-wise iterative expression (array→array); arrayAvg(field) = collapse to scalar (array→single value). Never mix both — arrayAvg(field[]) is semantically wrong.
my_field after lookup or joinlookup.my_field / right.my_fieldlookup prefixes added fields with lookup. by default (configurable via prefix:). join prefixes right-side fields with right..
substring(field, 0, 200)substring(field, from: 0, to: 200)The first parameter (expression) is positional, but from: and to: are named optional parameters and must include their names.
filter host = "A"filter host == "A"DQL uses == for equality comparison, not =. Single = is assignment (e.g., in fieldsAdd, summarize aliases).
fetch logs, from: toTimestamp('2026-01-01')fetch logs, from: -24hfrom: / to: accept duration literals (e.g., -24h, -7d) or now() expressions — not toTimestamp(). For absolute ranges use timeframe: "start/end" (ISO 8601).
filter log.level == "ERROR"filter loglevel == "ERROR"Log severity field is loglevel (no dot) — log.level does not exist.
sort count() descsort `count()` descFields with special characters (like parentheses) must be wrapped in backticks.
length(field)stringLength(field)DQL string length function is stringLength — there is no length().
metrics dt.host.cpu.usagetimeseries avg(dt.host.cpu.usage)metrics loads metric metadata, not values — use timeseries for data.
join [...], on:{left.a.b == right.a.b}join [...], on:{left[`a.b`] == right[`a.b`]}Dotted field names in join/lookup conditions require bracket notation with backticks.
fieldsSummary (no arguments)fieldsSummary field1, field2fieldsSummary requires at least one field parameter.
timeseries with percentile/median/percentRank — no resultsAdd rollup: avg (or min/max/sum) to the timeseries commandThese three functions require rollup: on gauge/count metrics — without it the query silently returns empty.
summarize p95 = percentile(duration, 95, rollup: avg)summarize p95 = percentile(duration, 95)rollup: is a timeseries-only parameter. The same-named aggregations in summarize over logs/spans/events reject it with UNKNOWN_PARAMETER_DEFINED. Only add rollup: when aggregating a metric inside timeseries.
filter array.contains(field, "v") or arrayContains(field, "v")filter in(field, {"v"})Neither function exists in DQL — both are hallucinated from Python/Java/SQL. in() already matches array-typed fields natively (e.g. k8s.namespace.name on dt.davis.problems): it returns true if any element of the needle matches any haystack element. See references/iterative-expressions.md.
filter k8s.namespace.name == "ns" where the field is array-typedfilter in(k8s.namespace.name, {"ns"})== against an array-typed field matches nothing — it returns zero rows with no error, which reads as "no data" rather than a mistake. k8s.* fields are arrays on dt.davis.problems. Use in() for exact membership, or matchesValue(field, {...}).
parseJson(field) or extractJsonField(field, jsonPath: "$.x")parse field, "JSON:parsed" then parsed[x]Neither function exists. JSON embedded in a string field is unpacked with the parse command and the JSON DPL matcher, then accessed with bracket notation.
filter hour(timestamp) == 4 / minute(timestamp)filter getHour(timestamp) == 4 / getMinute(timestamp)There are no hour()/minute() functions. The get* family returns numbers, so numeric comparison and ranges work. Do not substitute formatTimestamp(timestamp, format: "HH") — that returns a string, so == 4 silently matches nothing.
fields fromRelationships, toRelationships, containerImageTag on dt.entity.*describe dt.entity.<type> first, then select real fieldsClassic entity objects do not expose the Entities REST API's attribute names. Field names must be discovered with describe <dataObject>, not guessed from API payloads.
by: {bin(timestamp, 1h)} then sort `bin(timestamp,1h)`by: {t = bin(timestamp, 1h)} then sort tDQL normalizes the auto-generated group-key name to bin(timestamp, 1h) — with a space after the comma, regardless of how the expression was written. A backticked reference that omits the space raises FIELD_DOES_NOT_EXIST. Always alias group keys.
fetch spans | ... by: {bin(timestamp, 1h)}fetch spans | ... by: {t = bin(start_time, 1h)}spans has no timestamp field — its time fields are start_time and end_time. Referencing timestamp either errors or yields nulls depending on position.
lookup [...], fields: {`dotted.name`}lookup [...], fields: {dotted.name}Do not backtick field names inside the fields: parameter of lookup — causes PARSE_ERROR.
data record(key: "val")data record(key = "val")record() uses = for named fields, not : — : is for command parameters like rollup:.
getNodeField(dt.smartscape.host, "tags")["tag.key"]getNodeField(dt.smartscape.host, "tags")[tag.key]In this tag-map access pattern, bracket keys must use unquoted identifier syntax; quoted keys cause a parse error.
by: {dt.entity.host} or dt.entity.*by: {dt.smartscape.host} or dt.smartscape.*dt.entity.* is deprecated — always use dt.smartscape.* in new queries.

Fetch Command → Data Model

DQL queries start with fetch <data_object> or timeseries. There is no fetch dt.metric — metrics use timeseries.

Fetch CommandData ModelKey Fields / Notes
fetch spansDistributed tracingspan.*, service.*, http.*, db.*, code.*, exception.*
fetch logsLog eventslog.*, k8s.*, host.* — message body is content, severity is loglevel (NOT log.level)
fetch eventsDAVIS / infra eventsevent.*, dt.smartscape.*
fetch bizeventsBusiness eventsevent.*, custom fields
fetch security.eventsSecurity eventsvulnerability.*, event.*
fetch user.sessionsRUM sessionsdt.rum.*, browser.*, geo.*
fetch user.eventsRUM individual eventspage views, clicks, requests, errors
fetch user.replaysSession replay recordings
fetch application.snapshotsApplication snapshots
fetch dt.davis.eventsDavis-detected events
fetch dt.davis.problemsDavis-detected problems
timeseries avg(metric.key)MetricsNOT fetch — hyphenated keys need backticks: timeseries sum(`my.metric-name`)
smartscapeNodes "HOST"TopologyNOT fetch — types: HOST, SERVICE, K8S_CLUSTER, etc.

dt.entity.* is deprecated — use dt.smartscape.* and smartscapeNodes for new queries.

Discover all available data objects: fetch dt.system.data_objects | fields name, display_name, type

→ references/semantic-dictionary.md for full field namespaces


samplingRatio Parameter

fetch supports a samplingRatio: parameter to reduce the volume of data read — useful for improving query performance on large datasets.

dql
fetch spans, samplingRatio:100   // reads ~1% of data

Allowed values: depend on the concrete data object and range from 1, 10, 100, 1000, 10000 to 100000, the highest level only available for logs and spans.

Sampling is hierarchical for spans, user.events and user.sessions: a record included at a higher ratio (e.g. 100) is guaranteed to also appear at lower ratios (e.g. 10, 1), but not vice versa. This means results at different ratios are subsets of each other. All other non-metric data objects are sampled independently per record, so results at different ratios are not subsets.

The actual ratio applied is accessible via the dt.system.sampling_ratio field. Use it to extrapolate sampled counts back to true totals:

dql
fetch logs, samplingRatio:10
| summarize count_extrapolated = sum(dt.system.sampling_ratio)

Show full SKILL.md (1,259 more words)Show less

Timeseries Aggregation Functions

The timeseries command supports only these aggregation functions:

FunctionDescription
sumSum of metric data points per time slot
avgAverage of metric data points per time slot
minMinimum of metric data points per time slot
maxMaximum of metric data points per time slot
countCount of metric data points per time slot
percentile(metric, N)Nth percentile per time slot. Requires rollup: — see below.
median(metric)50th percentile per time slot (= percentile(metric, 50)). Requires rollup:.
percentRank(metric, value)Percentile rank of a value per time slot. Requires rollup:.
countDistinct(metric)Approximate distinct count per time slot (cardinality metrics only; does NOT accept rollup:).

Helpers (use alongside an aggregation): start(), end().

Not supported by timeseries: countIf, collectArray, stddev, variance, takeAny, takeFirst, takeLast — use summarize or makeTimeseries.

The rollup: parameter

Metrics are pre-aggregated at ingest time. rollup: controls how raw data points are combined per time slot. Required for percentile, median, percentRank — without it the query silently returns no results. avg/min/max/sum/count work without rollup:.

rollup: is a timeseries-only parameter — it belongs to metric aggregations and nothing else. The identically-named aggregation functions available in summarize over event data (logs, spans, events) do not accept it: summarize p95 = percentile(duration, 95, rollup: avg) fails with UNKNOWN_PARAMETER_DEFINED. In summarize, use percentile(field, N) with no rollup:.

Single aggregation — rollup: at command level. Multiple aggregations in {} — rollup: must go inside each function call (command-level rollup: causes UNKNOWN_PARAMETER_DEFINED):

dql
timeseries p90 = percentile(dt.process.handles.file_descriptors_percent_used, 90), rollup: avg
dql
timeseries {
  p90 = percentile(dt.process.handles.file_descriptors_percent_used, 90, rollup: avg),
  med = median(dt.process.handles.file_descriptors_percent_used, rollup: avg),
  avg_val = avg(dt.process.handles.file_descriptors_percent_used)
}, by: {dt.smartscape.host}

Values: avg (gauges), min, max, sum (counters), total.

Timeseries-to-scalar conversion

There are two ways to collapse a timeseries to a scalar. Prefer the scalar:true parameter when you only need the single aggregated value — it is more efficient because no array is materialized. Fall back to array functions when you need both the full series and a derived scalar in the same query.

Preferred: scalar:true on the aggregation function

Pass scalar:true to any timeseries aggregation function. The result field contains a single value instead of an array, and no intermediate array is allocated:

dql
timeseries avg_cpu = avg(dt.host.cpu.usage, scalar:true), by:{dt.smartscape.host}
dql
timeseries {
  avg_cpu = avg(dt.host.cpu.usage, scalar:true),
  max_cpu = max(dt.host.cpu.usage, scalar:true)
}, by:{dt.smartscape.host}

Fallback: array functions in fieldsAdd

When you need the full time series array alongside a derived scalar, use array functions in a subsequent | fieldsAdd:

FunctionDescription
arrayAvg(arr)Average of all values in the array
arraySum(arr)Sum of all values
arrayMin(arr)Minimum value
arrayMax(arr)Maximum value
arrayMedian(arr)Median value
arrayPercentile(arr, N)Nth percentile (0–100)
arrayLast(arr)Last non-null value (latest data point)
arrayFirst(arr)First non-null value (earliest data point)
dql
timeseries cpu = avg(dt.host.cpu.usage), by:{dt.smartscape.host}
| fieldsAdd avg_cpu = arrayAvg(cpu), max_cpu = arrayMax(cpu)

Time Alignment (@-operator)

The @ operator aligns timestamps to a boundary — agents often get this wrong.

ExpressionMeaning
now()@hCurrent time, aligned to the hour boundary
now()@dMidnight today
now()@w1Monday this week
now()-2h@h2 hours ago, aligned to the hour (offset first, then align)

Rules:

  • Order: offset before alignment — now()-2h@h, not now()@h-2h
  • No space between @ and the unit — now()@h not now() @h
  • m = minutes, M = months — do not confuse them

→ references/dql/dql-functions-timeseries.md for the full list of timeseries aggregations and rollup: rules → references/dql/dql-functions-array.md for arrayAvg / arrayMax / arrayPercentile / … spec


Entity & Smartscape Patterns

Entity fields are scoped per type — entity.id does not exist. Use smartscapeNodes for topology queries.

EntityID field in datasmartscapeNodes type
Hostdt.smartscape.host"HOST"
Servicedt.smartscape.service"SERVICE"
Processdt.smartscape.process"PROCESS"
K8s clusterdt.smartscape.k8s_cluster"K8S_CLUSTER"

Use toSmartscapeId() for ID conversion from strings (required!).

→ references/smartscape-topology-navigation.md


makeTimeseries Command

makeTimeseries builds a time-bucketed series from event data (logs, spans, bizevents). Unlike timeseries (which queries pre-ingested metrics), makeTimeseries aggregates data in a pipeline.

Do not pipe timeseries directly into makeTimeseries — it fails with INVALID_IMPLICIT_TIME_DEFAULT. To re-aggregate metric data, use start() + expand (see references/summarization.md).

dql
fetch logs
| makeTimeseries
    total = count(),
    errors = countIf(loglevel == "ERROR"),
    interval: 5m,
    by: {k8s.cluster.name}
| fieldsAdd error_rate = errors[] * 100.0 / total[]

Key parameters: interval:, by:{}, from:/to:, bins:, time: (timestamp field), spread: (for count/countIf only), nonempty:.

→ references/summarization.md for full makeTimeseries patterns and summarize bucketing → references/iterative-expressions.md for timeseries array manipulation


String Matching Functions

DQL has four main functions for string and array pattern matching. See references/string-matching.md for the full guide and quick-reference table.

  • matchesValue(field, {"pattern*", "*other*"}) — wildcard matching (* at start/end). Accepts an array field in the first param and an array literal {} in the second — no iAny or [] needed. Case-insensitive by default (caseSensitive: true to enforce case-sensitive matching). Replaces contains() + iAny chains and lower() workarounds.
  • matchesPhrase(field, "token") — tokenizes the string and matches whole words, unlike contains() which is a bare substring match. First param accepts an array field natively; second param must be a static string (array unwrapping causes a runtime error).
  • in(field, array("a", "b")) — set membership. Both params accept arrays, making it an overlap/intersection check.

Chained Lookup Pattern

Each lookup command without a fields parameter removes all existing fields starting with the prefix (default: lookup.) before adding new ones. When chaining multiple lookups, use fields parameter or custom prefixes to preserve the result:

Option 1 (default): the desired fields are known.

dql
fetch bizevents
// Step 1: First lookup — enrich orders with product info
| lookup [fetch bizevents
    | filter event.type == "product_catalog"
    | fields product_id, category],
  sourceField: product_id, lookupField: product_id, fields: {product_id, product_category = category}

// Step 2: Second lookup — specify fields with a different name
| lookup [fetch bizevents
    | filter event.type == "warehouse_stock"
    | fields category, warehouse_region],
  sourceField: product_category, lookupField: category, fields: {warehouse_region, warehouse_category = category}

All 4 lookup fields product_id, product_category, warehouse_region, and warehouse_category are available. Without the fields:{...} parameter, the fields would be prefixed with lookup. and the second lookup command would delete the fields added by the first lookup.

Option 2: keep all fields from the lookup.

dql
fetch bizevents
// Step 1: First lookup — enrich orders with product info
| lookup [fetch bizevents
    | filter event.type == "product_catalog"
    | fields product_id, category],
  sourceField: product_id, lookupField: product_id, prefix: "product."

// Step 2: Second lookup — specify fields with a different prefix
| lookup [fetch bizevents
    | filter event.type == "warehouse_stock"
    | fields category, warehouse_region],
  sourceField: product_category, lookupField: category, prefix: "warehouse."

The new fields are: product.product_id, product.category, warehouse.category, warehouse.warehouse_region. All fields starting with product. or warehouse. are removed from the original source. Without the dedicated prefix, both lookup commands would use the same prefix (lookup.) and the second lookup drops the first lookup's results — producing empty fields.


makeTimeseries Command

makeTimeseries builds a time-bucketed series from event data (logs, spans, bizevents). Unlike timeseries (which queries pre-ingested metrics), makeTimeseries aggregates data in a pipeline.

Do not pipe timeseries directly into makeTimeseries — it fails with INVALID_IMPLICIT_TIME_DEFAULT. To re-aggregate metric data, use start() + expand (see references/summarization.md).

dql
fetch logs
| makeTimeseries
    {total = count(),
    errors = countIf(loglevel == "ERROR")},
    interval: 5m,
    by: {k8s.cluster.name}
| fieldsAdd error_rate = errors[] * 100.0 / total[]

Key parameters: interval:, by:{}, from:/to:, bins:, time: (timestamp field), spread: (for count/countIf only), nonempty:. → references/dql/dql-commands.md for full spec.

Entity existence timeline using spread::

dql
smartscapeNodes "HOST"
| makeTimeseries concurrently_existing_hosts = count(), spread: lifetime

→ references/iterative-expressions.md for timeseries array manipulation


Timeframe Specification

Access to data requires specification of a timeframe. It can be specified in the UI, as REST API parameters, or in a DQL query explicitly using a pair of parameters: from: and to: (if one is omitted it defaults to now()), or alternatively using a single timeframe: parameter. Timeframe can be expressed using absolute values or relative expressions vs. current time. The time alignment operator (@) can be used to round timestamps to time unit boundaries — see references/operators.md for full details.

Examples
dql-snippet
from:now()-1h@h, to:now()@h     // last complete hour
dql-snippet
from:now()-1d@d, to:now()@d     // yesterday complete
dql-snippet
from:now()@M                    // this month so far, till now
dql-snippet
from:now()-2h@h                 // go back 2 hours, then align to hour boundary

See references/operators.md for the full @ alignment-unit table (including m vs. M, week-day variants w1–w7, and factor rules like @3h).

Absolute timestamps

Use ISO 8601 format:

dql-snippet
from:"2024-01-15T08:00:00Z", to:"2024-01-15T09:00:00Z"

Modifying Time

Key concepts
  • DQL has 3 specialized types related to time:
    • timestamp — internally kept as number of nanoseconds since epoch, but exposed as date/time in a particular timezone
    • timeframe — a pair of 2 timestamps (start and end)
    • duration — internally kept as number of nanoseconds, but exposed as duration scaled to a reasonable factor (e.g. ms, minutes, days)
Rules
  • Subtracting timestamps yields a duration: timestamp - timestamp → duration
  • Duration divided by duration yields a double: e.g. 2h / 1m = 120.0
  • Scalar times duration yields a duration: e.g. no_of_h * 1h → duration
  • For extraction of time elements (hours, days of month, etc):
    • ✅ Use time functions. They support calendar and time zones properly including DST.
    • ❌ Avoid using formatTimestamp for extracting time components.
    • ❌ Avoid converting timestamps and durations to double/long and using division, modulo, and constants expressing time units as nanoseconds.

References

© Dynatrace, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 33 other files (references) in skills/dt-dql-essentials of Dynatrace/dynatrace-for-ai.

  • SKILL.md
  • references/discovery.md
  • references/dql/dql-commands.md
  • references/dql/dql-data-types.md
  • references/dql/dql-functions-aggregation.md
  • references/dql/dql-functions-array.md
  • references/dql/dql-functions-bitwise.md
  • references/dql/dql-functions-boolean.md
  • references/dql/dql-functions-cast.md
  • references/dql/dql-functions-constant.md
  • references/dql/dql-functions-conversion.md
  • references/dql/dql-functions-create.md
  • references/dql/dql-functions-cryptographic.md
  • references/dql/dql-functions-entities.md
  • references/dql/dql-functions-expression-timeseries.md
  • references/dql/dql-functions-flow.md
  • references/dql/dql-functions-general.md
  • references/dql/dql-functions-get.md
  • references/dql/dql-functions-iterative.md
  • … and 15 more

Open the folder on GitHubat commit 4f9aa71

Compare with similar skills

Dt Dql Essentials next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Dt Dql Essentials compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Dt Dql Essentials this skillDynatrace/dynatrace-for-ai161—~9.3kAutomated safety check: PassApache-2.0
SQL Optimization Patternsynulihao/AgentSkillOS61711 repos~3.3kAutomated safety check: PassNone
Cloud Trace Queryinggoogle/skills21k—~1.7kAutomated safety check: PassApache-2.0
Query Engine Designrevfactory/claude-code-harness120—~474Automated safety check: PassNone
Query Plan Snapshot CLIeclipse-rdf4j/rdf4j420—~1.5kAutomated safety check: PassBSD-3-Clause
Wp Acf And Content Modelingjorgerosal/wordpress-skills101—~3.2kAutomated safety check: PassMIT

Similar skills

  • SQL Optimization Patterns

    ynulihao/AgentSkillOS

    Master SQL query optimization, indexing strategies, and EXPLAIN analysis to dramatically improve database performance and eliminate slow queries.

    617 GitHub starsUsed in 11 repos~3.3k tokens
    DatabasesAuto-check passed
  • Official

    Query Cloud Trace spans, filter by latency thresholds or error status, correlate distributed traces with Cloud Logging, and diagnose latency bottlenecks across Google Cloud services.

    21k GitHub stars~1.7k tokensUpdated yesterday
    DatabasesAuto-check passed
  • Query Engine Design

    revfactory/claude-code-harness

    SQL query engine design and implementation guide. An agent skill from revfactory/claude-code-harness.

    120 GitHub stars~474 tokensUpdated 7 mo ago
    DatabasesAuto-check passed
  • Query Plan Snapshot CLI

    eclipse-rdf4j/rdf4j

    Use QueryPlanSnapshotCli to capture and compare RDF4J query plans, then assess likely performance improvements/regressions from execution verification and semantic plan diffs.

    420 GitHub stars~1.5k tokensUpdated yesterday
    DatabasesAuto-check passed
  • Wp Acf And Content Modeling

    jorgerosal/wordpress-skills

    WordPress ACF and content modeling review. An agent skill from jorgerosal/wordpress-skills.

    101 GitHub stars~3.2k tokensUpdated 4 mo ago
    DatabasesAuto-check passed
  • Jpa Patterns

    affaan-m/ECC

    JPA/Hibernate patterns for entity design, relationships, query optimization, transactions, auditing, indexing, pagination, and pooling in Spring Boot.

    275k GitHub starsUsed in 5 repos~1.2k tokens
    DatabasesAuto-check passed

More from Dynatrace/dynatrace-for-ai

All 33 skills in this repo
  • Dt Obs Analytics

    Dynatrace/dynatrace-for-ai

    Analyze dashboards and notebooks using Davis analyzers — anomaly detection, novelty scoring, and correlation.

    161 GitHub stars~3.9k tokensUpdated 7 days ago
    Auto-check passed
  • Dt Setup iOS

    Dynatrace/dynatrace-for-ai

    Set up the Dynatrace iOS SDK (OneAgent) in an iOS project using Swift Package Manager.

    161 GitHub stars~3.3k tokensUpdated 7 days ago
    Auto-check passed
  • Dt Alerting

    Dynatrace/dynatrace-for-ai

    End-to-end Dynatrace alerting lifecycle — anomaly detector setup and model selection (static threshold, adaptive baseline, seasonal baseline), alert event storage in Grail, problem grouping and…

    161 GitHub stars~3.3k tokensUpdated 7 days ago
    Auto-check passed
  • Dt Obs AWS

    Dynatrace/dynatrace-for-ai

    AWS cloud resource monitoring including EC2, RDS, Lambda, ECS/EKS, VPC networking, load balancers, S3, DynamoDB, SQS/SNS, and cost optimization.

    161 GitHub stars~4.2k tokensUpdated 7 days ago
    Auto-check passed
  • Dt Obs Ext Monitors

    Dynatrace/dynatrace-for-ai

    3rd-party test and monitor result ingestion into Dynatrace Grail via the platform events ingest API (platform/ingest/custom/events/).

    161 GitHub stars~1.5k tokensUpdated 7 days ago
    Auto-check passed
  • Dt Obs Problems

    Dynatrace/dynatrace-for-ai

    DAVIS problem analysis including root cause identification, impact assessment, and correlation with other telemetry.

    161 GitHub stars~4.6k tokensUpdated 7 days ago
    Auto-check passed

Categories

Questions about Dt Dql Essentials

What does Dt Dql Essentials do?

Core DQL syntax, pitfalls, query patterns, and query optimization. Dt Dql Essentials is an agent skill from Dynatrace/dynatrace-for-ai. Core DQL syntax, pitfalls, query patterns, and query optimization.

When should I use Dt Dql Essentials?

Dt Dql Essentials fits situations like: explain an existing query; answer product questions.

How do I install Dt Dql Essentials in Claude Code?

Run `npx skills add Dynatrace/dynatrace-for-ai --skill dt-dql-essentials -a claude-code`. Or copy the skill folder (skills/dt-dql-essentials in Dynatrace/dynatrace-for-ai) into .claude/skills/dt-dql-essentials in your project. Claude Code loads it when a task matches its description.

How do I install Dt Dql Essentials in Codex?

Run `npx skills add Dynatrace/dynatrace-for-ai --skill dt-dql-essentials -a codex`. Or copy the skill folder (skills/dt-dql-essentials in Dynatrace/dynatrace-for-ai) into .agents/skills/dt-dql-essentials in your project. Codex loads it when a task matches its description.

Can I use Dt Dql Essentials in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Dynatrace/dynatrace-for-ai --skill dt-dql-essentials -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/dt-dql-essentials, .gemini/skills/dt-dql-essentials, .github/skills/dt-dql-essentials and .opencode/skills/dt-dql-essentials in your project.

What does Dt Dql Essentials need to run?

SKILL.md names no scripts, command-line tools or credentials: Dt Dql Essentials is instructions for the agent only.

Does Dt Dql Essentials access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Dt Dql Essentials safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Dt Dql Essentials use?

Dt Dql Essentials is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Dt Dql Essentials use?

About 9.3k tokens (SKILL.md is roughly 37k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 48k tokens, read only when the agent opens those files.

What are the alternatives to Dt Dql Essentials?

Skills that share tags, products or a category with Dt Dql Essentials: SQL Optimization Patterns (ynulihao/AgentSkillOS, 617 stars), Cloud Trace Querying (google/skills, 21k stars), Query Engine Design (revfactory/claude-code-harness, 120 stars) and Query Plan Snapshot CLI (eclipse-rdf4j/rdf4j, 420 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Dt Dql Essentials?

Dynatrace (a GitHub organization) maintains it in Dynatrace/dynatrace-for-ai, which has 161 GitHub stars. The repository holds 33 skills in this directory. The repository was last updated on October 1, 2026.

Source: Dynatrace/dynatrace-for-ai on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.