06 Aug 2026 02:11 PM
Hi Team,
i have below user session queries, i am looking for similar queries in DQL.
"userActionDuration" : f'SELECT AVG(useraction.duration),useraction.name FROM usersession WHERE userType="REAL_USER" AND userevent.pageGroup="{pageGroup}" GROUP BY useraction.name'
"visuallyCompleteTime" : f'SELECT AVG(useraction.visuallyCompleteTime),useraction.name FROM usersession WHERE userType="REAL_USER" AND userevent.pageGroup="{pageGroup}" GROUP BY useraction.name'
"documentInteractiveTime" : f'SELECT AVG(useraction.documentInteractiveTime),useraction.name FROM usersession WHERE userType="REAL_USER" AND userevent.pageGroup="{pageGroup}" GROUP BY useraction.name'
Please help me with these DQL queries or share me any related document for reference.
07 Aug 2026 07:10 AM
Hi, you could start from something like this:
fetch user.events
| filter isNotNull(user_action.id)
| filter dt.rum.user_type == "real_user"
| summarize avg(duration), by:{user_action.id, user_action.name}
About the new duration metrics you can check here:
https://www.dynatrace.com/knowledge-base/core-web-vitals/
bye
11 Aug 2026 09:55 AM
Hi @Tommaso_Fin , Thank you for the response, this table does not have data what i am looking for.
11 Aug 2026 10:39 AM
Hey,
For the duration, it would look something like this:
fetch user.events
| filter dt.rum.user_type == "real_user"
| fields duration, dt.rum.user_type, view.name, view.url.full
| summarize avg(duration), by:{view.name, view.url.full}That said, based on my own experience, the whole new RUM experience still has quite a few gaps and inconsistencies that make it difficult to use in many cases.
The data is also not live and can have significant delays. Sessions first need to end, and even then, the data can take up to 35 minutes to become available.
For example, if a normal user starts working at 08:30, works until 12:00, takes a break until 13:00, and then works until 17:00, I might only see their first actions from 08:30 around 12:35.
If they encounter an issue during their session, we would have to wait until they finish their session and then another ~35 minutes before we can investigate it. In the example above, that means potentially waiting until around 17:35 — or simply looking at the data the next day.
So for investigating issues with today's sessions, the new RUM is currently not very practical.
For visually complete time, I haven't been able to find a working metric myself.
documentInteractiveTime looks like it should correspond to performance.dom_interactive, but that one doesn't seem to work for me. Maybe you'll have more luck with it.
Note: page.groups doesn't seem to exist anymore(or Can't find them).
Also, keep in mind that any action naming rules you configured in Dynatrace settings won't be available in the new RUM. To use action Naming rules/clean names you will need to do this in application source code.
11 Aug 2026 05:45 PM - edited 11 Aug 2026 05:46 PM
Hi @dylan_taelemans ,
Thank you for responding. I tried below in the notebook it is giving me the required details.
import { metricsClient } from '@dynatrace-sdk/client-classic-environment-v2';
export default async function () {
const metrics = {
visuallyComplete:
'builtin:apps.web.action.visuallyComplete.load.browser:splitBy("dt.entity.application_method"):names',
lcp:
'builtin:apps.web.action.largestContentfulPaint.load.browser:splitBy("dt.entity.application_method"):names',
fid:
'builtin:apps.web.action.firstInputDelay.load.browser:splitBy("dt.entity.application_method"):names',
firstByte:
'builtin:apps.web.action.firstByte.load.browser:splitBy("dt.entity.application_method"):names'
};
try {
const [
visuallyCompleteData,
lcpData,
fidData,
firstByteData
] = await Promise.all([
metricsClient.query({
metricSelector: metrics.visuallyComplete,
from: '-30d',
to: 'now',
acceptType: 'application/json'
}),
metricsClient.query({
metricSelector: metrics.lcp,
from: '-30d',
to: 'now',
acceptType: 'application/json'
}),
metricsClient.query({
metricSelector: metrics.fid,
from: '-30d',
to: 'now',
acceptType: 'application/json'
}),
metricsClient.query({
metricSelector: metrics.firstByte,
from: '-30d',
to: 'now',
acceptType: 'application/json'
})
]);
const rowsMap = new Map<string, any>();
const addMetric = (
data: any,
columnName: string
) => {
const series = data.result?.[0]?.data ?? [];
series.forEach((item: any) => {
const methodId =
item.dimensionMap?.['dt.entity.application_method'];
const pageName =
item.dimensionMap?.['dt.entity.application_method.name'] ??
methodId;
const value =
item.values?.find(
(v: number | null) => v != null
) ?? 0;
if (!rowsMap.has(methodId)) {
rowsMap.set(methodId, {
PageName: pageName
});
}
rowsMap.get(methodId)[columnName] =
Math.round(value);
});
};
addMetric(
visuallyCompleteData,
'VisuallyCompleteMs'
);
addMetric(
lcpData,
'LargestContentfulPaintMs'
);
addMetric(
fidData,
'FirstInputDelayMs'
);
addMetric(
firstByteData,
'FirstByteMs'
);
const rows = [];
for (const row of rowsMap.values()) {
const vcScore = rateMetric(
row.VisuallyCompleteMs ?? 0,
5000,
10000
);
const lcpScore = rateMetric(
row.LargestContentfulPaintMs ?? 0,
2500,
4000
);
const ttfbScore = rateMetric(
row.FirstByteMs ?? 0,
800,
1800
);
const fidScore = rateMetric(
row.FirstInputDelayMs ?? 0,
100,
300
);
const totalScore =
(vcScore * 0.4) +
(lcpScore * 0.3) +
(ttfbScore * 0.2) +
(fidScore * 0.1);
let pagePerformance = 'Poor';
if (totalScore >= 1.5) {
pagePerformance = 'Good';
} else if (totalScore >= 0.8) {
pagePerformance = 'Tolerated';
}
row.PagePerformance = pagePerformance;
rows.push(row);
}
return rows.sort(
(a, b) =>
(b.VisuallyCompleteMs || 0) -
(a.VisuallyCompleteMs || 0)
);
} catch (error) {
return `🚫 Error: ${error}`;
}
}
function rateMetric(
value: number,
goodThreshold: number,
toleratedThreshold: number
) {
if (value <= goodThreshold) return 2;
if (value <= toleratedThreshold) return 1;
return 0;
}
Featured Posts