mcp-instana 0.1.0__py3-none-any.whl → 0.2.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.
- mcp_instana-0.2.0.dist-info/METADATA +1229 -0
- mcp_instana-0.2.0.dist-info/RECORD +59 -0
- {mcp_instana-0.1.0.dist-info → mcp_instana-0.2.0.dist-info}/WHEEL +1 -1
- mcp_instana-0.2.0.dist-info/entry_points.txt +4 -0
- mcp_instana-0.1.0.dist-info/LICENSE → mcp_instana-0.2.0.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 +628 -0
- src/application/application_catalog.py +155 -0
- src/application/application_global_alert_config.py +653 -0
- src/{client/application_metrics_mcp_tools.py → application/application_metrics.py} +113 -131
- src/{client/application_resources_mcp_tools.py → application/application_resources.py} +131 -151
- src/application/application_settings.py +1731 -0
- src/application/application_topology.py +111 -0
- src/automation/action_catalog.py +416 -0
- src/automation/action_history.py +338 -0
- src/core/__init__.py +1 -0
- src/core/server.py +586 -0
- src/core/utils.py +213 -0
- src/event/__init__.py +1 -0
- src/event/events_tools.py +850 -0
- src/infrastructure/__init__.py +1 -0
- src/{client/infrastructure_analyze_mcp_tools.py → infrastructure/infrastructure_analyze.py} +207 -206
- src/{client/infrastructure_catalog_mcp_tools.py → infrastructure/infrastructure_catalog.py} +197 -265
- src/infrastructure/infrastructure_metrics.py +171 -0
- src/{client/infrastructure_resources_mcp_tools.py → infrastructure/infrastructure_resources.py} +198 -227
- src/{client/infrastructure_topology_mcp_tools.py → infrastructure/infrastructure_topology.py} +110 -109
- src/log/__init__.py +1 -0
- src/log/log_alert_configuration.py +331 -0
- src/prompts/__init__.py +16 -0
- src/prompts/application/__init__.py +1 -0
- src/prompts/application/application_alerts.py +54 -0
- src/prompts/application/application_catalog.py +26 -0
- src/prompts/application/application_metrics.py +57 -0
- src/prompts/application/application_resources.py +26 -0
- src/prompts/application/application_settings.py +75 -0
- src/prompts/application/application_topology.py +30 -0
- src/prompts/events/__init__.py +1 -0
- src/prompts/events/events_tools.py +161 -0
- src/prompts/infrastructure/infrastructure_analyze.py +72 -0
- src/prompts/infrastructure/infrastructure_catalog.py +53 -0
- src/prompts/infrastructure/infrastructure_metrics.py +45 -0
- src/prompts/infrastructure/infrastructure_resources.py +74 -0
- src/prompts/infrastructure/infrastructure_topology.py +38 -0
- src/prompts/settings/__init__.py +0 -0
- src/prompts/settings/custom_dashboard.py +157 -0
- src/prompts/website/__init__.py +1 -0
- src/prompts/website/website_analyze.py +35 -0
- src/prompts/website/website_catalog.py +40 -0
- src/prompts/website/website_configuration.py +105 -0
- src/prompts/website/website_metrics.py +34 -0
- src/settings/__init__.py +1 -0
- src/settings/custom_dashboard_tools.py +417 -0
- src/website/__init__.py +0 -0
- src/website/website_analyze.py +433 -0
- src/website/website_catalog.py +171 -0
- src/website/website_configuration.py +770 -0
- src/website/website_metrics.py +241 -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/events_mcp_tools.py +0 -531
- 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
src/{client/infrastructure_topology_mcp_tools.py → infrastructure/infrastructure_topology.py}
RENAMED
|
@@ -4,93 +4,94 @@ Infrastructure Topology MCP Tools Module
|
|
|
4
4
|
This module provides infrastructure topology-specific MCP tools for Instana monitoring.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
import logging
|
|
7
8
|
import sys
|
|
8
|
-
import
|
|
9
|
-
from typing import Dict, Any, Optional, List, Union
|
|
10
|
-
from datetime import datetime
|
|
9
|
+
from typing import Any, Dict, Optional
|
|
11
10
|
|
|
12
11
|
# Import the necessary classes from the SDK
|
|
13
12
|
try:
|
|
14
|
-
from instana_client.api.infrastructure_topology_api import
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
from instana_client.
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
from instana_client.api.infrastructure_topology_api import (
|
|
14
|
+
InfrastructureTopologyApi, #type: ignore
|
|
15
|
+
)
|
|
16
|
+
from instana_client.api_client import ApiClient #type: ignore
|
|
17
|
+
from instana_client.configuration import Configuration #type: ignore
|
|
18
|
+
|
|
19
|
+
except ImportError:
|
|
20
|
+
import logging
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
logger.error("Failed to import infrastructure topology API", exc_info=True)
|
|
20
23
|
raise
|
|
21
24
|
|
|
22
|
-
from .
|
|
25
|
+
from src.core.utils import BaseInstanaClient, register_as_tool, with_header_auth
|
|
26
|
+
|
|
27
|
+
# Configure logger for this module
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
23
29
|
|
|
24
|
-
# Helper function for debug printing
|
|
25
30
|
def debug_print(*args, **kwargs):
|
|
26
|
-
"""
|
|
27
|
-
|
|
31
|
+
"""
|
|
32
|
+
Print debug information to stderr.
|
|
33
|
+
|
|
34
|
+
This function is used for debugging purposes and prints information to stderr.
|
|
35
|
+
It accepts the same arguments as the built-in print function.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
*args: Variable length argument list to print
|
|
39
|
+
**kwargs: Arbitrary keyword arguments to pass to print function
|
|
40
|
+
"""
|
|
41
|
+
# Use logger.debug instead of direct printing
|
|
42
|
+
message = " ".join(str(arg) for arg in args)
|
|
43
|
+
logger.debug(message)
|
|
28
44
|
|
|
29
45
|
class InfrastructureTopologyMCPTools(BaseInstanaClient):
|
|
30
46
|
"""Tools for infrastructure topology in Instana MCP."""
|
|
31
|
-
|
|
47
|
+
|
|
32
48
|
def __init__(self, read_token: str, base_url: str):
|
|
33
49
|
"""Initialize the Infrastructure Topology MCP tools client."""
|
|
34
50
|
super().__init__(read_token=read_token, base_url=base_url)
|
|
35
|
-
|
|
36
|
-
try:
|
|
37
|
-
|
|
38
|
-
# Configure the API client with the correct base URL and authentication
|
|
39
|
-
configuration = Configuration()
|
|
40
|
-
configuration.host = base_url
|
|
41
|
-
configuration.api_key['ApiKeyAuth'] = read_token
|
|
42
|
-
configuration.api_key_prefix['ApiKeyAuth'] = 'apiToken'
|
|
43
|
-
|
|
44
|
-
# Create an API client with this configuration
|
|
45
|
-
api_client = ApiClient(configuration=configuration)
|
|
46
|
-
|
|
47
|
-
# Initialize the Instana SDK's InfrastructureTopologyApi with our configured client
|
|
48
|
-
self.topo_api = InfrastructureTopologyApi(api_client=api_client)
|
|
49
|
-
except Exception as e:
|
|
50
|
-
debug_print(f"Error initializing InfrastructureTopologyApi: {e}")
|
|
51
|
-
traceback.print_exc(file=sys.stderr)
|
|
52
|
-
raise
|
|
53
|
-
|
|
51
|
+
|
|
54
52
|
@register_as_tool
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
@with_header_auth(InfrastructureTopologyApi)
|
|
54
|
+
async def get_related_hosts(self,
|
|
55
|
+
snapshot_id: str,
|
|
56
|
+
to_time: Optional[int] = None,
|
|
57
|
+
window_size: Optional[int] = None,
|
|
58
|
+
ctx=None,
|
|
59
|
+
api_client=None) -> Dict[str, Any]:
|
|
60
60
|
"""
|
|
61
61
|
Get hosts related to a specific snapshot.
|
|
62
|
-
|
|
63
|
-
This tool retrieves a list of host IDs that are related to the specified snapshot. Use this when you need to
|
|
64
|
-
understand the relationships between infrastructure components, particularly which hosts are connected to
|
|
62
|
+
|
|
63
|
+
This tool retrieves a list of host IDs that are related to the specified snapshot. Use this when you need to
|
|
64
|
+
understand the relationships between infrastructure components, particularly which hosts are connected to
|
|
65
65
|
a specific entity.
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
For example, use this tool when:
|
|
68
68
|
- You need to find all hosts connected to a specific container, process, or service
|
|
69
69
|
- You want to understand the infrastructure dependencies of an application component
|
|
70
70
|
- You're investigating an issue and need to see which hosts might be affected
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
Args:
|
|
73
73
|
snapshot_id: The ID of the snapshot to find related hosts for (required)
|
|
74
74
|
to_time: End timestamp in milliseconds (optional)
|
|
75
75
|
window_size: Window size in milliseconds (optional)
|
|
76
76
|
ctx: The MCP context (optional)
|
|
77
|
-
|
|
77
|
+
api_client: API client for testing (optional)
|
|
78
|
+
|
|
78
79
|
Returns:
|
|
79
80
|
Dictionary containing related hosts information or error information
|
|
80
81
|
"""
|
|
81
82
|
try:
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
logger.debug(f"get_related_hosts called with snapshot_id={snapshot_id}")
|
|
84
|
+
|
|
84
85
|
if not snapshot_id:
|
|
85
86
|
return {"error": "snapshot_id parameter is required"}
|
|
86
|
-
|
|
87
|
+
|
|
87
88
|
# Call the get_related_hosts method from the SDK
|
|
88
|
-
result =
|
|
89
|
+
result = api_client.get_related_hosts(
|
|
89
90
|
snapshot_id=snapshot_id,
|
|
90
91
|
to=to_time,
|
|
91
92
|
window_size=window_size
|
|
92
93
|
)
|
|
93
|
-
|
|
94
|
+
|
|
94
95
|
# Convert the result to a dictionary
|
|
95
96
|
if isinstance(result, list):
|
|
96
97
|
result_dict = {
|
|
@@ -101,52 +102,53 @@ class InfrastructureTopologyMCPTools(BaseInstanaClient):
|
|
|
101
102
|
else:
|
|
102
103
|
# For any other type, convert to string representation
|
|
103
104
|
result_dict = {"data": str(result), "snapshotId": snapshot_id}
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
|
|
106
|
+
logger.debug(f"Result from get_related_hosts: {result_dict}")
|
|
106
107
|
return result_dict
|
|
107
|
-
|
|
108
|
+
|
|
108
109
|
except Exception as e:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
traceback.print_exc(file=sys.stderr)
|
|
112
|
-
return {"error": f"Failed to get related hosts: {str(e)}"}
|
|
110
|
+
logger.error(f"Error in get_related_hosts: {e}", exc_info=True)
|
|
111
|
+
return {"error": f"Failed to get related hosts: {e!s}"}
|
|
113
112
|
|
|
114
113
|
@register_as_tool
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
114
|
+
@with_header_auth(InfrastructureTopologyApi)
|
|
115
|
+
async def get_topology(self,
|
|
116
|
+
include_data: Optional[bool] = False,
|
|
117
|
+
ctx=None,
|
|
118
|
+
api_client=None) -> Dict[str, Any]:
|
|
118
119
|
"""
|
|
119
120
|
Get the infrastructure topology information.
|
|
120
|
-
|
|
121
|
-
This tool retrieves the complete infrastructure topology from Instana, showing how all monitored entities
|
|
121
|
+
|
|
122
|
+
This tool retrieves the complete infrastructure topology from Instana, showing how all monitored entities
|
|
122
123
|
are connected. Use this when you need a comprehensive view of your infrastructure's relationships and dependencies.
|
|
123
|
-
|
|
124
|
-
The topology includes nodes (representing entities like hosts, processes, containers) and edges (representing
|
|
124
|
+
|
|
125
|
+
The topology includes nodes (representing entities like hosts, processes, containers) and edges (representing
|
|
125
126
|
connections between entities). This is useful for understanding the overall structure of your environment.
|
|
126
|
-
|
|
127
|
+
|
|
127
128
|
For example, use this tool when:
|
|
128
129
|
- You need a complete map of your infrastructure
|
|
129
130
|
- You want to understand how components are connected
|
|
130
131
|
- You're analyzing dependencies between systems
|
|
131
132
|
- You need to visualize your infrastructure's architecture
|
|
132
|
-
|
|
133
|
+
|
|
133
134
|
Args:
|
|
134
135
|
include_data: Whether to include detailed snapshot data in nodes (optional, default: False)
|
|
135
136
|
ctx: The MCP context (optional)
|
|
136
|
-
|
|
137
|
+
api_client: API client for testing (optional)
|
|
138
|
+
|
|
137
139
|
Returns:
|
|
138
140
|
Dictionary containing infrastructure topology information with detailed summary or error information
|
|
139
141
|
"""
|
|
140
142
|
try:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
#
|
|
143
|
+
logger.debug(f"get_topology called - using include_data={include_data}")
|
|
144
|
+
|
|
145
|
+
# Use the API client from the decorator
|
|
144
146
|
try:
|
|
145
|
-
result =
|
|
146
|
-
|
|
147
|
+
result = api_client.get_topology(include_data=include_data)
|
|
148
|
+
logger.debug("SDK call successful, processing result")
|
|
147
149
|
except Exception as sdk_error:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
+
logger.error(f"SDK validation error: {sdk_error}")
|
|
151
|
+
|
|
150
152
|
# If it's a validation error, try to extract useful information from the error
|
|
151
153
|
if "validation error" in str(sdk_error).lower():
|
|
152
154
|
return {
|
|
@@ -158,45 +160,45 @@ class InfrastructureTopologyMCPTools(BaseInstanaClient):
|
|
|
158
160
|
else:
|
|
159
161
|
# Re-raise if it's not a validation error
|
|
160
162
|
raise sdk_error
|
|
161
|
-
|
|
163
|
+
|
|
162
164
|
# Convert the result to a dictionary
|
|
163
165
|
result_dict = None
|
|
164
|
-
|
|
166
|
+
|
|
165
167
|
# Try different ways to convert the result
|
|
166
168
|
if hasattr(result, 'to_dict'):
|
|
167
169
|
try:
|
|
168
170
|
result_dict = result.to_dict()
|
|
169
|
-
|
|
171
|
+
logger.debug("Successfully converted result using to_dict()")
|
|
170
172
|
except Exception as e:
|
|
171
|
-
|
|
172
|
-
|
|
173
|
+
logger.error(f"to_dict() failed: {e}")
|
|
174
|
+
|
|
173
175
|
if result_dict is None and isinstance(result, dict):
|
|
174
176
|
result_dict = result
|
|
175
|
-
|
|
176
|
-
|
|
177
|
+
logger.debug("Result is already a dictionary")
|
|
178
|
+
|
|
177
179
|
if result_dict is None:
|
|
178
180
|
# Try to extract data from the result object manually
|
|
179
181
|
try:
|
|
180
182
|
if hasattr(result, '__dict__'):
|
|
181
183
|
result_dict = result.__dict__
|
|
182
|
-
|
|
184
|
+
logger.debug("Extracted data using __dict__")
|
|
183
185
|
else:
|
|
184
186
|
result_dict = {"data": str(result)}
|
|
185
|
-
|
|
187
|
+
logger.debug("Converted result to string representation")
|
|
186
188
|
except Exception as e:
|
|
187
|
-
|
|
189
|
+
logger.error(f"Manual extraction failed: {e}")
|
|
188
190
|
result_dict = {"data": str(result)}
|
|
189
|
-
|
|
191
|
+
|
|
190
192
|
# Process the result if we have valid data
|
|
191
193
|
if isinstance(result_dict, dict) and ('nodes' in result_dict or 'data' in result_dict):
|
|
192
194
|
nodes = result_dict.get('nodes', [])
|
|
193
195
|
edges = result_dict.get('edges', [])
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
196
|
+
|
|
197
|
+
logger.debug(f"Processing {len(nodes)} nodes and {len(edges)} edges")
|
|
198
|
+
|
|
197
199
|
# If we have no nodes but have data, try to extract from data field
|
|
198
200
|
if not nodes and 'data' in result_dict:
|
|
199
|
-
|
|
201
|
+
logger.debug("No nodes found, checking data field")
|
|
200
202
|
return {
|
|
201
203
|
"summary": {
|
|
202
204
|
"status": "Data retrieved but in unexpected format",
|
|
@@ -206,60 +208,60 @@ class InfrastructureTopologyMCPTools(BaseInstanaClient):
|
|
|
206
208
|
"rawDataAvailable": True,
|
|
207
209
|
"note": "Topology data was retrieved but not in the expected nodes/edges format"
|
|
208
210
|
}
|
|
209
|
-
|
|
211
|
+
|
|
210
212
|
# Take only first 30 nodes for analysis to avoid token limits
|
|
211
213
|
sample_nodes = nodes[:30] if len(nodes) > 30 else nodes
|
|
212
214
|
sample_edges = edges[:30] if len(edges) > 30 else edges
|
|
213
|
-
|
|
215
|
+
|
|
214
216
|
# Count nodes by plugin type from sample
|
|
215
217
|
plugin_counts = {}
|
|
216
218
|
host_info = {}
|
|
217
219
|
kubernetes_resources = {}
|
|
218
220
|
sample_nodes_details = []
|
|
219
|
-
|
|
221
|
+
|
|
220
222
|
for node in sample_nodes:
|
|
221
223
|
if not isinstance(node, dict):
|
|
222
224
|
continue
|
|
223
|
-
|
|
225
|
+
|
|
224
226
|
plugin = node.get('plugin', 'unknown')
|
|
225
227
|
plugin_counts[plugin] = plugin_counts.get(plugin, 0) + 1
|
|
226
|
-
|
|
228
|
+
|
|
227
229
|
# Keep minimal node info for sample
|
|
228
230
|
node_label = str(node.get('label', 'unknown'))
|
|
229
231
|
if len(node_label) > 40:
|
|
230
232
|
node_label = node_label[:37] + "..."
|
|
231
|
-
|
|
233
|
+
|
|
232
234
|
node_id = str(node.get('id', ''))
|
|
233
235
|
if len(node_id) > 15:
|
|
234
236
|
node_id = node_id[:12] + "..."
|
|
235
|
-
|
|
237
|
+
|
|
236
238
|
sample_nodes_details.append({
|
|
237
239
|
'plugin': plugin,
|
|
238
240
|
'label': node_label,
|
|
239
241
|
'id': node_id
|
|
240
242
|
})
|
|
241
|
-
|
|
243
|
+
|
|
242
244
|
# Extract host information
|
|
243
245
|
if plugin == 'host':
|
|
244
246
|
label = str(node.get('label', 'unknown'))
|
|
245
247
|
host_info[label] = str(node.get('id', ''))
|
|
246
|
-
|
|
248
|
+
|
|
247
249
|
# Group Kubernetes resources
|
|
248
250
|
if plugin.startswith('kubernetes'):
|
|
249
251
|
k8s_type = plugin.replace('kubernetes', '').lower()
|
|
250
252
|
if k8s_type not in kubernetes_resources:
|
|
251
253
|
kubernetes_resources[k8s_type] = 0
|
|
252
254
|
kubernetes_resources[k8s_type] += 1
|
|
253
|
-
|
|
255
|
+
|
|
254
256
|
# Estimate total counts based on sample
|
|
255
257
|
sample_size = len(sample_nodes)
|
|
256
258
|
total_size = len(nodes)
|
|
257
259
|
scaling_factor = total_size / sample_size if sample_size > 0 else 1
|
|
258
|
-
|
|
260
|
+
|
|
259
261
|
estimated_plugin_counts = {}
|
|
260
262
|
for plugin, count in plugin_counts.items():
|
|
261
263
|
estimated_plugin_counts[plugin] = int(count * scaling_factor)
|
|
262
|
-
|
|
264
|
+
|
|
263
265
|
# Create comprehensive summary
|
|
264
266
|
summary = {
|
|
265
267
|
'totalNodes': len(nodes),
|
|
@@ -269,7 +271,7 @@ class InfrastructureTopologyMCPTools(BaseInstanaClient):
|
|
|
269
271
|
'scalingFactor': round(scaling_factor, 2),
|
|
270
272
|
'note': f'Analysis based on first {sample_size} nodes out of {total_size} total'
|
|
271
273
|
},
|
|
272
|
-
'topPluginTypes': dict(
|
|
274
|
+
'topPluginTypes': dict(sorted(estimated_plugin_counts.items(), key=lambda x: x[1], reverse=True)[:10]),
|
|
273
275
|
'infrastructureOverview': {
|
|
274
276
|
'estimatedHosts': int(len(host_info) * scaling_factor),
|
|
275
277
|
'sampleHosts': list(host_info.keys())[:3], # Show first 3 hosts
|
|
@@ -278,7 +280,7 @@ class InfrastructureTopologyMCPTools(BaseInstanaClient):
|
|
|
278
280
|
'estimatedProcesses': int(plugin_counts.get('process', 0) * scaling_factor)
|
|
279
281
|
}
|
|
280
282
|
}
|
|
281
|
-
|
|
283
|
+
|
|
282
284
|
# Add edge analysis from sample if available
|
|
283
285
|
if sample_edges:
|
|
284
286
|
edge_types = {}
|
|
@@ -286,13 +288,13 @@ class InfrastructureTopologyMCPTools(BaseInstanaClient):
|
|
|
286
288
|
if isinstance(edge, dict):
|
|
287
289
|
edge_type = edge.get('type', 'unknown')
|
|
288
290
|
edge_types[edge_type] = edge_types.get(edge_type, 0) + 1
|
|
289
|
-
|
|
291
|
+
|
|
290
292
|
if edge_types:
|
|
291
293
|
summary['connectionAnalysis'] = {
|
|
292
294
|
'sampleEdgeTypes': edge_types,
|
|
293
295
|
'sampleEdgesAnalyzed': len(sample_edges)
|
|
294
296
|
}
|
|
295
|
-
|
|
297
|
+
|
|
296
298
|
# Return compact summary
|
|
297
299
|
return {
|
|
298
300
|
'summary': summary,
|
|
@@ -307,13 +309,12 @@ class InfrastructureTopologyMCPTools(BaseInstanaClient):
|
|
|
307
309
|
"availableKeys": list(result_dict.keys()) if isinstance(result_dict, dict) else "Not a dictionary",
|
|
308
310
|
"suggestion": "The topology data may be in a different format than expected"
|
|
309
311
|
}
|
|
310
|
-
|
|
312
|
+
|
|
311
313
|
except Exception as e:
|
|
312
|
-
|
|
313
|
-
import traceback
|
|
314
|
-
traceback.print_exc(file=sys.stderr)
|
|
314
|
+
logger.error(f"Error in get_topology: {e}", exc_info=True)
|
|
315
315
|
return {
|
|
316
|
-
"error": f"Failed to get topology: {
|
|
316
|
+
"error": f"Failed to get topology: {e!s}",
|
|
317
317
|
"errorType": type(e).__name__,
|
|
318
318
|
"suggestion": "This may be due to API response format changes or network issues"
|
|
319
319
|
}
|
|
320
|
+
|
src/log/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Log module for MCP Instana
|