mcp-instana 0.1.0__py3-none-any.whl → 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcp_instana-0.1.1.dist-info/METADATA +908 -0
- mcp_instana-0.1.1.dist-info/RECORD +30 -0
- {mcp_instana-0.1.0.dist-info → mcp_instana-0.1.1.dist-info}/WHEEL +1 -1
- mcp_instana-0.1.1.dist-info/entry_points.txt +4 -0
- mcp_instana-0.1.0.dist-info/LICENSE → mcp_instana-0.1.1.dist-info/licenses/LICENSE.md +3 -3
- src/application/__init__.py +1 -0
- src/{client/application_alert_config_mcp_tools.py → application/application_alert_config.py} +251 -273
- src/application/application_analyze.py +415 -0
- src/application/application_catalog.py +153 -0
- src/{client/application_metrics_mcp_tools.py → application/application_metrics.py} +107 -129
- src/{client/application_resources_mcp_tools.py → application/application_resources.py} +128 -150
- src/application/application_settings.py +1135 -0
- src/application/application_topology.py +107 -0
- src/core/__init__.py +1 -0
- src/core/server.py +436 -0
- src/core/utils.py +213 -0
- src/event/__init__.py +1 -0
- src/{client/events_mcp_tools.py → event/events_tools.py} +128 -136
- src/infrastructure/__init__.py +1 -0
- src/{client/infrastructure_analyze_mcp_tools.py → infrastructure/infrastructure_analyze.py} +200 -203
- src/{client/infrastructure_catalog_mcp_tools.py → infrastructure/infrastructure_catalog.py} +194 -264
- src/infrastructure/infrastructure_metrics.py +167 -0
- src/{client/infrastructure_resources_mcp_tools.py → infrastructure/infrastructure_resources.py} +192 -223
- src/{client/infrastructure_topology_mcp_tools.py → infrastructure/infrastructure_topology.py} +105 -106
- src/log/__init__.py +1 -0
- src/log/log_alert_configuration.py +331 -0
- src/prompts/mcp_prompts.py +900 -0
- src/prompts/prompt_loader.py +29 -0
- src/prompts/prompt_registry.json +21 -0
- mcp_instana-0.1.0.dist-info/METADATA +0 -649
- mcp_instana-0.1.0.dist-info/RECORD +0 -19
- mcp_instana-0.1.0.dist-info/entry_points.txt +0 -3
- src/client/What is the sum of queue depth for all q +0 -55
- src/client/instana_client_base.py +0 -93
- src/client/log_alert_configuration_mcp_tools.py +0 -316
- src/client/show the top 5 services with the highest +0 -28
- src/mcp_server.py +0 -343
|
@@ -4,95 +4,88 @@ Agent Monitoring Events MCP Tools Module
|
|
|
4
4
|
This module provides agent monitoring events-specific MCP tools for Instana monitoring.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
import
|
|
8
|
-
from typing import Dict, Any, Optional, List, Union
|
|
7
|
+
import logging
|
|
9
8
|
from datetime import datetime
|
|
9
|
+
from typing import Any, Dict, Optional
|
|
10
10
|
|
|
11
11
|
# Import the correct class name (EventsApi with lowercase 'i')
|
|
12
12
|
from instana_client.api.events_api import EventsApi
|
|
13
13
|
|
|
14
|
-
from .
|
|
14
|
+
from src.core.utils import BaseInstanaClient, register_as_tool, with_header_auth
|
|
15
|
+
|
|
16
|
+
# Configure logger for this module
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
15
18
|
|
|
16
19
|
class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
17
20
|
"""Tools for agent monitoring events in Instana MCP."""
|
|
18
|
-
|
|
21
|
+
|
|
19
22
|
def __init__(self, read_token: str, base_url: str):
|
|
20
23
|
"""Initialize the Agent Monitoring Events MCP tools client."""
|
|
21
24
|
super().__init__(read_token=read_token, base_url=base_url)
|
|
22
|
-
|
|
23
|
-
# Configure the API client with the correct base URL and authentication
|
|
24
|
-
from instana_client.configuration import Configuration
|
|
25
|
-
configuration = Configuration()
|
|
26
|
-
configuration.host = base_url
|
|
27
|
-
configuration.api_key['ApiKeyAuth'] = read_token
|
|
28
|
-
configuration.api_key_prefix['ApiKeyAuth'] = 'apiToken'
|
|
29
|
-
|
|
30
|
-
# Create an API client with this configuration
|
|
31
|
-
from instana_client.api_client import ApiClient
|
|
32
|
-
api_client = ApiClient(configuration=configuration)
|
|
33
|
-
|
|
34
|
-
# Initialize the Instana SDK's EventsApi with our configured client
|
|
35
|
-
self.events_api = EventsApi(api_client=api_client)
|
|
36
|
-
|
|
37
|
-
|
|
25
|
+
|
|
38
26
|
@register_as_tool
|
|
39
|
-
|
|
27
|
+
@with_header_auth(EventsApi)
|
|
28
|
+
async def get_event(self, event_id: str, ctx=None, api_client=None) -> Dict[str, Any]:
|
|
40
29
|
"""
|
|
41
30
|
Get a specific event by ID.
|
|
42
|
-
|
|
31
|
+
|
|
43
32
|
Args:
|
|
44
33
|
event_id: The ID of the event to retrieve
|
|
45
34
|
ctx: The MCP context (optional)
|
|
46
|
-
|
|
35
|
+
api_client: API client for testing (optional)
|
|
36
|
+
|
|
47
37
|
Returns:
|
|
48
38
|
Dictionary containing the event data or error information
|
|
49
39
|
"""
|
|
50
40
|
try:
|
|
51
41
|
# Call the get_event method from the SDK
|
|
52
|
-
result =
|
|
53
|
-
|
|
42
|
+
result = api_client.get_event(event_id=event_id)
|
|
43
|
+
|
|
54
44
|
return result
|
|
55
45
|
except Exception as e:
|
|
56
|
-
|
|
46
|
+
logger.error(f"Error in get_event: {e}", exc_info=True)
|
|
47
|
+
return {"error": f"Failed to get event: {e!s}"}
|
|
57
48
|
|
|
58
49
|
@register_as_tool
|
|
50
|
+
@with_header_auth(EventsApi)
|
|
59
51
|
async def get_kubernetes_info_events(self,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
52
|
+
from_time: Optional[int] = None,
|
|
53
|
+
to_time: Optional[int] = None,
|
|
54
|
+
time_range: Optional[str] = None,
|
|
55
|
+
max_events: Optional[int] = 50, # Added parameter to limit events
|
|
56
|
+
ctx=None, api_client=None) -> Dict[str, Any]:
|
|
65
57
|
"""
|
|
66
58
|
Get Kubernetes info events based on the provided parameters and return a detailed analysis.
|
|
67
|
-
|
|
59
|
+
|
|
68
60
|
This tool retrieves Kubernetes events from Instana and provides a detailed analysis focusing on top problems,
|
|
69
61
|
their details, and actionable fix suggestions. You can specify a time range using timestamps or natural language
|
|
70
62
|
like "last 24 hours" or "last 2 days".
|
|
71
|
-
|
|
63
|
+
|
|
72
64
|
Args:
|
|
73
65
|
from_time: Start timestamp in milliseconds since epoch (optional)
|
|
74
66
|
to_time: End timestamp in milliseconds since epoch (optional)
|
|
75
67
|
time_range: Natural language time range like "last 24 hours", "last 2 days", "last week" (optional)
|
|
76
68
|
max_events: Maximum number of events to process (default: 50)
|
|
77
69
|
ctx: The MCP context (optional)
|
|
78
|
-
|
|
70
|
+
api_client: API client for testing (optional)
|
|
71
|
+
|
|
79
72
|
Returns:
|
|
80
73
|
Dictionary containing detailed Kubernetes events analysis or error information
|
|
81
74
|
"""
|
|
82
75
|
try:
|
|
83
76
|
# Process natural language time range if provided
|
|
84
77
|
if time_range:
|
|
85
|
-
|
|
86
|
-
|
|
78
|
+
logger.debug(f"Processing natural language time range: '{time_range}'")
|
|
79
|
+
|
|
87
80
|
# Current time in milliseconds
|
|
88
81
|
current_time_ms = int(datetime.now().timestamp() * 1000)
|
|
89
|
-
|
|
82
|
+
|
|
90
83
|
# Default to 24 hours if just "last few hours" is specified
|
|
91
84
|
if time_range.lower() in ["last few hours", "last hours", "few hours"]:
|
|
92
85
|
hours = 24
|
|
93
86
|
from_time = current_time_ms - (hours * 60 * 60 * 1000)
|
|
94
87
|
to_time = current_time_ms
|
|
95
|
-
|
|
88
|
+
logger.debug(f"Interpreted as last {hours} hours")
|
|
96
89
|
# Extract hours if specified
|
|
97
90
|
elif "hour" in time_range.lower():
|
|
98
91
|
import re
|
|
@@ -126,26 +119,26 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
126
119
|
hours = 24
|
|
127
120
|
from_time = current_time_ms - (hours * 60 * 60 * 1000)
|
|
128
121
|
to_time = current_time_ms
|
|
129
|
-
|
|
122
|
+
|
|
130
123
|
# Set default time range if not provided
|
|
131
124
|
if not to_time:
|
|
132
125
|
to_time = int(datetime.now().timestamp() * 1000)
|
|
133
126
|
if not from_time:
|
|
134
127
|
from_time = to_time - (24 * 60 * 60 * 1000) # Default to 24 hours
|
|
135
|
-
|
|
128
|
+
|
|
136
129
|
# Call the kubernetes_info_events method from the SDK
|
|
137
|
-
result =
|
|
130
|
+
result = api_client.kubernetes_info_events(
|
|
138
131
|
to=to_time,
|
|
139
132
|
var_from=from_time,
|
|
140
133
|
window_size=None,
|
|
141
134
|
filter_event_updates=None,
|
|
142
135
|
exclude_triggered_before=None
|
|
143
136
|
)
|
|
144
|
-
|
|
137
|
+
|
|
145
138
|
# Print the raw result for debugging
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
139
|
+
logger.debug(f"Raw API result type: {type(result)}")
|
|
140
|
+
logger.debug(f"Raw API result length: {len(result) if isinstance(result, list) else 'not a list'}")
|
|
141
|
+
|
|
149
142
|
# If there are no events, return early
|
|
150
143
|
if not result or (isinstance(result, list) and len(result) == 0):
|
|
151
144
|
from_date = datetime.fromtimestamp(from_time/1000).strftime('%Y-%m-%d %H:%M:%S')
|
|
@@ -155,17 +148,17 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
155
148
|
"time_range": f"{from_date} to {to_date}",
|
|
156
149
|
"events_count": 0
|
|
157
150
|
}
|
|
158
|
-
|
|
151
|
+
|
|
159
152
|
# Process the events to create a summary
|
|
160
153
|
events = result if isinstance(result, list) else [result]
|
|
161
|
-
|
|
154
|
+
|
|
162
155
|
# Get the total number of events before limiting
|
|
163
156
|
total_events_count = len(events)
|
|
164
|
-
|
|
157
|
+
|
|
165
158
|
# Limit the number of events to process
|
|
166
159
|
events = events[:max_events]
|
|
167
|
-
|
|
168
|
-
|
|
160
|
+
logger.debug(f"Limited to processing {len(events)} events out of {total_events_count} total events")
|
|
161
|
+
|
|
169
162
|
# Convert InfraEventResult objects to dictionaries if needed
|
|
170
163
|
event_dicts = []
|
|
171
164
|
for event in events:
|
|
@@ -173,14 +166,14 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
173
166
|
event_dicts.append(event.to_dict())
|
|
174
167
|
else:
|
|
175
168
|
event_dicts.append(event)
|
|
176
|
-
|
|
169
|
+
|
|
177
170
|
# Group events by problem type
|
|
178
171
|
problem_groups = {}
|
|
179
|
-
|
|
172
|
+
|
|
180
173
|
# Process each event
|
|
181
174
|
for event in event_dicts:
|
|
182
175
|
problem = event.get("problem", "Unknown")
|
|
183
|
-
|
|
176
|
+
|
|
184
177
|
# Initialize problem group if not exists
|
|
185
178
|
if problem not in problem_groups:
|
|
186
179
|
problem_groups[problem] = {
|
|
@@ -191,26 +184,26 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
191
184
|
"fix_suggestions": set(),
|
|
192
185
|
"sample_events": []
|
|
193
186
|
}
|
|
194
|
-
|
|
187
|
+
|
|
195
188
|
# Update problem group
|
|
196
189
|
problem_groups[problem]["count"] += 1
|
|
197
|
-
|
|
190
|
+
|
|
198
191
|
# Extract namespace from entityLabel
|
|
199
192
|
entity_label = event.get("entityLabel", "")
|
|
200
193
|
if "/" in entity_label:
|
|
201
194
|
namespace, entity = entity_label.split("/", 1)
|
|
202
195
|
problem_groups[problem]["affected_namespaces"].add(namespace)
|
|
203
196
|
problem_groups[problem]["affected_entities"].add(entity)
|
|
204
|
-
|
|
197
|
+
|
|
205
198
|
# Add detail and fix suggestion
|
|
206
199
|
detail = event.get("detail", "")
|
|
207
200
|
if detail:
|
|
208
201
|
problem_groups[problem]["details"].add(detail)
|
|
209
|
-
|
|
202
|
+
|
|
210
203
|
fix_suggestion = event.get("fixSuggestion", "")
|
|
211
204
|
if fix_suggestion:
|
|
212
205
|
problem_groups[problem]["fix_suggestions"].add(fix_suggestion)
|
|
213
|
-
|
|
206
|
+
|
|
214
207
|
# Add sample event (up to 3 per problem)
|
|
215
208
|
if len(problem_groups[problem]["sample_events"]) < 3:
|
|
216
209
|
simple_event = {
|
|
@@ -220,17 +213,17 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
220
213
|
"detail": detail
|
|
221
214
|
}
|
|
222
215
|
problem_groups[problem]["sample_events"].append(simple_event)
|
|
223
|
-
|
|
216
|
+
|
|
224
217
|
# Sort problems by count (most frequent first)
|
|
225
218
|
sorted_problems = sorted(problem_groups.items(), key=lambda x: x[1]["count"], reverse=True)
|
|
226
|
-
|
|
219
|
+
|
|
227
220
|
# Format the time range in a human-readable format
|
|
228
221
|
from_date = datetime.fromtimestamp(from_time/1000).strftime('%Y-%m-%d %H:%M:%S')
|
|
229
222
|
to_date = datetime.fromtimestamp(to_time/1000).strftime('%Y-%m-%d %H:%M:%S')
|
|
230
|
-
|
|
223
|
+
|
|
231
224
|
# Create a detailed analysis of each problem
|
|
232
225
|
problem_analyses = []
|
|
233
|
-
|
|
226
|
+
|
|
234
227
|
# Process each problem
|
|
235
228
|
for problem_name, problem_data in sorted_problems:
|
|
236
229
|
# Create a detailed problem analysis
|
|
@@ -242,9 +235,9 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
242
235
|
"fix_suggestions": list(problem_data["fix_suggestions"]),
|
|
243
236
|
"sample_events": problem_data["sample_events"]
|
|
244
237
|
}
|
|
245
|
-
|
|
238
|
+
|
|
246
239
|
problem_analyses.append(problem_analysis)
|
|
247
|
-
|
|
240
|
+
|
|
248
241
|
# Create a comprehensive analysis
|
|
249
242
|
analysis_result = {
|
|
250
243
|
"summary": f"Analysis based on {len(events)} of {total_events_count} Kubernetes events between {from_date} and {to_date}.",
|
|
@@ -253,64 +246,63 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
253
246
|
"events_analyzed": len(events),
|
|
254
247
|
"problem_analyses": problem_analyses[:10] # Limit to top 10 problems for readability
|
|
255
248
|
}
|
|
256
|
-
|
|
249
|
+
|
|
257
250
|
# Create a more user-friendly text summary for direct display
|
|
258
251
|
markdown_summary = "# Kubernetes Events Analysis\n\n"
|
|
259
252
|
markdown_summary += f"Analysis based on {len(events)} of {total_events_count} Kubernetes events between {from_date} and {to_date}.\n\n"
|
|
260
|
-
|
|
253
|
+
|
|
261
254
|
markdown_summary += "## Top Problems\n\n"
|
|
262
|
-
|
|
255
|
+
|
|
263
256
|
# Add each problem to the markdown summary
|
|
264
257
|
for problem_analysis in problem_analyses[:5]: # Limit to top 5 for readability
|
|
265
258
|
problem_name = problem_analysis["problem"]
|
|
266
259
|
count = problem_analysis["count"]
|
|
267
|
-
|
|
260
|
+
|
|
268
261
|
markdown_summary += f"### {problem_name} ({count} events)\n\n"
|
|
269
|
-
|
|
262
|
+
|
|
270
263
|
# Add affected namespaces if available
|
|
271
264
|
if problem_analysis.get("affected_namespaces"):
|
|
272
265
|
namespaces = ", ".join(problem_analysis["affected_namespaces"][:5])
|
|
273
266
|
if len(problem_analysis["affected_namespaces"]) > 5:
|
|
274
267
|
namespaces += f" and {len(problem_analysis['affected_namespaces']) - 5} more"
|
|
275
268
|
markdown_summary += f"**Affected Namespaces:** {namespaces}\n\n"
|
|
276
|
-
|
|
269
|
+
|
|
277
270
|
# Add fix suggestions
|
|
278
271
|
if problem_analysis.get("fix_suggestions"):
|
|
279
272
|
markdown_summary += "**Fix Suggestions:**\n\n"
|
|
280
273
|
for suggestion in list(problem_analysis["fix_suggestions"])[:3]: # Limit to top 3 suggestions
|
|
281
274
|
markdown_summary += f"- {suggestion}\n"
|
|
282
|
-
|
|
275
|
+
|
|
283
276
|
markdown_summary += "\n"
|
|
284
|
-
|
|
277
|
+
|
|
285
278
|
# Add the markdown summary to the result
|
|
286
279
|
analysis_result["markdown_summary"] = markdown_summary
|
|
287
|
-
|
|
280
|
+
|
|
288
281
|
return analysis_result
|
|
289
|
-
|
|
282
|
+
|
|
290
283
|
except Exception as e:
|
|
291
|
-
|
|
292
|
-
import traceback
|
|
293
|
-
traceback.print_exc(file=sys.stderr)
|
|
284
|
+
logger.error(f"Error in get_kubernetes_info_events: {e}", exc_info=True)
|
|
294
285
|
return {
|
|
295
|
-
"error": f"Failed to get Kubernetes info events: {
|
|
286
|
+
"error": f"Failed to get Kubernetes info events: {e!s}"
|
|
296
287
|
}
|
|
297
288
|
|
|
298
289
|
@register_as_tool
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
290
|
+
@with_header_auth(EventsApi)
|
|
291
|
+
async def get_agent_monitoring_events(self,
|
|
292
|
+
query: Optional[str] = None,
|
|
293
|
+
from_time: Optional[int] = None,
|
|
294
|
+
to_time: Optional[int] = None,
|
|
295
|
+
size: Optional[int] = 100,
|
|
296
|
+
max_events: Optional[int] = 50, # Added parameter to limit events
|
|
297
|
+
time_range: Optional[str] = None, # Added parameter for natural language time range
|
|
298
|
+
ctx=None, api_client=None) -> Dict[str, Any]:
|
|
307
299
|
"""
|
|
308
300
|
Get agent monitoring events from Instana and return a detailed analysis.
|
|
309
|
-
|
|
310
|
-
This tool retrieves agent monitoring events from Instana and provides a detailed analysis focusing on
|
|
311
|
-
monitoring issues, their frequency, and affected entities. You can specify a time range using timestamps
|
|
301
|
+
|
|
302
|
+
This tool retrieves agent monitoring events from Instana and provides a detailed analysis focusing on
|
|
303
|
+
monitoring issues, their frequency, and affected entities. You can specify a time range using timestamps
|
|
312
304
|
or natural language like "last 24 hours" or "last 2 days".
|
|
313
|
-
|
|
305
|
+
|
|
314
306
|
Args:
|
|
315
307
|
query: Query string to filter events (optional)
|
|
316
308
|
from_time: Start timestamp in milliseconds since epoch (optional, defaults to 1 hour ago)
|
|
@@ -319,24 +311,25 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
319
311
|
max_events: Maximum number of events to process for analysis (optional, default 50)
|
|
320
312
|
time_range: Natural language time range like "last 24 hours", "last 2 days", "last week" (optional)
|
|
321
313
|
ctx: The MCP context (optional)
|
|
322
|
-
|
|
314
|
+
api_client: API client for testing (optional)
|
|
315
|
+
|
|
323
316
|
Returns:
|
|
324
317
|
Dictionary containing summarized agent monitoring events data or error information
|
|
325
318
|
"""
|
|
326
319
|
try:
|
|
327
320
|
# Process natural language time range if provided
|
|
328
321
|
if time_range:
|
|
329
|
-
|
|
330
|
-
|
|
322
|
+
logger.debug(f"Processing natural language time range: '{time_range}'")
|
|
323
|
+
|
|
331
324
|
# Current time in milliseconds
|
|
332
325
|
current_time_ms = int(datetime.now().timestamp() * 1000)
|
|
333
|
-
|
|
326
|
+
|
|
334
327
|
# Default to 24 hours if just "last few hours" is specified
|
|
335
328
|
if time_range.lower() in ["last few hours", "last hours", "few hours"]:
|
|
336
329
|
hours = 24
|
|
337
330
|
from_time = current_time_ms - (hours * 60 * 60 * 1000)
|
|
338
331
|
to_time = current_time_ms
|
|
339
|
-
|
|
332
|
+
logger.debug(f"Interpreted as last {hours} hours")
|
|
340
333
|
# Extract hours if specified
|
|
341
334
|
elif "hour" in time_range.lower():
|
|
342
335
|
import re
|
|
@@ -370,29 +363,29 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
370
363
|
hours = 24
|
|
371
364
|
from_time = current_time_ms - (hours * 60 * 60 * 1000)
|
|
372
365
|
to_time = current_time_ms
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
366
|
+
|
|
367
|
+
logger.debug(f"get_agent_monitoring_events called with query={query}, from_time={from_time}, to_time={to_time}, size={size}")
|
|
368
|
+
|
|
376
369
|
# Set default time range if not provided
|
|
377
370
|
if not to_time:
|
|
378
371
|
to_time = int(datetime.now().timestamp() * 1000)
|
|
379
|
-
|
|
372
|
+
|
|
380
373
|
if not from_time:
|
|
381
374
|
from_time = to_time - (60 * 60 * 1000) # Default to 1 hour
|
|
382
|
-
|
|
375
|
+
|
|
383
376
|
# Call the agent_monitoring_events method from the SDK
|
|
384
|
-
result =
|
|
377
|
+
result = api_client.agent_monitoring_events(
|
|
385
378
|
to=to_time,
|
|
386
379
|
var_from=from_time,
|
|
387
380
|
window_size=None,
|
|
388
381
|
filter_event_updates=None,
|
|
389
382
|
exclude_triggered_before=None
|
|
390
383
|
)
|
|
391
|
-
|
|
384
|
+
|
|
392
385
|
# Print the raw result for debugging
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
386
|
+
logger.debug(f"Raw API result type: {type(result)}")
|
|
387
|
+
logger.debug(f"Raw API result length: {len(result) if isinstance(result, list) else 'not a list'}")
|
|
388
|
+
|
|
396
389
|
# If there are no events, return early
|
|
397
390
|
if not result or (isinstance(result, list) and len(result) == 0):
|
|
398
391
|
from_date = datetime.fromtimestamp(from_time/1000).strftime('%Y-%m-%d %H:%M:%S')
|
|
@@ -402,17 +395,17 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
402
395
|
"time_range": f"{from_date} to {to_date}",
|
|
403
396
|
"events_count": 0
|
|
404
397
|
}
|
|
405
|
-
|
|
398
|
+
|
|
406
399
|
# Process the events to create a summary
|
|
407
400
|
events = result if isinstance(result, list) else [result]
|
|
408
|
-
|
|
401
|
+
|
|
409
402
|
# Get the total number of events before limiting
|
|
410
403
|
total_events_count = len(events)
|
|
411
|
-
|
|
404
|
+
|
|
412
405
|
# Limit the number of events to process
|
|
413
406
|
events = events[:max_events]
|
|
414
|
-
|
|
415
|
-
|
|
407
|
+
logger.debug(f"Limited to processing {len(events)} events out of {total_events_count} total events")
|
|
408
|
+
|
|
416
409
|
# Convert objects to dictionaries if needed
|
|
417
410
|
event_dicts = []
|
|
418
411
|
for event in events:
|
|
@@ -420,17 +413,17 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
420
413
|
event_dicts.append(event.to_dict())
|
|
421
414
|
else:
|
|
422
415
|
event_dicts.append(event)
|
|
423
|
-
|
|
416
|
+
|
|
424
417
|
# Group events by problem type
|
|
425
418
|
problem_groups = {}
|
|
426
|
-
|
|
419
|
+
|
|
427
420
|
# Process each event
|
|
428
421
|
for event in event_dicts:
|
|
429
422
|
# Extract the monitoring issue from the problem field
|
|
430
423
|
full_problem = event.get("problem", "Unknown")
|
|
431
424
|
# Strip "Monitoring issue: " prefix if present
|
|
432
425
|
problem = full_problem.replace("Monitoring issue: ", "") if "Monitoring issue: " in full_problem else full_problem
|
|
433
|
-
|
|
426
|
+
|
|
434
427
|
# Initialize problem group if not exists
|
|
435
428
|
if problem not in problem_groups:
|
|
436
429
|
problem_groups[problem] = {
|
|
@@ -439,19 +432,19 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
439
432
|
"entity_types": set(),
|
|
440
433
|
"sample_events": []
|
|
441
434
|
}
|
|
442
|
-
|
|
435
|
+
|
|
443
436
|
# Update problem group
|
|
444
437
|
problem_groups[problem]["count"] += 1
|
|
445
|
-
|
|
438
|
+
|
|
446
439
|
# Add entity information
|
|
447
440
|
entity_name = event.get("entityName", "Unknown")
|
|
448
441
|
entity_label = event.get("entityLabel", "Unknown")
|
|
449
442
|
entity_type = event.get("entityType", "Unknown")
|
|
450
|
-
|
|
443
|
+
|
|
451
444
|
entity_info = f"{entity_name} ({entity_label})"
|
|
452
445
|
problem_groups[problem]["affected_entities"].add(entity_info)
|
|
453
446
|
problem_groups[problem]["entity_types"].add(entity_type)
|
|
454
|
-
|
|
447
|
+
|
|
455
448
|
# Add sample event (up to 3 per problem)
|
|
456
449
|
if len(problem_groups[problem]["sample_events"]) < 3:
|
|
457
450
|
simple_event = {
|
|
@@ -462,17 +455,17 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
462
455
|
"severity": event.get("severity", 0)
|
|
463
456
|
}
|
|
464
457
|
problem_groups[problem]["sample_events"].append(simple_event)
|
|
465
|
-
|
|
458
|
+
|
|
466
459
|
# Sort problems by count (most frequent first)
|
|
467
460
|
sorted_problems = sorted(problem_groups.items(), key=lambda x: x[1]["count"], reverse=True)
|
|
468
|
-
|
|
461
|
+
|
|
469
462
|
# Format the time range in a human-readable format
|
|
470
463
|
from_date = datetime.fromtimestamp(from_time/1000).strftime('%Y-%m-%d %H:%M:%S')
|
|
471
464
|
to_date = datetime.fromtimestamp(to_time/1000).strftime('%Y-%m-%d %H:%M:%S')
|
|
472
|
-
|
|
465
|
+
|
|
473
466
|
# Create a detailed analysis of each problem
|
|
474
467
|
problem_analyses = []
|
|
475
|
-
|
|
468
|
+
|
|
476
469
|
# Process each problem
|
|
477
470
|
for problem_name, problem_data in sorted_problems:
|
|
478
471
|
# Create a detailed problem analysis
|
|
@@ -483,9 +476,9 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
483
476
|
"entity_types": list(problem_data["entity_types"]),
|
|
484
477
|
"sample_events": problem_data["sample_events"]
|
|
485
478
|
}
|
|
486
|
-
|
|
479
|
+
|
|
487
480
|
problem_analyses.append(problem_analysis)
|
|
488
|
-
|
|
481
|
+
|
|
489
482
|
# Create a comprehensive analysis
|
|
490
483
|
analysis_result = {
|
|
491
484
|
"summary": f"Analysis based on {len(events)} of {total_events_count} agent monitoring events between {from_date} and {to_date}.",
|
|
@@ -494,38 +487,37 @@ class AgentMonitoringEventsMCPTools(BaseInstanaClient):
|
|
|
494
487
|
"events_analyzed": len(events),
|
|
495
488
|
"problem_analyses": problem_analyses[:10] # Limit to top 10 problems for readability
|
|
496
489
|
}
|
|
497
|
-
|
|
490
|
+
|
|
498
491
|
# Create a more user-friendly text summary for direct display
|
|
499
492
|
markdown_summary = "# Agent Monitoring Events Analysis\n\n"
|
|
500
493
|
markdown_summary += f"Analysis based on {len(events)} of {total_events_count} agent monitoring events between {from_date} and {to_date}.\n\n"
|
|
501
|
-
|
|
494
|
+
|
|
502
495
|
markdown_summary += "## Top Monitoring Issues\n\n"
|
|
503
|
-
|
|
496
|
+
|
|
504
497
|
# Add each problem to the markdown summary
|
|
505
498
|
for problem_analysis in problem_analyses[:5]: # Limit to top 5 for readability
|
|
506
499
|
problem_name = problem_analysis["problem"]
|
|
507
500
|
count = problem_analysis["count"]
|
|
508
|
-
|
|
501
|
+
|
|
509
502
|
markdown_summary += f"### {problem_name} ({count} events)\n\n"
|
|
510
|
-
|
|
503
|
+
|
|
511
504
|
# Add affected entities if available
|
|
512
505
|
if problem_analysis.get("affected_entities"):
|
|
513
506
|
entities = ", ".join(problem_analysis["affected_entities"][:5])
|
|
514
507
|
if len(problem_analysis["affected_entities"]) > 5:
|
|
515
508
|
entities += f" and {len(problem_analysis['affected_entities']) - 5} more"
|
|
516
509
|
markdown_summary += f"**Affected Entities:** {entities}\n\n"
|
|
517
|
-
|
|
510
|
+
|
|
518
511
|
markdown_summary += "\n"
|
|
519
|
-
|
|
512
|
+
|
|
520
513
|
# Add the markdown summary to the result
|
|
521
514
|
analysis_result["markdown_summary"] = markdown_summary
|
|
522
|
-
|
|
515
|
+
|
|
523
516
|
return analysis_result
|
|
524
|
-
|
|
517
|
+
|
|
525
518
|
except Exception as e:
|
|
526
|
-
|
|
527
|
-
import traceback
|
|
528
|
-
traceback.print_exc(file=sys.stderr)
|
|
519
|
+
logger.error(f"Error in get_agent_monitoring_events: {e}", exc_info=True)
|
|
529
520
|
return {
|
|
530
|
-
"error": f"Failed to get agent monitoring events: {
|
|
521
|
+
"error": f"Failed to get agent monitoring events: {e!s}"
|
|
531
522
|
}
|
|
523
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Infrastructure module for MCP Instana
|