Skip to content

Commit 9fe20bf

Browse files
feat: Replace list-problems with a DQL based tool (#73)
* feat: Replace list-problems with a DQL based tool, remove get-problem-details tool. * Fixed additional space Co-authored-by: Manuel Warum <[email protected]> * Fix timeframe for list_problems and docs * chore: Refactor executeDql to take an object for config --------- Co-authored-by: Manuel Warum <[email protected]>
1 parent 8d749b5 commit 9fe20bf

11 files changed

+85
-85
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# @dynatrace-oss/dynatrace-mcp-server
22

3+
## 0.5.0 (Release Candidate 2)
4+
5+
- Improved "List Problems" tool to use a DQL statement to retrieve data from Dynatrace, and provide better next steps
6+
- Removed "Get Problem Details" tool, as the same can be achieved with a simple "execute_dql" call
7+
- Removed scope `environment-api:problems:read` as it's no longer needed
8+
39
## 0.5.0 (Release Candidate 1)
410

511
- Added support for Authorization via Platform Tokens via environment variable `DT_PLATFORM_TOKEN`

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ Depending on the features you are using, the following scopes are needed:
136136
- `app-engine:functions:run` - needed for for almost all tools
137137
- `environment-api:security-problems:read` - needed for reading security problems (_currently not available for Platform Tokens_)
138138
- `environment-api:entities:read` - read monitored entities (_currently not available for Platform Tokens_)
139-
- `environment-api:problems:read` - get problems (_currently not available for Platform Tokens_)
140139
- `environment-api:metrics:read` - read metrics (_currently not available for Platform Tokens_)
141140
- `environment-api:slo:read` - read SLOs (_currently not available for Platform Tokens_)
142141
- `automation:workflows:read` - read Workflows

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@dynatrace-oss/dynatrace-mcp-server",
3-
"version": "0.5.0-rc.1",
3+
"version": "0.5.0-rc.2",
44
"description": "Model Context Protocol (MCP) server for Dynatrace",
55
"keywords": [
66
"Dynatrace",

src/capabilities/execute-dql.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { HttpClient } from '@dynatrace-sdk/http-client';
2-
import { QueryExecutionClient, QueryAssistanceClient, QueryResult } from '@dynatrace-sdk/client-query';
2+
import { QueryExecutionClient, QueryAssistanceClient, QueryResult, ExecuteRequest } from '@dynatrace-sdk/client-query';
33

44
export const verifyDqlStatement = async (dtClient: HttpClient, dqlStatement: string) => {
55
const queryAssistanceClient = new QueryAssistanceClient(dtClient);
@@ -13,17 +13,21 @@ export const verifyDqlStatement = async (dtClient: HttpClient, dqlStatement: str
1313
return response;
1414
};
1515

16+
/**
17+
* Execute a DQL statement against the Dynatrace API.
18+
* If the result is immediately available, it will be returned.
19+
* If the result is not immediately available, it will poll for the result until it is available.
20+
* @param dtClient
21+
* @param body - Contains the DQL statement to execute, and optional parameters like maxResultRecords and maxResultBytes
22+
* @returns the result without metadata and without notifications, or undefined if the query failed or no result was returned.
23+
*/
1624
export const executeDql = async (
1725
dtClient: HttpClient,
18-
dqlStatement: string,
26+
body: ExecuteRequest,
1927
): Promise<QueryResult['records'] | undefined> => {
2028
const queryExecutionClient = new QueryExecutionClient(dtClient);
2129

22-
const response = await queryExecutionClient.queryExecute({
23-
body: {
24-
query: dqlStatement,
25-
},
26-
});
30+
const response = await queryExecutionClient.queryExecute({ body });
2731

2832
if (response.result) {
2933
// return response result immediately

src/capabilities/find-monitored-entity-by-name.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export const findMonitoredEntityByName = async (dtClient: HttpClient, entityName
88
| append [fetch dt.entity.process_group | search "*${entityName}*" | fieldsAdd entity.type]
99
| append [fetch dt.entity.cloud_application | search "*${entityName}*" | fieldsAdd entity.type]`;
1010

11-
const dqlResponse = await executeDql(dtClient, dql);
11+
const dqlResponse = await executeDql(dtClient, { query: dql });
1212

1313
if (dqlResponse && dqlResponse.length > 0) {
1414
let resp = 'The following monitored entities were found:\n';

src/capabilities/get-events-for-cluster.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ export const getEventsForCluster = async (dtClient: HttpClient, clusterId: strin
99
dql = `fetch events | filter isNotNull(k8s.cluster.uid)`;
1010
}
1111

12-
return executeDql(dtClient, dql);
12+
return executeDql(dtClient, { query: dql });
1313
};

src/capabilities/get-logs-for-entity.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ import { executeDql } from './execute-dql';
44
export const getLogsForEntity = async (dtClient: HttpClient, entityId: string) => {
55
const dql = `fetch logs | filter dt.source_entity == "${entityId}"`;
66

7-
return executeDql(dtClient, dql);
7+
return executeDql(dtClient, { query: dql });
88
};

src/capabilities/get-problem-details.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/capabilities/list-problems.ts

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
11
import { HttpClient } from '@dynatrace-sdk/http-client';
2-
import { ProblemsClient } from '@dynatrace-sdk/client-classic-environment-v2';
2+
import { executeDql } from './execute-dql';
33

4-
export const listProblems = async (dtClient: HttpClient) => {
5-
const problemsClient = new ProblemsClient(dtClient);
4+
export const listProblems = async (dtClient: HttpClient, additionalFilter?: string) => {
5+
// DQL Statement from Problems App to fetch all Davis Problems for the last 12 hours to now
6+
const dql = `fetch dt.davis.problems, from: now()-12h, to: now()
7+
| filter isNull(dt.davis.is_duplicate) OR not(dt.davis.is_duplicate)
8+
${additionalFilter ? `| filter ${additionalFilter}` : ''}
9+
| fieldsAdd
10+
duration = coalesce(event.end, now()) - event.start,
11+
affected_entities_count = arraySize(affected_entity_ids),
12+
event_count = arraySize(dt.davis.event_ids),
13+
affected_users_count = dt.davis.affected_users_count,
14+
problem_id = event.id
15+
| fields display_id, event.name, event.description, event.status, event.category, event.start, event.end,
16+
root_cause_entity_id, root_cause_entity_name, duration, affected_entities_count,
17+
event_count, affected_users_count, problem_id, dt.davis.mute.status, dt.davis.mute.user,
18+
entity_tags, labels.alerting_profile, maintenance.is_under_maintenance,
19+
aws.account.id, azure.resource.group, azure.subscription, cloud.provider, cloud.region,
20+
dt.cost.costcenter, dt.cost.product, dt.host_group.id, dt.security_context, gcp.project.id,
21+
host.name,
22+
k8s.cluster.name, k8s.cluster.uid, k8s.container.name, k8s.namespace.name, k8s.node.name, k8s.pod.name, k8s.service.name, k8s.workload.kind, k8s.workload.name
23+
| sort event.status asc, event.start desc
24+
`;
625

7-
const securityProblems = await problemsClient.getProblems({
8-
pageSize: 100,
9-
});
10-
11-
const problems = securityProblems.problems?.map((problem) => {
12-
return `${problem.displayId} (please refer to this problem with \`problemId\` ${problem.problemId}): ${problem.title}`;
13-
});
14-
15-
return problems;
26+
return await executeDql(dtClient, { query: dql, maxResultRecords: 5000, maxResultBytes: /* 5 MB */ 5000000 });
1627
};

0 commit comments

Comments
 (0)