Querying Grail from Apps
Two ways to query DQL from a Dynatrace app:
Method SDK Package Best For
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ
useDqlQuery (hook) @dynatrace-sdk/react-hooks Simple queries in components
queryExecutionClient (imperative) @dynatrace-sdk/client-query Custom polling, error handling
useDqlQuery โ The Simple Way
import { useDqlQuery } from "@dynatrace-sdk/react-hooks";
const result = useDqlQuery({
body: { query: `fetch dt.entity.host | fields entity.name, cpuCores, osType | limit 10` }
});
// result.data โ query results
// result.isLoading โ loading state
// result.error โ error if any
queryExecutionClient โ Full Control
From the real Host Health Monitor app (deployed, auto-refreshes every 30 seconds). This is a custom wrapper โ not the SDK's useDql hook:
import { queryExecutionClient } from "@dynatrace-sdk/client-query";
import { useState, useEffect, useCallback } from "react";
export function useDql(query: string) {
const [data, setData] = useState<Record<string, unknown>[]>([]);
const [loading, setLoading] = useState(true);
const run = useCallback(() => {
queryExecutionClient
.queryExecute({ body: { query, requestTimeoutMilliseconds: 30000, maxResultRecords: 1000 } })
.then((res) => { setData(res.result?.records ?? []); setLoading(false); })
.catch(() => setLoading(false));
}, [query]);
useEffect(() => {
run();
const id = setInterval(run, 30_000);
return () => clearInterval(id);
}, [run]);
return { data, loading };
}
Available Data
DQL Fetch Target What You Get Scope Needed
โโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ
dt.entity.host Hosts, CPU, memory, OS storage:entities:read
dt.entity.service Services, technology storage:entities:read
fetch logs Log records storage:logs:read
fetch events Davis events and problems storage:events:read
fetch bizevents Business events storage:bizevents:read
timeseries Metric time series storage:metrics:read
dt.davis.slo SLO status and targets storage:events:read
โ ๏ธ Every data type needs its own scope in app.config.json. Missing scope = silent empty results (no error, just no data).
๐ Try it: In your app, query the top 5 busiest services: const result = useDqlQuery({ body: { query: "timeseries rt=avg(dt.service.request.response_time), by:{dt.entity.service} | fieldsAdd current=arrayLast(rt) | sort current desc | limit 5" } }); โ render in a DataTable. Your app now shows a live "slowest services" leaderboard.