holmesgpt 0.13.2__py3-none-any.whl → 0.18.4__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.
- holmes/__init__.py +3 -5
- holmes/clients/robusta_client.py +20 -6
- holmes/common/env_vars.py +58 -3
- holmes/common/openshift.py +1 -1
- holmes/config.py +123 -148
- holmes/core/conversations.py +71 -15
- holmes/core/feedback.py +191 -0
- holmes/core/investigation.py +31 -39
- holmes/core/investigation_structured_output.py +3 -3
- holmes/core/issue.py +1 -1
- holmes/core/llm.py +508 -88
- holmes/core/models.py +108 -4
- holmes/core/openai_formatting.py +14 -1
- holmes/core/prompt.py +48 -3
- holmes/core/runbooks.py +1 -0
- holmes/core/safeguards.py +8 -6
- holmes/core/supabase_dal.py +295 -100
- holmes/core/tool_calling_llm.py +489 -428
- holmes/core/tools.py +325 -56
- holmes/core/tools_utils/token_counting.py +21 -0
- holmes/core/tools_utils/tool_context_window_limiter.py +40 -0
- holmes/core/tools_utils/tool_executor.py +0 -13
- holmes/core/tools_utils/toolset_utils.py +1 -0
- holmes/core/toolset_manager.py +191 -5
- holmes/core/tracing.py +19 -3
- holmes/core/transformers/__init__.py +23 -0
- holmes/core/transformers/base.py +63 -0
- holmes/core/transformers/llm_summarize.py +175 -0
- holmes/core/transformers/registry.py +123 -0
- holmes/core/transformers/transformer.py +32 -0
- holmes/core/truncation/compaction.py +94 -0
- holmes/core/truncation/dal_truncation_utils.py +23 -0
- holmes/core/truncation/input_context_window_limiter.py +219 -0
- holmes/interactive.py +228 -31
- holmes/main.py +23 -40
- holmes/plugins/interfaces.py +2 -1
- holmes/plugins/prompts/__init__.py +2 -1
- holmes/plugins/prompts/_fetch_logs.jinja2 +31 -6
- holmes/plugins/prompts/_general_instructions.jinja2 +1 -2
- holmes/plugins/prompts/_runbook_instructions.jinja2 +24 -12
- holmes/plugins/prompts/base_user_prompt.jinja2 +7 -0
- holmes/plugins/prompts/conversation_history_compaction.jinja2 +89 -0
- holmes/plugins/prompts/generic_ask.jinja2 +0 -4
- holmes/plugins/prompts/generic_ask_conversation.jinja2 +0 -1
- holmes/plugins/prompts/generic_ask_for_issue_conversation.jinja2 +0 -1
- holmes/plugins/prompts/generic_investigation.jinja2 +0 -1
- holmes/plugins/prompts/investigation_procedure.jinja2 +50 -1
- holmes/plugins/prompts/kubernetes_workload_ask.jinja2 +0 -1
- holmes/plugins/prompts/kubernetes_workload_chat.jinja2 +0 -1
- holmes/plugins/runbooks/__init__.py +145 -17
- holmes/plugins/runbooks/catalog.json +2 -0
- holmes/plugins/sources/github/__init__.py +4 -2
- holmes/plugins/sources/prometheus/models.py +1 -0
- holmes/plugins/toolsets/__init__.py +44 -27
- holmes/plugins/toolsets/aks-node-health.yaml +46 -0
- holmes/plugins/toolsets/aks.yaml +64 -0
- holmes/plugins/toolsets/atlas_mongodb/mongodb_atlas.py +38 -47
- holmes/plugins/toolsets/azure_sql/apis/alert_monitoring_api.py +3 -2
- holmes/plugins/toolsets/azure_sql/apis/azure_sql_api.py +2 -1
- holmes/plugins/toolsets/azure_sql/apis/connection_failure_api.py +3 -2
- holmes/plugins/toolsets/azure_sql/apis/connection_monitoring_api.py +3 -1
- holmes/plugins/toolsets/azure_sql/apis/storage_analysis_api.py +3 -1
- holmes/plugins/toolsets/azure_sql/azure_sql_toolset.py +12 -13
- holmes/plugins/toolsets/azure_sql/tools/analyze_connection_failures.py +15 -12
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_connections.py +15 -12
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_health_status.py +11 -11
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_performance.py +11 -9
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_storage.py +15 -12
- holmes/plugins/toolsets/azure_sql/tools/get_active_alerts.py +15 -15
- holmes/plugins/toolsets/azure_sql/tools/get_slow_queries.py +11 -8
- holmes/plugins/toolsets/azure_sql/tools/get_top_cpu_queries.py +11 -8
- holmes/plugins/toolsets/azure_sql/tools/get_top_data_io_queries.py +11 -8
- holmes/plugins/toolsets/azure_sql/tools/get_top_log_io_queries.py +11 -8
- holmes/plugins/toolsets/azure_sql/utils.py +0 -32
- holmes/plugins/toolsets/bash/argocd/__init__.py +3 -3
- holmes/plugins/toolsets/bash/aws/__init__.py +4 -4
- holmes/plugins/toolsets/bash/azure/__init__.py +4 -4
- holmes/plugins/toolsets/bash/bash_toolset.py +11 -15
- holmes/plugins/toolsets/bash/common/bash.py +23 -13
- holmes/plugins/toolsets/bash/common/bash_command.py +1 -1
- holmes/plugins/toolsets/bash/common/stringify.py +1 -1
- holmes/plugins/toolsets/bash/kubectl/__init__.py +2 -1
- holmes/plugins/toolsets/bash/kubectl/constants.py +0 -1
- holmes/plugins/toolsets/bash/kubectl/kubectl_get.py +3 -4
- holmes/plugins/toolsets/bash/parse_command.py +12 -13
- holmes/plugins/toolsets/cilium.yaml +284 -0
- holmes/plugins/toolsets/connectivity_check.py +124 -0
- holmes/plugins/toolsets/coralogix/api.py +132 -119
- holmes/plugins/toolsets/coralogix/coralogix.jinja2 +14 -0
- holmes/plugins/toolsets/coralogix/toolset_coralogix.py +219 -0
- holmes/plugins/toolsets/coralogix/utils.py +15 -79
- holmes/plugins/toolsets/datadog/datadog_api.py +525 -26
- holmes/plugins/toolsets/datadog/datadog_logs_instructions.jinja2 +55 -11
- holmes/plugins/toolsets/datadog/datadog_metrics_instructions.jinja2 +3 -3
- holmes/plugins/toolsets/datadog/datadog_models.py +59 -0
- holmes/plugins/toolsets/datadog/datadog_url_utils.py +213 -0
- holmes/plugins/toolsets/datadog/instructions_datadog_traces.jinja2 +165 -28
- holmes/plugins/toolsets/datadog/toolset_datadog_general.py +417 -241
- holmes/plugins/toolsets/datadog/toolset_datadog_logs.py +234 -214
- holmes/plugins/toolsets/datadog/toolset_datadog_metrics.py +167 -79
- holmes/plugins/toolsets/datadog/toolset_datadog_traces.py +374 -363
- holmes/plugins/toolsets/elasticsearch/__init__.py +6 -0
- holmes/plugins/toolsets/elasticsearch/elasticsearch.py +834 -0
- holmes/plugins/toolsets/elasticsearch/opensearch_ppl_query_docs.jinja2 +1616 -0
- holmes/plugins/toolsets/elasticsearch/opensearch_query_assist.py +78 -0
- holmes/plugins/toolsets/elasticsearch/opensearch_query_assist_instructions.jinja2 +223 -0
- holmes/plugins/toolsets/git.py +54 -50
- holmes/plugins/toolsets/grafana/base_grafana_toolset.py +16 -4
- holmes/plugins/toolsets/grafana/common.py +13 -29
- holmes/plugins/toolsets/grafana/grafana_tempo_api.py +455 -0
- holmes/plugins/toolsets/grafana/loki/instructions.jinja2 +25 -0
- holmes/plugins/toolsets/grafana/loki/toolset_grafana_loki.py +191 -0
- holmes/plugins/toolsets/grafana/loki_api.py +4 -0
- holmes/plugins/toolsets/grafana/toolset_grafana.py +293 -89
- holmes/plugins/toolsets/grafana/toolset_grafana_dashboard.jinja2 +49 -0
- holmes/plugins/toolsets/grafana/toolset_grafana_tempo.jinja2 +246 -11
- holmes/plugins/toolsets/grafana/toolset_grafana_tempo.py +820 -292
- holmes/plugins/toolsets/grafana/trace_parser.py +4 -3
- holmes/plugins/toolsets/internet/internet.py +15 -16
- holmes/plugins/toolsets/internet/notion.py +9 -11
- holmes/plugins/toolsets/investigator/core_investigation.py +44 -36
- holmes/plugins/toolsets/investigator/model.py +3 -1
- holmes/plugins/toolsets/json_filter_mixin.py +134 -0
- holmes/plugins/toolsets/kafka.py +36 -42
- holmes/plugins/toolsets/kubernetes.yaml +317 -113
- holmes/plugins/toolsets/kubernetes_logs.py +9 -9
- holmes/plugins/toolsets/kubernetes_logs.yaml +32 -0
- holmes/plugins/toolsets/logging_utils/logging_api.py +94 -8
- holmes/plugins/toolsets/mcp/toolset_mcp.py +218 -64
- holmes/plugins/toolsets/newrelic/new_relic_api.py +165 -0
- holmes/plugins/toolsets/newrelic/newrelic.jinja2 +65 -0
- holmes/plugins/toolsets/newrelic/newrelic.py +320 -0
- holmes/plugins/toolsets/openshift.yaml +283 -0
- holmes/plugins/toolsets/prometheus/prometheus.py +1202 -421
- holmes/plugins/toolsets/prometheus/prometheus_instructions.jinja2 +54 -5
- holmes/plugins/toolsets/prometheus/utils.py +28 -0
- holmes/plugins/toolsets/rabbitmq/api.py +23 -4
- holmes/plugins/toolsets/rabbitmq/toolset_rabbitmq.py +13 -14
- holmes/plugins/toolsets/robusta/robusta.py +239 -68
- holmes/plugins/toolsets/robusta/robusta_instructions.jinja2 +26 -9
- holmes/plugins/toolsets/runbook/runbook_fetcher.py +157 -27
- holmes/plugins/toolsets/service_discovery.py +1 -1
- holmes/plugins/toolsets/servicenow_tables/instructions.jinja2 +83 -0
- holmes/plugins/toolsets/servicenow_tables/servicenow_tables.py +426 -0
- holmes/plugins/toolsets/utils.py +88 -0
- holmes/utils/config_utils.py +91 -0
- holmes/utils/connection_utils.py +31 -0
- holmes/utils/console/result.py +10 -0
- holmes/utils/default_toolset_installation_guide.jinja2 +1 -22
- holmes/utils/env.py +7 -0
- holmes/utils/file_utils.py +2 -1
- holmes/utils/global_instructions.py +60 -11
- holmes/utils/holmes_status.py +6 -4
- holmes/utils/holmes_sync_toolsets.py +0 -2
- holmes/utils/krr_utils.py +188 -0
- holmes/utils/log.py +15 -0
- holmes/utils/markdown_utils.py +2 -3
- holmes/utils/memory_limit.py +58 -0
- holmes/utils/sentry_helper.py +64 -0
- holmes/utils/stream.py +69 -8
- holmes/utils/tags.py +4 -3
- holmes/version.py +37 -15
- holmesgpt-0.18.4.dist-info/LICENSE +178 -0
- {holmesgpt-0.13.2.dist-info → holmesgpt-0.18.4.dist-info}/METADATA +35 -31
- holmesgpt-0.18.4.dist-info/RECORD +258 -0
- holmes/core/performance_timing.py +0 -72
- holmes/plugins/toolsets/aws.yaml +0 -80
- holmes/plugins/toolsets/coralogix/toolset_coralogix_logs.py +0 -112
- holmes/plugins/toolsets/datadog/datadog_traces_formatter.py +0 -310
- holmes/plugins/toolsets/datadog/toolset_datadog_rds.py +0 -739
- holmes/plugins/toolsets/grafana/grafana_api.py +0 -42
- holmes/plugins/toolsets/grafana/tempo_api.py +0 -124
- holmes/plugins/toolsets/grafana/toolset_grafana_loki.py +0 -110
- holmes/plugins/toolsets/newrelic.py +0 -231
- holmes/plugins/toolsets/opensearch/opensearch.py +0 -257
- holmes/plugins/toolsets/opensearch/opensearch_logs.py +0 -161
- holmes/plugins/toolsets/opensearch/opensearch_traces.py +0 -218
- holmes/plugins/toolsets/opensearch/opensearch_traces_instructions.jinja2 +0 -12
- holmes/plugins/toolsets/opensearch/opensearch_utils.py +0 -166
- holmes/plugins/toolsets/servicenow/install.md +0 -37
- holmes/plugins/toolsets/servicenow/instructions.jinja2 +0 -3
- holmes/plugins/toolsets/servicenow/servicenow.py +0 -219
- holmes/utils/keygen_utils.py +0 -6
- holmesgpt-0.13.2.dist-info/LICENSE.txt +0 -21
- holmesgpt-0.13.2.dist-info/RECORD +0 -234
- /holmes/plugins/toolsets/{opensearch → newrelic}/__init__.py +0 -0
- {holmesgpt-0.13.2.dist-info → holmesgpt-0.18.4.dist-info}/WHEEL +0 -0
- {holmesgpt-0.13.2.dist-info → holmesgpt-0.18.4.dist-info}/entry_points.txt +0 -0
|
@@ -1,11 +1,40 @@
|
|
|
1
1
|
|
|
2
2
|
# Prometheus/PromQL queries
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
{%- if config and config.prometheus_url and "coralogix" in config.prometheus_url %}
|
|
5
|
+
You are using Coralogix Prometheus.
|
|
6
|
+
* Metrics/labels may differ; discover names with `get_metric_names` first.
|
|
7
|
+
* For high-cardinality, wrap with `topk(5, <query>)`.
|
|
8
|
+
* Always include explicit time ranges for range queries.
|
|
9
|
+
* Example: `container_cpu_utilization{namespace="test-173"}` can fail if the label is named differently (e.g., `k8s_namespace_name`) or the metric is named differently. Do not assume names—only use labels you have seen returned or been told exist.
|
|
10
|
+
{%- endif %}
|
|
11
|
+
|
|
12
|
+
## Efficient Metric Discovery (when needed)
|
|
13
|
+
* When you need to discover metrics, use `get_metric_names` with filters - it's the fastest method
|
|
14
|
+
* Combine multiple patterns with regex OR (|) to reduce API calls:
|
|
15
|
+
- `{__name__=~"node_cpu.*|node_memory.*|node_disk.*"}` - get all node resource metrics in one call
|
|
16
|
+
- `{__name__=~"container.*|pod.*|kube.*"}` - get all Kubernetes-related metrics
|
|
17
|
+
- `{namespace=~"example1|example2|example3"}` - metrics from multiple namespaces
|
|
18
|
+
* Use `get_metric_metadata` after discovering names to get types/descriptions if needed
|
|
19
|
+
* Use `get_label_values` to discover pods, namespaces, jobs: e.g., get_label_values(label="pod")
|
|
20
|
+
* Only use `get_series` when you need full label sets (slower than other methods)
|
|
21
|
+
|
|
22
|
+
## Retrying queries that return too much data
|
|
23
|
+
* When a Prometheus query returns too much data (e.g., truncation error), you MUST retry with a more specific query or less data points or topk/bottomk
|
|
24
|
+
* NEVER EVER EVER answer a question based on Prometheus data that was truncated as you might be missing important information and give the totally wrong answer
|
|
25
|
+
* Prefer telling the user you can't answer the question because of too much data rather than answering based on incomplete data
|
|
26
|
+
* You are also able to show graphs to the user (using the promql embed functionality mentioned below) so you can show users graphs and THEY can interpret the data themselves, even if you can't answer.
|
|
27
|
+
* Do NOT hestitate to try alternative queries and try to reduce the amount of data returned until you get a successful query
|
|
28
|
+
* Be extremely, extremely cautious when answering based on get_label_values because the existence of a label value says NOTHING about the metric value itself (is it high, low, or perhaps the label exists in Prometheus but its an older series not present right now)
|
|
29
|
+
* DO NOT give answers about metrics based on what 'is typically the case' or 'common knowledge' - if you can't see the actual metric value, you MUST NEVER EVER answer about it - just tell the user your limitations due to the size of the data
|
|
30
|
+
|
|
31
|
+
## Alert Investigation & Query Execution
|
|
32
|
+
* When investigating a Prometheus alert, ALWAYS call list_prometheus_rules to get the alert definition
|
|
4
33
|
* Use Prometheus to query metrics from the alert promql
|
|
5
34
|
* Use prometheus to execute promql queries with the tools `execute_prometheus_instant_query` and `execute_prometheus_range_query`
|
|
6
35
|
* To create queries, use 'start_timestamp' and 'end_timestamp' as graphs start and end times
|
|
7
36
|
* ALWAYS embed the execution results into your answer
|
|
8
|
-
* You only need to embed the partial result in your response. Include the "tool_name" and "
|
|
37
|
+
* You only need to embed the partial result in your response. Include the "tool_name" and "tool_call_id". For example: << {"type": "promql", "tool_name": "execute_prometheus_range_query", "tool_call_id": "92jf2hf"} >>
|
|
9
38
|
* Use these tools to generate charts that users can see. Here are standard metrics but you can use different ones:
|
|
10
39
|
** For memory consumption: `container_memory_working_set_bytes`
|
|
11
40
|
** For CPU usage: `container_cpu_usage_seconds_total`
|
|
@@ -16,9 +45,29 @@
|
|
|
16
45
|
** Avoid global averages like `sum(rate(<metric>_sum)) / sum(rate(<metric>_count))` because it hides data and is not generally informative
|
|
17
46
|
* Timestamps MUST be in string date format. For example: '2025-03-15 10:10:08.610862+00:00'
|
|
18
47
|
* Post processing will parse your response, re-run the query from the tool output and create a chart visible to the user
|
|
19
|
-
*
|
|
48
|
+
* When unsure about available metrics, use `get_metric_names` with appropriate filters (combine multiple patterns with | for efficiency). Then use `get_metric_metadata` if you need descriptions/types
|
|
20
49
|
* Check that any node, service, pod, container, app, namespace, etc. mentioned in the query exist in the kubernetes cluster before making a query. Use any appropriate kubectl tool(s) for this
|
|
21
50
|
* The toolcall will return no data to you. That is expected. You MUST however ensure that the query is successful.
|
|
51
|
+
|
|
52
|
+
## Handling High-Cardinality Metrics
|
|
53
|
+
* CRITICAL: When querying metrics that may return many time series (>10), ALWAYS use aggregation to limit results
|
|
54
|
+
* ALWAYS use `topk()` or `bottomk()` to limit the number of series returned
|
|
55
|
+
* Standard pattern for high-cardinality queries:
|
|
56
|
+
- Use `topk(5, <your_query>)` to get the top 5 series
|
|
57
|
+
- Example: `topk(5, rate(container_cpu_usage_seconds_total{namespace="example"}[5m]))`
|
|
58
|
+
- This prevents context overflow and focuses on the most relevant data
|
|
59
|
+
* To also capture the aggregate of remaining series as "other":
|
|
60
|
+
```
|
|
61
|
+
topk(5, rate(container_cpu_usage_seconds_total{namespace="example"}[5m])) or label_replace((sum(rate(container_cpu_usage_seconds_total{namespace="example"}[5m])) - sum(topk(5, rate(container_cpu_usage_seconds_total{namespace="example"}[5m])))), "pod", "other", "", "")
|
|
62
|
+
```
|
|
63
|
+
* Common high-cardinality scenarios requiring topk():
|
|
64
|
+
- Pod-level metrics in namespaces with many pods
|
|
65
|
+
- Container-level CPU/memory metrics
|
|
66
|
+
- HTTP metrics with many endpoints or status codes
|
|
67
|
+
- Any query returning more than 10 time series
|
|
68
|
+
* For initial exploration, you may use instant queries with `count()` to check cardinality:
|
|
69
|
+
- Example: `count(count by (pod) (container_cpu_usage_seconds_total{namespace="example"}))`
|
|
70
|
+
- If count > 10, use topk() in your range query
|
|
22
71
|
* When doing queries, always extend the time range, to 15 min before and after the alert start time
|
|
23
72
|
* ALWAYS embed the execution results into your answer
|
|
24
73
|
* ALWAYS embed a Prometheus graph in the response. The graph should visualize data related to the incident.
|
|
@@ -26,9 +75,9 @@
|
|
|
26
75
|
* When embedding multiple graphs, always add line spacing between them
|
|
27
76
|
For example:
|
|
28
77
|
|
|
29
|
-
<<{"type": "promql", "tool_name": "execute_prometheus_range_query", "
|
|
78
|
+
<<{"type": "promql", "tool_name": "execute_prometheus_range_query", "tool_call_id": "lBaA"}>>
|
|
30
79
|
|
|
31
|
-
<<{"type": "promql", "tool_name": "execute_prometheus_range_query", "
|
|
80
|
+
<<{"type": "promql", "tool_name": "execute_prometheus_range_query", "tool_call_id": "IKtq"}>>
|
|
32
81
|
|
|
33
82
|
{%- if config and config.additional_labels and config.additional_labels.keys()|list|length > 0 %}
|
|
34
83
|
* ALWAYS add the following additional labels to ALL PromQL queries:
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Optional, Union
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def parse_duration_to_seconds(v: Optional[Union[str, float, int]]) -> Optional[float]:
|
|
6
|
+
if v is None:
|
|
7
|
+
return None
|
|
8
|
+
if isinstance(v, (int, float)):
|
|
9
|
+
return float(v)
|
|
10
|
+
s = v.strip().lower()
|
|
11
|
+
if s.isdigit():
|
|
12
|
+
return float(int(s))
|
|
13
|
+
|
|
14
|
+
units = {"s": 1, "m": 60, "h": 3600, "d": 86400}
|
|
15
|
+
|
|
16
|
+
# Check for partial time formats (e.g., 1h30m, 5m12s, 1d2h30m)
|
|
17
|
+
pattern = r"(\d+(?:\.\d+)?)(d|h|m|s)"
|
|
18
|
+
matches = re.findall(pattern, s)
|
|
19
|
+
|
|
20
|
+
if matches:
|
|
21
|
+
total_seconds = 0.0
|
|
22
|
+
for value_str, unit in matches:
|
|
23
|
+
value = float(value_str)
|
|
24
|
+
total_seconds += value * units[unit]
|
|
25
|
+
return float(int(total_seconds))
|
|
26
|
+
|
|
27
|
+
# fallback: try float seconds
|
|
28
|
+
return float(s)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
from enum import Enum
|
|
2
1
|
import logging
|
|
2
|
+
from enum import Enum
|
|
3
3
|
from typing import Any, Dict, List, Optional, Set
|
|
4
4
|
from urllib.parse import urljoin, urlparse
|
|
5
5
|
|
|
6
6
|
import backoff
|
|
7
|
-
from pydantic import BaseModel
|
|
8
7
|
import requests # type: ignore
|
|
8
|
+
from pydantic import BaseModel, ConfigDict, model_validator
|
|
9
9
|
from requests.auth import HTTPBasicAuth # type: ignore
|
|
10
10
|
|
|
11
11
|
# --- Enums and Pydantic Models (Mostly Unchanged) ---
|
|
@@ -17,12 +17,31 @@ class ClusterConnectionStatus(str, Enum):
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class RabbitMQClusterConfig(BaseModel):
|
|
20
|
+
model_config = ConfigDict(extra="allow")
|
|
21
|
+
|
|
20
22
|
id: str = "rabbitmq" # must be unique
|
|
21
23
|
management_url: str # e.g., http://rabbitmq-service:15672
|
|
22
24
|
username: Optional[str] = None
|
|
23
25
|
password: Optional[str] = None
|
|
24
26
|
request_timeout_seconds: int = 30
|
|
25
|
-
|
|
27
|
+
verify_ssl: bool = True
|
|
28
|
+
|
|
29
|
+
@model_validator(mode="after")
|
|
30
|
+
def handle_deprecated_fields(self):
|
|
31
|
+
extra = self.model_extra or {}
|
|
32
|
+
deprecated = []
|
|
33
|
+
|
|
34
|
+
# Map old name to new name
|
|
35
|
+
if "verify_certs" in extra:
|
|
36
|
+
self.verify_ssl = extra["verify_certs"]
|
|
37
|
+
deprecated.append("verify_certs -> verify_ssl")
|
|
38
|
+
|
|
39
|
+
if deprecated:
|
|
40
|
+
logging.warning(
|
|
41
|
+
f"RabbitMQ config uses deprecated field names: {', '.join(deprecated)}. "
|
|
42
|
+
"Please update your configuration."
|
|
43
|
+
)
|
|
44
|
+
return self
|
|
26
45
|
|
|
27
46
|
# For internal use
|
|
28
47
|
connection_status: Optional[ClusterConnectionStatus] = None
|
|
@@ -111,7 +130,7 @@ def make_request(
|
|
|
111
130
|
params=params,
|
|
112
131
|
json=data,
|
|
113
132
|
timeout=config.request_timeout_seconds,
|
|
114
|
-
verify=config.
|
|
133
|
+
verify=config.verify_ssl,
|
|
115
134
|
)
|
|
116
135
|
response.raise_for_status()
|
|
117
136
|
return response.json()
|
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import logging
|
|
2
|
+
import os
|
|
3
3
|
from typing import Any, List, Optional, Tuple
|
|
4
|
+
from urllib.parse import urljoin
|
|
4
5
|
|
|
5
6
|
from pydantic import BaseModel
|
|
7
|
+
from requests import RequestException # type: ignore
|
|
8
|
+
|
|
6
9
|
from holmes.core.tools import (
|
|
7
10
|
CallablePrerequisite,
|
|
8
11
|
StructuredToolResult,
|
|
12
|
+
StructuredToolResultStatus,
|
|
9
13
|
Tool,
|
|
14
|
+
ToolInvokeContext,
|
|
10
15
|
ToolParameter,
|
|
11
|
-
ToolResultStatus,
|
|
12
16
|
Toolset,
|
|
13
17
|
ToolsetTag,
|
|
14
18
|
)
|
|
15
|
-
from requests import RequestException # type: ignore
|
|
16
|
-
from urllib.parse import urljoin
|
|
17
|
-
|
|
18
19
|
from holmes.plugins.toolsets.rabbitmq.api import (
|
|
19
20
|
ClusterConnectionStatus,
|
|
20
21
|
RabbitMQClusterConfig,
|
|
@@ -63,9 +64,7 @@ class ListConfiguredClusters(BaseRabbitMQTool):
|
|
|
63
64
|
toolset=toolset,
|
|
64
65
|
)
|
|
65
66
|
|
|
66
|
-
def _invoke(
|
|
67
|
-
self, params: dict, user_approved: bool = False
|
|
68
|
-
) -> StructuredToolResult:
|
|
67
|
+
def _invoke(self, params: dict, context: ToolInvokeContext) -> StructuredToolResult:
|
|
69
68
|
if not self.toolset.config:
|
|
70
69
|
raise ValueError("RabbitMQ is not configured.")
|
|
71
70
|
|
|
@@ -79,7 +78,7 @@ class ListConfiguredClusters(BaseRabbitMQTool):
|
|
|
79
78
|
if c.connection_status == ClusterConnectionStatus.SUCCESS
|
|
80
79
|
]
|
|
81
80
|
return StructuredToolResult(
|
|
82
|
-
status=
|
|
81
|
+
status=StructuredToolResultStatus.SUCCESS, data=available_clusters
|
|
83
82
|
)
|
|
84
83
|
|
|
85
84
|
def get_parameterized_one_liner(self, params) -> str:
|
|
@@ -103,21 +102,21 @@ class GetRabbitMQClusterStatus(BaseRabbitMQTool):
|
|
|
103
102
|
toolset=toolset,
|
|
104
103
|
)
|
|
105
104
|
|
|
106
|
-
def _invoke(
|
|
107
|
-
self, params: dict, user_approved: bool = False
|
|
108
|
-
) -> StructuredToolResult:
|
|
105
|
+
def _invoke(self, params: dict, context: ToolInvokeContext) -> StructuredToolResult:
|
|
109
106
|
try:
|
|
110
107
|
# Fetch node details which include partition info
|
|
111
108
|
cluster_config = self._get_cluster_config(
|
|
112
109
|
cluster_id=params.get("cluster_id")
|
|
113
110
|
)
|
|
114
111
|
result = get_cluster_status(cluster_config)
|
|
115
|
-
return StructuredToolResult(
|
|
112
|
+
return StructuredToolResult(
|
|
113
|
+
status=StructuredToolResultStatus.SUCCESS, data=result
|
|
114
|
+
)
|
|
116
115
|
|
|
117
116
|
except Exception as e:
|
|
118
117
|
logging.info("Failed to process RabbitMQ cluster status", exc_info=True)
|
|
119
118
|
return StructuredToolResult(
|
|
120
|
-
status=
|
|
119
|
+
status=StructuredToolResultStatus.ERROR,
|
|
121
120
|
error=f"Unexpected error fetching RabbitMQ cluster status: {str(e)}",
|
|
122
121
|
data=None,
|
|
123
122
|
)
|