mcp-instana 0.1.0__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.
@@ -0,0 +1,377 @@
1
+ """
2
+ Application Metrics MCP Tools Module
3
+
4
+ This module provides application metrics-specific MCP tools for Instana monitoring.
5
+ """
6
+
7
+ import sys
8
+ import traceback
9
+ from typing import Dict, Any, Optional, List, Union
10
+ from datetime import datetime
11
+
12
+ # Import the necessary classes from the SDK
13
+ try:
14
+ from instana_client.api.application_metrics_api import ApplicationMetricsApi
15
+ from instana_client.api_client import ApiClient
16
+ from instana_client.configuration import Configuration
17
+ from instana_client.models.get_application_metrics import GetApplicationMetrics
18
+ from instana_client.models.get_applications import GetApplications
19
+ from instana_client.models.get_endpoints import GetEndpoints
20
+ from instana_client.models.get_services import GetServices
21
+ except ImportError as e:
22
+ print(f"Error importing Instana SDK: {e}", file=sys.stderr)
23
+ traceback.print_exc(file=sys.stderr)
24
+ raise
25
+
26
+ from .instana_client_base import BaseInstanaClient, register_as_tool
27
+
28
+ # Helper function for debug printing
29
+ def debug_print(*args, **kwargs):
30
+ """Print debug information to stderr instead of stdout"""
31
+ print(*args, file=sys.stderr, **kwargs)
32
+
33
+ class ApplicationMetricsMCPTools(BaseInstanaClient):
34
+ """Tools for application metrics in Instana MCP."""
35
+
36
+ def __init__(self, read_token: str, base_url: str):
37
+ """Initialize the Application Metrics MCP tools client."""
38
+ super().__init__(read_token=read_token, base_url=base_url)
39
+
40
+ try:
41
+
42
+ # Configure the API client with the correct base URL and authentication
43
+ configuration = Configuration()
44
+ configuration.host = base_url
45
+ configuration.api_key['ApiKeyAuth'] = read_token
46
+ configuration.api_key_prefix['ApiKeyAuth'] = 'apiToken'
47
+
48
+ # Create an API client with this configuration
49
+ api_client = ApiClient(configuration=configuration)
50
+
51
+ # Initialize the Instana SDK's ApplicationMetricsApi with our configured client
52
+ self.metrics_api = ApplicationMetricsApi(api_client=api_client)
53
+ except Exception as e:
54
+ debug_print(f"Error initializing ApplicationMetricsApi: {e}")
55
+ traceback.print_exc(file=sys.stderr)
56
+ raise
57
+
58
+ @register_as_tool
59
+ async def get_application_data_metrics_v2(self,
60
+ metrics: Optional[List[Dict[str, Any]]] = None,
61
+ time_frame: Optional[Dict[str, int]] = None,
62
+ application_id: Optional[str] = None,
63
+ service_id: Optional[str] = None,
64
+ endpoint_id: Optional[str] = None,
65
+ ctx=None) -> Dict[str, Any]:
66
+ """
67
+ Get application data metrics using the v2 API.
68
+
69
+ This API endpoint retrieves one or more supported aggregations of metrics for a combination of entities.
70
+ For example, retrieve MEAN aggregation of latency metric for an Endpoint, Service, and Application.
71
+
72
+ Args:
73
+ metrics: List of metrics to retrieve with their aggregations
74
+ Example: [{"metric": "latency", "aggregation": "MEAN"}]
75
+ time_frame: Dictionary with 'from' and 'to' timestamps in milliseconds
76
+ Example: {"from": 1617994800000, "to": 1618081200000}
77
+ application_id: ID of the application to get metrics for (optional)
78
+ service_id: ID of the service to get metrics for (optional)
79
+ endpoint_id: ID of the endpoint to get metrics for (optional)
80
+ ctx: The MCP context (optional)
81
+
82
+ Returns:
83
+ Dictionary containing metrics data or error information
84
+ """
85
+ try:
86
+ debug_print(f"get_application_data_metrics_v2 called with application_id={application_id}, service_id={service_id}, endpoint_id={endpoint_id}")
87
+
88
+ # Set default time range if not provided
89
+ if not time_frame:
90
+ to_time = int(datetime.now().timestamp() * 1000)
91
+ from_time = to_time - (60 * 60 * 1000) # Default to 1 hour
92
+ time_frame = {
93
+ "from": from_time,
94
+ "to": to_time
95
+ }
96
+
97
+ # Set default metrics if not provided
98
+ if not metrics:
99
+ metrics = [
100
+ {
101
+ "metric": "latency",
102
+ "aggregation": "MEAN"
103
+ }
104
+ ]
105
+
106
+ # Create the request body
107
+ request_body = {
108
+ "metrics": metrics,
109
+ "timeFrame": time_frame
110
+ }
111
+
112
+ # Add entity IDs if provided
113
+ if application_id:
114
+ request_body["applicationId"] = application_id
115
+ if service_id:
116
+ request_body["serviceId"] = service_id
117
+ if endpoint_id:
118
+ request_body["endpointId"] = endpoint_id
119
+
120
+ # Create the GetApplicationMetrics object
121
+ get_app_metrics = GetApplicationMetrics(**request_body)
122
+
123
+ # Call the get_application_data_metrics_v2 method from the SDK
124
+ result = self.metrics_api.get_application_data_metrics_v2(
125
+ get_application_metrics=get_app_metrics
126
+ )
127
+
128
+ # Convert the result to a dictionary
129
+ if hasattr(result, 'to_dict'):
130
+ result_dict = result.to_dict()
131
+ else:
132
+ # If it's already a dict or another format, use it as is
133
+ result_dict = result
134
+
135
+ debug_print(f"Result from get_application_data_metrics_v2: {result_dict}")
136
+ return result_dict
137
+ except Exception as e:
138
+ debug_print(f"Error in get_application_data_metrics_v2: {e}")
139
+ traceback.print_exc(file=sys.stderr)
140
+ return {"error": f"Failed to get application data metrics: {str(e)}"}
141
+
142
+ @register_as_tool
143
+ async def get_application_metrics(self,
144
+ application_ids: Optional[List[str]] = None,
145
+ metrics: Optional[List[Dict[str, str]]] = None,
146
+ time_frame: Optional[Dict[str, int]] = None,
147
+ fill_time_series: Optional[bool] = True,
148
+ ctx=None) -> Dict[str, Any]:
149
+ """
150
+ Get metrics for specific applications.
151
+
152
+ This API endpoint retrieves one or more supported aggregations of metrics for an Application Perspective.
153
+
154
+ Args:
155
+ application_ids: List of application IDs to get metrics for
156
+ metrics: List of metrics to retrieve with their aggregations
157
+ Example: [{"metric": "latency", "aggregation": "MEAN"}]
158
+ time_frame: Dictionary with 'from' and 'to' timestamps in milliseconds
159
+ Example: {"from": 1617994800000, "to": 1618081200000}
160
+ fill_time_series: Whether to fill missing data points with timestamp and value 0
161
+ ctx: The MCP context (optional)
162
+
163
+ Returns:
164
+ Dictionary containing application metrics data or error information
165
+ """
166
+ try:
167
+ debug_print(f"get_application_metrics called with application_ids={application_ids}")
168
+
169
+ # Set default time range if not provided
170
+ if not time_frame:
171
+ to_time = int(datetime.now().timestamp() * 1000)
172
+ from_time = to_time - (60 * 60 * 1000) # Default to 1 hour
173
+ time_frame = {
174
+ "from": from_time,
175
+ "to": to_time
176
+ }
177
+
178
+ # Set default metrics if not provided
179
+ if not metrics:
180
+ metrics = [
181
+ {
182
+ "metric": "latency",
183
+ "aggregation": "MEAN"
184
+ }
185
+ ]
186
+
187
+ # Create the request body
188
+ request_body = {
189
+ "metrics": metrics,
190
+ "timeFrame": time_frame
191
+ }
192
+
193
+ # Add application IDs if provided
194
+ if application_ids:
195
+ request_body["applicationIds"] = application_ids
196
+
197
+ # Create the GetApplications object
198
+ get_applications = GetApplications(**request_body)
199
+
200
+ # Call the get_application_metrics method from the SDK
201
+ result = self.metrics_api.get_application_metrics(
202
+ fill_time_series=fill_time_series,
203
+ get_applications=get_applications
204
+ )
205
+
206
+ # Convert the result to a dictionary
207
+ if hasattr(result, 'to_dict'):
208
+ result_dict = result.to_dict()
209
+ else:
210
+ # If it's already a dict or another format, use it as is
211
+ result_dict = result
212
+
213
+ debug_print(f"Result from get_application_metrics: {result_dict}")
214
+ return result_dict
215
+ except Exception as e:
216
+ debug_print(f"Error in get_application_metrics: {e}")
217
+ traceback.print_exc(file=sys.stderr)
218
+ return {"error": f"Failed to get application metrics: {str(e)}"}
219
+
220
+ @register_as_tool
221
+ async def get_endpoints_metrics(self,
222
+ endpoint_ids: Optional[List[str]] = None,
223
+ metrics: Optional[List[Dict[str, str]]] = None,
224
+ time_frame: Optional[Dict[str, int]] = None,
225
+ fill_time_series: Optional[bool] = True,
226
+ ctx=None) -> Dict[str, Any]:
227
+ """
228
+ Get metrics for specific endpoints.
229
+
230
+ This API endpoint retrieves one or more supported aggregations of metrics for an Endpoint.
231
+
232
+ Args:
233
+ endpoint_ids: List of endpoint IDs to get metrics for
234
+ metrics: List of metrics to retrieve with their aggregations
235
+ Example: [{"metric": "latency", "aggregation": "MEAN"}]
236
+ time_frame: Dictionary with 'from' and 'to' timestamps in milliseconds
237
+ Example: {"from": 1617994800000, "to": 1618081200000}
238
+ fill_time_series: Whether to fill missing data points with timestamp and value 0
239
+ ctx: The MCP context (optional)
240
+
241
+ Returns:
242
+ Dictionary containing endpoint metrics data or error information
243
+ """
244
+ try:
245
+ debug_print(f"get_endpoints_metrics called with endpoint_ids={endpoint_ids}")
246
+
247
+ # Set default time range if not provided
248
+ if not time_frame:
249
+ to_time = int(datetime.now().timestamp() * 1000)
250
+ from_time = to_time - (60 * 60 * 1000) # Default to 1 hour
251
+ time_frame = {
252
+ "from": from_time,
253
+ "to": to_time
254
+ }
255
+
256
+ # Set default metrics if not provided
257
+ if not metrics:
258
+ metrics = [
259
+ {
260
+ "metric": "latency",
261
+ "aggregation": "MEAN"
262
+ }
263
+ ]
264
+
265
+ # Create the request body
266
+ request_body = {
267
+ "metrics": metrics,
268
+ "timeFrame": time_frame
269
+ }
270
+
271
+ # Add endpoint IDs if provided
272
+ if endpoint_ids:
273
+ request_body["endpointIds"] = endpoint_ids
274
+
275
+ # Create the GetEndpoints object
276
+ get_endpoints = GetEndpoints(**request_body)
277
+
278
+ # Call the get_endpoints_metrics method from the SDK
279
+ result = self.metrics_api.get_endpoints_metrics(
280
+ fill_time_series=fill_time_series,
281
+ get_endpoints=get_endpoints
282
+ )
283
+
284
+ # Convert the result to a dictionary
285
+ if hasattr(result, 'to_dict'):
286
+ result_dict = result.to_dict()
287
+ else:
288
+ # If it's already a dict or another format, use it as is
289
+ result_dict = result
290
+
291
+ debug_print(f"Result from get_endpoints_metrics: {result_dict}")
292
+ return result_dict
293
+ except Exception as e:
294
+ debug_print(f"Error in get_endpoints_metrics: {e}")
295
+ traceback.print_exc(file=sys.stderr)
296
+ return {"error": f"Failed to get endpoints metrics: {str(e)}"}
297
+
298
+ @register_as_tool
299
+ async def get_services_metrics(self,
300
+ service_ids: Optional[List[str]] = None,
301
+ metrics: Optional[List[Dict[str, str]]] = None,
302
+ time_frame: Optional[Dict[str, int]] = None,
303
+ fill_time_series: Optional[bool] = True,
304
+ include_snapshot_ids: Optional[bool] = False,
305
+ ctx=None) -> Dict[str, Any]:
306
+ """
307
+ Get metrics for specific services.
308
+
309
+ This API endpoint retrieves one or more supported aggregations of metrics for a Service.
310
+
311
+ Args:
312
+ service_ids: List of service IDs to get metrics for
313
+ metrics: List of metrics to retrieve with their aggregations
314
+ Example: [{"metric": "latency", "aggregation": "MEAN"}]
315
+ time_frame: Dictionary with 'from' and 'to' timestamps in milliseconds
316
+ Example: {"from": 1617994800000, "to": 1618081200000}
317
+ fill_time_series: Whether to fill missing data points with timestamp and value 0
318
+ include_snapshot_ids: Whether to include snapshot IDs in the results
319
+ ctx: The MCP context (optional)
320
+
321
+ Returns:
322
+ Dictionary containing service metrics data or error information
323
+ """
324
+ try:
325
+ debug_print(f"get_services_metrics called with service_ids={service_ids}")
326
+
327
+ # Set default time range if not provided
328
+ if not time_frame:
329
+ to_time = int(datetime.now().timestamp() * 1000)
330
+ from_time = to_time - (60 * 60 * 1000) # Default to 1 hour
331
+ time_frame = {
332
+ "from": from_time,
333
+ "to": to_time
334
+ }
335
+
336
+ # Set default metrics if not provided
337
+ if not metrics:
338
+ metrics = [
339
+ {
340
+ "metric": "latency",
341
+ "aggregation": "MEAN"
342
+ }
343
+ ]
344
+
345
+ # Create the request body
346
+ request_body = {
347
+ "metrics": metrics,
348
+ "timeFrame": time_frame
349
+ }
350
+
351
+ # Add service IDs if provided
352
+ if service_ids:
353
+ request_body["serviceIds"] = service_ids
354
+
355
+ # Create the GetServices object
356
+ get_services = GetServices(**request_body)
357
+
358
+ # Call the get_services_metrics method from the SDK
359
+ result = self.metrics_api.get_services_metrics(
360
+ fill_time_series=fill_time_series,
361
+ include_snapshot_ids=include_snapshot_ids,
362
+ get_services=get_services
363
+ )
364
+
365
+ # Convert the result to a dictionary
366
+ if hasattr(result, 'to_dict'):
367
+ result_dict = result.to_dict()
368
+ else:
369
+ # If it's already a dict or another format, use it as is
370
+ result_dict = result
371
+
372
+ debug_print(f"Result from get_services_metrics: {result_dict}")
373
+ return result_dict
374
+ except Exception as e:
375
+ debug_print(f"Error in get_services_metrics: {e}")
376
+ traceback.print_exc(file=sys.stderr)
377
+ return {"error": f"Failed to get services metrics: {str(e)}"}