02 Mar 2026
09:50 AM
- last edited on
02 Mar 2026
01:13 PM
by
GosiaMurawska
hi,
in the community i have downloaded this runbook very helpful,
but i need to exract only the process that have monitoring state different from "ok".
How can change the code?
/*
* This function will run in the DYNATRACE JavaScript runtime.
* For information visit https://dt-url.net/functions-help
*/
import { monitoredEntitiesMonitoringStateClient } from "@dynatrace-sdk/client-classic-environment-v2";
import { queryExecutionClient } from "@dynatrace-sdk/client-query";
// **** Dynatrace API ****
async function fetchAllMonitoringStates(pgID) {
const pgID_string = `${pgID.map(id => `"${id}"`).join(",")}`;
let nextPageKey = null;
const monitoringStates = [];
do {
const params = nextPageKey
? { nextPageKey }
: { entitySelector: `entityId(${pgID_string})`};
const result = await monitoredEntitiesMonitoringStateClient.getStates(params);
monitoringStates.push(...result.monitoringStates);
nextPageKey = result.nextPageKey;
} while (nextPageKey);
return monitoringStates
}
export default async function () {
const now = new Date();
const twentyMinutesAgo = new Date(now.getTime() - 20 * 60 * 1000);
const formatDate = (date) => date.toISOString();
const $dt_timeframe_from = formatDate(twentyMinutesAgo);
const $dt_timeframe_to = formatDate(now);
// **** DQL Query ****
const dqlQuery = `
fetch dt.entity.process_group_instance
| fieldsAdd host.id=belongs_to[dt.entity.host], pg_id=instance_of[dt.entity.process_group], cgi_id=(belongs_to[dt.entity.container_group_instance])
| lookup [fetch dt.entity.host], sourceField:host.id, lookupField:id, fields:{host.name=entity.name, host.hostGroupName=hostGroupName}
| lookup [fetch dt.entity.process_group], sourceField:pg_id, lookupField:id, fields:{process.name=entity.name}
| lookup [fetch dt.entity.container_group_instance
| fieldsAdd pod_id=belongs_to[dt.entity.cloud_application_instance], namespace_id=belongs_to[dt.entity.cloud_application_namespace], node_id=belongs_to[dt.entity.host]
| lookup [fetch dt.entity.cloud_application_instance], sourceField:pod_id, lookupField:id, fields:{pod_name=entity.name}
| lookup [fetch dt.entity.cloud_application_namespace], sourceField:namespace_id, lookupField:id, fields:{namespace=entity.name}
| lookup [fetch dt.entity.host], sourceField:node_id, lookupField:id, fields:{node_name=entity.name}], sourceField:cgi_id, lookupField:id, fields:{pod_name, namespace, node_name}
| fields managementZones, host.id, host.name, host.hostGroupName, process.name, pod_name, namespace, node_name, id
| sort process.name desc
//| filter host.hostGroupName == "bet-booker"
`;
// **** Execution Performance Limits ****
// const queryExecution = await queryExecutionClient.queryExecute({ body: { query: dqlQuery } });
const queryExecution = await queryExecutionClient.queryExecute({ body: {
query: dqlQuery,
scanLimitGBytes: -1
// fetchTimeoutSeconds:5000,
// defalutScanLimitsGbytes: 500000,
// maxResultsBytes: 100000000,
// maxResultsRecords: 300000000
} });
let dqlResults = [];
while (true) {
const queryPollResult = await queryExecutionClient.queryPoll({ requestToken: queryExecution.requestToken });
if (queryPollResult.state !== "RUNNING") {
dqlResults = queryPollResult.result.records;
break;
}
}
let pgID = dqlResults.map(item => item.id);
const processAllChunks = async () => {
const allMonitoringStates = [];
for (let i = 0; i < pgID.length; i += 50) {
const chunk = pgID.slice(i, i + 50);
const chunkStates = await fetchAllMonitoringStates(chunk);
allMonitoringStates.push(...chunkStates);
}
return allMonitoringStates;
};
const monitoringStates = await processAllChunks();
const mergedResults = dqlResults.map(dqlItem => {
const match = monitoringStates.find(apiItem => apiItem.entityId === dqlItem.id);
return match ? { ...dqlItem, severity: match.severity, state: match.state } : dqlItem;
});
return mergedResults
}
Solved! Go to Solution.
02 Mar 2026 10:57 AM
Hi,
try this:
Total number of calls over the selected time range (sum of all minutes)
timeseries calls_per_min = sum(dt.service.request.count, rate:1m),
by:{endpoint.name, dt.entity.service, dt.host_group.id},
interval: 1m
| fieldsAdd service_name = entityName(dt.entity.service)
| fieldsAdd endpoint_key = concat(service_name, " :: ", endpoint.name, " :: ", dt.host_group.id)
| filter in(endpoint_key,
"CustomerFrontendREST :: Images :: et-large",
"JourneyService :: findJourneys :: et-large"
)
| fieldsAdd total_calls_row = arraySum(calls_per_min)
| summarize total_calls = sum(total_calls_row)
Current total (last datapoint), combined calls/min at the end of the chart
timeseries calls_per_min = sum(dt.service.request.count, rate:1m),
by:{endpoint.name, dt.entity.service, dt.host_group.id},
interval: 1m
| fieldsAdd service_name = entityName(dt.entity.service)
| fieldsAdd endpoint_key = concat(service_name, " :: ", endpoint.name, " :: ", dt.host_group.id)
| filter in(endpoint_key,
"CustomerFrontendREST :: Images :: et-large",
"JourneyService :: findJourneys :: et-large"
)
| fieldsAdd last_cpm_row = arrayLast(calls_per_min)
| summarize last_cpm_total = sum(last_cpm_row)
02 Mar 2026 11:24 AM
(-: is my request too
02 Mar 2026 11:17 AM
Hi,
I don’t have a ton of experience with this, but it seems to me that you don’t touch the DQL, only after merging the results (DQL + Monitoring State API) you apply a filter to keep only the processes where state != "OK".
Change return mergedResults to
const mergedResults = dqlResults.map(dqlItem => {
const match = monitoringStates.find(apiItem => apiItem.entityId === dqlItem.id);
return match ? { ...dqlItem, severity: match.severity, state: match.state } : dqlItem;
});
//Only proccesses !== "OK"
const onlyNotOk = mergedResults.filter(item => {
// jeśli dla jakiegoś wpisu nie ma state (API nie zwróciło), to:
if (!item.state) return true;
return item.state.toUpperCase() !== "OK";
});
return onlyNotOk;If you want to drop records with no state and keep only “real” non-OK ones:
return mergedResults.filter(item => item.state && item.state.toUpperCase() !== "OK");That’s it. It’s best to filter by state after the merge, because state comes from monitoredEntitiesMonitoringStateClient.getStates()
02 Mar 2026 11:23 AM
is possible have timeseries? because, in this case i have only the last value and i can't use line widget.
thanks a lot
02 Mar 2026 01:37 PM
Hi,
IMO yes, timeseries is possible, but not from getStates().
I am pretty sure, that monitoredEntitiesMonitoringStateClient.getStates() returns a point-in-time snapshot. Like monitoring state. So you’ll always have only a single latest value.
Mabye chang state to number (OK=0, WARNING=1, ERROR=2) and send it as custom metric. Thanks to that you can show it in line widget
Featured Posts