Skip to content

Json mixin for tools - #1276

Closed
aantn wants to merge 5 commits into
masterfrom
codex/linear-mention-rob-39-update-grafana-tool-to-handle-large-2mkyd9
Closed

aantn wants to merge 5 commits into
masterfrom
codex/linear-mention-rob-39-update-grafana-tool-to-handle-large-2mkyd9

Conversation

@aantn

@aantn aantn commented Dec 30, 2025 •

Copy link
Copy Markdown
Collaborator

Summary

  • add optional jsonpath/jq filtering and depth truncation to Grafana dashboard fetch tools
  • document response-size controls and add regression tests for filters and truncation
  • add jsonpath-ng and jq dependencies and refresh poetry.lock
  • add LLM eval (app-170) that provisions a Grafana instance with a nested dashboard to validate filtered responses, now generating a large dashboard at test time
  • track recommended evals for this branch in evals_per_branch.json
  • refactor Grafana dashboard tools to reuse a shared JSON filter mixin for consistent param injection and filtering
  • apply the shared JSON filter mixin to OpenSearch status tools and return JSON-friendly data for filtering

Testing

  • poetry run pytest tests/plugins/toolsets/grafana/test_dashboard_filters.py --cov-config=pyproject.toml --cov=holmes --cov-fail-under=0

Codex Task

Summary by CodeRabbit

  • New Features

    • JSON filtering for tool responses: max_depth (truncation), jsonpath and jq extraction; filters run before truncation.
  • Documentation

    • Added "Controlling response size" guidance for dashboard tooling.
  • Tests

    • Added unit and integration tests, fixtures and deployment manifests covering dashboard filtering and error cases.
  • Chores

    • Added runtime support for jq and jsonpath libraries.

✏️ Tip: You can customize this high-level summary in your review settings.

Signed-off-by: Codex <codex@openai.com>
@github-actions

github-actions Bot commented Dec 30, 2025 •

Copy link
Copy Markdown
Contributor

✅ Results of HolmesGPT evals

Automatically triggered by commit b24cdd9

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 36.6s 5 13 $0.1571
✅ 101_loki_historical_logs_pod_deleted 52.2s 7 13 $0.1824
✅ 111_pod_names_contain_service 39.8s 6 14 $0.1619
✅ 12_job_crashing 41.8s 6 15 $0.1704
✅ 162_get_runbooks 82.5s 8 17 $0.2389
✅ 176_network_policy_blocking_traffic_no_runbooks 47.0s 7 15 $0.1879
✅ 24_misconfigured_pvc 47.5s 7 17 $0.1809
✅ 43_current_datetime_from_prompt 4.1s 1 — $0.0616
✅ 61_exact_match_counting 12.1s 3 3 $0.0854
Total 40.4s avg 5.6 avg 13.4 avg $1.4266

📖 Legend
Icon Meaning
✅ The test was successful
➖ The test was skipped
⚠️ The test failed but is known to be flaky or known to fail
🚧 The test had a setup failure (not a code regression)
🔧 The test failed due to mock data issues (not a code regression)
🚫 The test was throttled by API rate limits/overload
❌ The test failed and should be fixed before merging the PR
🔄 Re-run evals manually

⚠️ Warning: Manual re-runs have NO default markers and will run ALL LLM tests (~100+), which can take 1+ hours. Use markers: regression or filter: test_name to limit scope.

Option 1: Comment on this PR with /eval:

/eval
markers: regression

Or with more options (one per line):

/eval
model: gpt-4o
markers: regression
filter: 09_crashpod
iterations: 5
Option Description
model Model(s) to test (default: same as automatic runs)
markers Pytest markers (no default - runs all tests!)
filter Pytest -k filter
iterations Number of runs, max 10

Option 2: Trigger via GitHub Actions UI → "Run workflow"

🏷️ Valid markers
  • chain-of-causation
  • compaction
  • context_window
  • coralogix
  • counting
  • database
  • datadog
  • datetime
  • easy
  • embeds
  • grafana-dashboard
  • hard
  • kafka
  • kubernetes
  • leaked-information
  • logs
  • loki
  • medium
  • metrics
  • network
  • newrelic
  • no-cicd
  • numerical
  • one-test
  • port-forward
  • prometheus
  • question-answer
  • regression
  • runbooks
  • slackbot
  • storage
  • toolset-limitation
  • traces
  • transparency
📋 Valid eval names (use with filter)

test_ask_holmes:

  • 01_how_many_pods
  • 02_what_is_wrong_with_pod
  • 03_what_is_the_command_to_port_forward
  • 04_related_k8s_events
  • 05_image_version
  • 06_explain_issue
  • 07_high_latency
  • 08_sock_shop_frontend
  • 09_crashpod
  • 100a_loki_historical_logs
  • 100b_loki_historical_logs_nonstandard_label
  • 101_loki_historical_logs_pod_deleted
  • 102_loki_label_discovery
  • 102a_loki_logs_transparency
  • 102b_loki_multiple_pods
  • 103_logs_transparency_default_limit
  • 104a_postgres_root_issue
  • 104b_postgres_missing_index_pgstat
  • 104c_postgres_minimal_missing_index
  • 105_redis_wrong_data_structure
  • 107_log_filter_http_status_code
  • 108_logs_nearby_lines
  • 109_logs_transparency_not_found
  • 10_image_pull_backoff
  • 110_cpu_graph_robusta_runner
  • 110_k8s_events_image_pull
  • 111_disabled_datadog_traces
  • 111_pod_names_contain_service
  • 111_tool_hallucination
  • 112_find_pvcs_by_uuid
  • 114_checkout_latency_tracing_rebuild
  • 115_checkout_errors_tracing
  • 117_new_relic_tracing
  • 117b_new_relic_block_embed
  • 118_new_relic_logs
  • 119_new_relic_metrics
  • 11_init_containers
  • 120_new_relic_traces2
  • 121_new_relic_checkout_errors_tracing
  • 122_new_relic_checkout_latency_tracing_rebuild
  • 123_new_relic_checkout_errors_tracing
  • 124_checkout_latency_prometheus
  • 12_job_crashing
  • 13a_pending_node_selector_basic
  • 13b_pending_node_selector_detailed
  • 14_pending_resources
  • 151_disabled_toolsets_fallback_only
  • 156_kafka_opensearch_latency
  • 157_disk_full_statefulset
  • 158_slack_chat_correct_date
  • 159_prometheus_high_cardinality_cpu
  • 15_failed_readiness_probe
  • 160_electricity_market_bidding_bug
  • 160a_cpu_per_namespace_graph
  • 160b_cpu_per_namespace_graph_with_prom_truncation
  • 160c_cpu_per_namespace_graph_with_global_truncation
  • 161_bidding_version_performance
  • 161_conversation_compaction
  • 162_get_runbooks
  • 163_compaction_follow_up
  • 164_datadog_traces_coupon_code
  • 165_alert_with_multiple_runbooks
  • 16_failed_no_toolset_found
  • 170_grafana_dashboard_filters
  • 173_coralogix_logs
  • 174_coralogix_traces_ad
  • 175_coralogix_metrics_frontend
  • 176_network_policy_blocking_traffic_no_runbooks
  • 177_grafana_home_dashboard
  • 178_grafana_search_dashboard_query
  • 179_grafana_big_dashboard_query
  • 17_oom_kill
  • 18_oom_kill_from_issues_history
  • 19_detect_missing_app_details
  • 20_long_log_file_search
  • 21_job_fail_curl_no_svc_account
  • 22_high_latency_dbi_down
  • 23_app_error_in_current_logs
  • 24_misconfigured_pvc
  • 25_misconfigured_ingress_class
  • 26_page_render_times
  • 27a_multi_container_logs
  • 27b_multi_container_logs
  • 28_permissions_error
  • 30_basic_promql_graph_cluster_memory
  • 32_basic_promql_graph_pod_cpu
  • 33_cpu_metrics_discovery
  • 34_memory_graph
  • 35_tempo
  • 36_argocd_find_resource
  • 37_argocd_wrong_namespace
  • 38_rabbitmq_split_head
  • 39_failed_toolset
  • 41_setup_argo
  • 42_dns_issues_result_all_tools
  • 42_dns_issues_result_new_tools
  • 42_dns_issues_result_new_tools_no_runbook
  • 42_dns_issues_result_old_tools
  • 42_dns_issues_steps_new_all_tools
  • 42_dns_issues_steps_new_tools
  • 42_dns_issues_steps_old_tools
  • 43_current_datetime_from_prompt
  • 43_slack_deployment_logs
  • 44_slack_statefulset_logs
  • 45_fetch_deployment_logs_simple
  • 46_job_crashing_no_longer_exists
  • 47_truncated_logs_context_window
  • 48_logs_since_thursday
  • 49_logs_since_last_week
  • 50_logs_since_specific_date
  • 50a_logs_since_last_specific_month
  • 51_logs_summarize_errors
  • 52_logs_login_issues
  • 53_logs_find_term
  • 54_azure_sql
  • 54_not_truncated_when_getting_pods
  • 55_kafka_runbook
  • 57_cluster_name_confusion
  • 57_wrong_namespace
  • 58_counting_pods_by_status
  • 59_label_based_counting
  • 60_count_less_than
  • 61_exact_match_counting
  • 62_fetch_error_logs_with_errors
  • 63_fetch_error_logs_no_errors
  • 64_keda_vs_hpa_confusion
  • 65_health_check_followup
  • 66_http_error_needle
  • 67_performance_degradation
  • 68_cascading_failures
  • 69_rate_limit_exhaustion
  • 70_memory_leak_detection
  • 71_connection_pool_starvation
  • 73a_time_window_anomaly
  • 73b_time_window_anomaly
  • 74_config_change_impact
  • 75_network_flapping
  • 76_service_discovery_issue
  • 77_liveness_probe_misconfiguration
  • 78a_missing_cpu_limits
  • 78b_cpu_quota_exceeded
  • 79_configmap_mount_issue
  • 80_pvc_storage_class_mismatch
  • 81_service_account_permission_denied
  • 82_pod_anti_affinity_conflict
  • 83_secret_not_found
  • 84_network_policy_blocking_traffic
  • 85_hpa_not_scaling
  • 86_configmap_like_but_secret
  • 89_runbook_missing_cloudwatch
  • 90_runbook_basic_selection
  • 91a_datadog_metrics_missing_namespace
  • 91b_datadog_metrics_pod_exists
  • 91c_datadog_metrics_deployment
  • 91d_datadog_metrics_historical_pod
  • 91e_datadog_custom_metrics
  • 91f_datadog_logs_historical_pod
  • 91g_datadog_metrics_mismatched_pod
  • 91h_datadog_logs_empty_query_with_url
  • 91i_datadog_metrics_empty_query_with_url
  • 92_cpu_graph_conversation
  • 93_calling_datadog
  • 93_events_since_specific_date
  • 94_runbook_transparency
  • 95_runbook_memory_leak_detection
  • 96_no_matching_runbook
  • 97_logs_clarification_needed
  • 99_logs_transparency_custom_time

test_investigate:

  • 01_oom_kill
  • 02_crashloop_backoff
  • 03_cpu_throttling
  • 04_image_pull_backoff
  • 05_crashpod
  • 06_job_failure
  • 07_job_syntax_error
  • 08_memory_pressure
  • 09_high_latency
  • 10_KubeDeploymentReplicasMismatch
  • 11_KubePodCrashLooping
  • 12_KubePodNotReady
  • 13_Watchdog
  • 14_tempo
  • 15_dns_resolution
  • 16_dns_resolution_no_tool
  • 17_investigate_correct_date

@coderabbitai

coderabbitai Bot commented Dec 30, 2025 •

Copy link
Copy Markdown
Contributor

Walkthrough

Adds a JsonFilterMixin that provides jsonpath, jq, and depth-truncation controls and integrates it into Grafana, OpenSearch, and Coralogix tools; updates docs, tests, fixtures, and runtime deps to exercise and document response-size filtering.

Changes

Cohort / File(s) Summary
Core Filtering Infrastructure
holmes/plugins/toolsets/json_filter_mixin.py
New JsonFilterMixin implementing extend_parameters() and filter_result(), with helpers for max_depth truncation, jsonpath and jq extraction, safe parsing, error handling, and logging.
Grafana Toolset Integration
holmes/plugins/toolsets/grafana/toolset_grafana.py
GetDashboardByUID and GetHomeDashboard now inherit JsonFilterMixin, use extend_parameters() for parameters, call self.filter_result(result, params) before returning, and propagate URL from filtered results.
OpenSearch Toolset Integration
holmes/plugins/toolsets/opensearch/opensearch.py
Added JsonFilterMixin to ListShards, GetClusterSettings, GetClusterHealth, ListOpenSearchHosts; constructors use extend_parameters(); tools return JSON-friendly structures and pass them through filter_result().
Coralogix Tool Integration
holmes/plugins/toolsets/coralogix/toolset_coralogix.py
ExecuteDataPrimeQuery now mixes in JsonFilterMixin and returns filtered StructuredToolResult (data as dict instead of pretty-printed string).
Documentation
docs/data-sources/builtin-toolsets/grafanadashboards.md
Added "Controlling response size" section documenting max_depth, jsonpath, and jq controls and that filters are applied before truncation.
Runtime Dependencies
pyproject.toml
Added runtime dependencies: jq and jsonpath-ng.
Unit Tests
tests/plugins/toolsets/grafana/test_dashboard_filters.py
New tests covering truncation, jsonpath/jq application order, invalid-expression error handling, and integration with a mocked Grafana request.
E2E Test Fixtures
tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/...
Added generate_dashboard.py, grafana.yaml, test_case.yaml, toolsets.yaml to build a large dashboard fixture, deploy Grafana, run filtering tests, and tear down.
Test Index
evals_per_branch.json
Added reference to the new Grafana dashboard filter fixture path tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client/Invoker
    participant Tool as Tool (Grafana / OpenSearch / Coralogix)
    participant Remote as Remote API
    participant Filter as JsonFilterMixin
    participant Result as StructuredToolResult

    Client->>Tool: invoke(params)
    Tool->>Remote: fetch raw data (HTTP API)
    Remote-->>Tool: raw JSON / object
    Note right of Tool: wrap response in StructuredToolResult
    Tool->>Filter: filter_result(result, params)

    rect rgb(220,240,255)
        Note over Filter: Extraction Phase (applied first)
        Filter->>Filter: parse string → JSON (if needed)
        Filter->>Filter: apply jsonpath (optional)
        Filter->>Filter: apply jq (optional)
    end

    rect rgb(240,220,255)
        Note over Filter: Truncation Phase
        Filter->>Filter: truncate to max_depth (optional)
    end

    alt success
        Filter-->>Tool: filtered StructuredToolResult
        Tool->>Client: return filtered result (url adjusted if applicable)
    else error
        Filter-->>Tool: ERROR StructuredToolResult (message)
        Tool->>Client: return error result
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • moshemorad

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.63% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Json mixin for tools' accurately summarizes the primary change: introducing a reusable JSON filter mixin applied across multiple toolsets (Grafana, OpenSearch, Coralogix) to provide consistent filtering and depth truncation capabilities.

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd8a435 and 8ca3b82.

📒 Files selected for processing (2)
  • holmes/plugins/toolsets/coralogix/toolset_coralogix.py
  • pyproject.toml
🚧 Files skipped from review as they are similar to previous changes (1)
  • pyproject.toml
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Use Ruff for formatting and linting (configured in pyproject.toml)
Type hints required (mypy configuration in pyproject.toml)
ALWAYS place Python imports at the top of the file, not inside functions or methods

Files:

  • holmes/plugins/toolsets/coralogix/toolset_coralogix.py
holmes/plugins/toolsets/**

📄 CodeRabbit inference engine (CLAUDE.md)

Toolsets: organize as holmes/plugins/toolsets/{name}.yaml or {name}/ directories

Files:

  • holmes/plugins/toolsets/coralogix/toolset_coralogix.py
🧠 Learnings (2)
📚 Learning: 2025-12-29T08:35:37.668Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T08:35:37.668Z
Learning: Applies to holmes/plugins/toolsets/** : Toolsets: organize as `holmes/plugins/toolsets/{name}.yaml` or `{name}/` directories

Applied to files:

  • holmes/plugins/toolsets/coralogix/toolset_coralogix.py
📚 Learning: 2025-12-29T08:35:37.668Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T08:35:37.668Z
Learning: Applies to holmes/plugins/toolsets/**/*.yaml : All toolsets MUST return detailed error messages from underlying APIs to enable LLM self-correction, including exact query/command executed, time ranges and parameters used, and full API error response

Applied to files:

  • holmes/plugins/toolsets/coralogix/toolset_coralogix.py
🧬 Code graph analysis (1)
holmes/plugins/toolsets/coralogix/toolset_coralogix.py (2)
holmes/plugins/toolsets/json_filter_mixin.py (2)
  • JsonFilterMixin (60-149)
  • filter_result (120-149)
holmes/core/tools.py (2)
  • Tool (178-370)
  • StructuredToolResult (80-106)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build (3.11)
  • GitHub Check: build (3.12)
  • GitHub Check: build (3.10)
  • GitHub Check: llm_evals
🔇 Additional comments (2)
holmes/plugins/toolsets/coralogix/toolset_coralogix.py (2)

16-16: LGTM: Import statement correct.

The JsonFilterMixin import is properly placed at the top of the file and is used in the class signature.


170-176: LGTM: Result filtering integration correct.

The result handling correctly:

  1. Wraps the data in a StructuredToolResult
  2. Passes it through self.filter_result(wrapped, params) for filtering
  3. Returns the filtered result

The data structure change from a JSON string to a dictionary is appropriate for enabling JSON-based filtering.

Note: This assumes filter parameters are properly exposed via extend_parameters() (see previous comment).


Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Dec 30, 2025 •

Copy link
Copy Markdown
Contributor

✅ Docker image ready for f7a65a2 (built in 54s)

⚠️ Warning: does not support ARM (ARM images are built on release only - not on every PR)

Use this tag to pull the image for testing.

📋 Copy commands

⚠️ Temporary images are deleted after 30 days. Copy to a permanent registry before using them:

gcloud auth configure-docker us-central1-docker.pkg.dev
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:f7a65a2
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:f7a65a2 me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:f7a65a2
docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:f7a65a2

Patch Helm values in one line (choose the chart you use):

HolmesGPT chart:

helm upgrade --install holmesgpt ./helm/holmes \
  --set registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set image=holmes-dev:f7a65a2

Robusta wrapper chart:

helm upgrade --install robusta robusta/robusta \
  --reuse-values \
  --set holmes.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set holmes.image=holmes-dev:f7a65a2

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
docs/data-sources/builtin-toolsets/grafanadashboards.md (1)

61-69: Clear documentation of filtering controls.

The new section effectively explains the three filtering options and their interaction. The note about filters running before depth truncation is particularly helpful.

Optional style refinement

Consider replacing "very big" with a more specific phrase like "large" or "substantial" for a more professional tone:

-Large dashboards can produce very big JSON payloads. To keep tool outputs readable you can:
+Large dashboards can produce substantial JSON payloads. To keep tool outputs readable you can:
holmes/plugins/toolsets/opensearch/opensearch.py (1)

68-71: Pre-existing bug: Variable shadowing causes incorrect client resolution.

The inner comprehension shadows the outer loop variable client, causing the any() to check all clients instead of just the current one. This means the function may return the wrong client when hosts overlap.

This is existing code outside the PR's scope, but consider fixing it:

🔎 Proposed fix
 for client in clients:
-    found = any(host in client.hosts for client in clients)
+    found = host in client.hosts
     if found:
         return client
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7110f2d and b24cdd9.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • docs/data-sources/builtin-toolsets/grafanadashboards.md
  • evals_per_branch.json
  • holmes/plugins/toolsets/grafana/toolset_grafana.py
  • holmes/plugins/toolsets/json_filter_mixin.py
  • holmes/plugins/toolsets/opensearch/opensearch.py
  • pyproject.toml
  • tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/generate_dashboard.py
  • tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/grafana.yaml
  • tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/test_case.yaml
  • tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/toolsets.yaml
  • tests/plugins/toolsets/grafana/test_dashboard_filters.py
🧰 Additional context used
📓 Path-based instructions (6)
tests/llm/**/*.yaml

📄 CodeRabbit inference engine (CLAUDE.md)

tests/llm/**/*.yaml: Use dedicated namespace per test: app-<testid> (e.g., app-177) to prevent conflicts when tests run simultaneously
All pod names must be unique across tests - never reuse pod names between tests
Never use :latest container tags in test infrastructure - use specific versions like grafana/grafana:12.3.1

Files:

  • tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/toolsets.yaml
  • tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/test_case.yaml
  • tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/grafana.yaml
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Use Ruff for formatting and linting (configured in pyproject.toml)
Type hints required (mypy configuration in pyproject.toml)
ALWAYS place Python imports at the top of the file, not inside functions or methods

Files:

  • tests/plugins/toolsets/grafana/test_dashboard_filters.py
  • holmes/plugins/toolsets/json_filter_mixin.py
  • holmes/plugins/toolsets/grafana/toolset_grafana.py
  • tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/generate_dashboard.py
  • holmes/plugins/toolsets/opensearch/opensearch.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Tests: match source structure under tests/

Files:

  • tests/plugins/toolsets/grafana/test_dashboard_filters.py
  • tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/generate_dashboard.py
docs/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

When writing documentation in the docs/ directory, always add a blank line between a header/bold text and a list, otherwise MkDocs won't render the list properly

Files:

  • docs/data-sources/builtin-toolsets/grafanadashboards.md
tests/llm/**/test_case.yaml

📄 CodeRabbit inference engine (CLAUDE.md)

Never use names that hint at the problem or expected behavior in resource naming (e.g., avoid broken-pod, test-project-that-does-not-exist, crashloop-app). Use neutral names that don't give away what the LLM should discover

Files:

  • tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/test_case.yaml
holmes/plugins/toolsets/**

📄 CodeRabbit inference engine (CLAUDE.md)

Toolsets: organize as holmes/plugins/toolsets/{name}.yaml or {name}/ directories

Files:

  • holmes/plugins/toolsets/json_filter_mixin.py
  • holmes/plugins/toolsets/grafana/toolset_grafana.py
  • holmes/plugins/toolsets/opensearch/opensearch.py
🧠 Learnings (3)
📚 Learning: 2025-12-29T08:35:37.668Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T08:35:37.668Z
Learning: Applies to holmes/plugins/toolsets/** : Toolsets: organize as `holmes/plugins/toolsets/{name}.yaml` or `{name}/` directories

Applied to files:

  • tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/toolsets.yaml
  • holmes/plugins/toolsets/opensearch/opensearch.py
📚 Learning: 2025-12-29T08:35:37.668Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T08:35:37.668Z
Learning: Applies to holmes/plugins/toolsets/**/*.yaml : All toolsets MUST return detailed error messages from underlying APIs to enable LLM self-correction, including exact query/command executed, time ranges and parameters used, and full API error response

Applied to files:

  • tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/toolsets.yaml
📚 Learning: 2025-12-29T08:35:37.668Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T08:35:37.668Z
Learning: Applies to tests/llm/**/*.yaml : Never use `:latest` container tags in test infrastructure - use specific versions like `grafana/grafana:12.3.1`

Applied to files:

  • tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/test_case.yaml
  • tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/grafana.yaml
🧬 Code graph analysis (3)
holmes/plugins/toolsets/json_filter_mixin.py (1)
holmes/core/tools.py (3)
  • StructuredToolResult (79-105)
  • StructuredToolResultStatus (52-76)
  • ToolParameter (157-163)
holmes/plugins/toolsets/grafana/toolset_grafana.py (1)
holmes/plugins/toolsets/json_filter_mixin.py (3)
  • JsonFilterMixin (60-122)
  • extend_parameters (82-85)
  • filter_result (109-122)
holmes/plugins/toolsets/opensearch/opensearch.py (3)
holmes/plugins/toolsets/json_filter_mixin.py (3)
  • JsonFilterMixin (60-122)
  • extend_parameters (82-85)
  • filter_result (109-122)
holmes/core/tools.py (4)
  • ToolParameter (157-163)
  • ToolInvokeContext (166-174)
  • StructuredToolResult (79-105)
  • StructuredToolResultStatus (52-76)
holmes/plugins/toolsets/utils.py (1)
  • toolset_name_for_one_liner (232-236)
🪛 Checkov (3.2.334)
tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/grafana.yaml

[medium] 1-68: Containers should not run with allowPrivilegeEscalation

(CKV_K8S_20)


[medium] 1-68: Minimize the admission of root containers

(CKV_K8S_23)

🪛 LanguageTool
docs/data-sources/builtin-toolsets/grafanadashboards.md

[style] ~63-~63: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: ...onse size Large dashboards can produce very big JSON payloads. To keep tool outputs rea...

(EN_WEAK_ADJECTIVE)

🪛 Ruff (0.14.10)
tests/plugins/toolsets/grafana/test_dashboard_filters.py

16-16: Unused lambda argument: endpoint

(ARG005)

holmes/plugins/toolsets/json_filter_mixin.py

42-42: Consider moving this statement to an else block

(TRY300)


43-43: Do not catch blind exception: Exception

(BLE001)


54-54: Consider moving this statement to an else block

(TRY300)


55-55: Do not catch blind exception: Exception

(BLE001)


63-79: Mutable class attributes should be annotated with typing.ClassVar

(RUF012)


92-92: Do not catch blind exception: Exception

(BLE001)

holmes/plugins/toolsets/grafana/toolset_grafana.py

283-283: Unused method argument: context

(ARG002)

holmes/plugins/toolsets/opensearch/opensearch.py

100-100: Unused method argument: context

(ARG002)


166-166: Unused method argument: context

(ARG002)


190-190: Unused method argument: context

(ARG002)

🪛 YAMLlint (1.37.1)
tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/grafana.yaml

[error] 20-20: duplication of key "apiVersion" in mapping

(key-duplicates)


[error] 21-21: duplication of key "kind" in mapping

(key-duplicates)


[error] 22-22: duplication of key "metadata" in mapping

(key-duplicates)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build (3.10)
  • GitHub Check: build (3.12)
  • GitHub Check: build (3.11)
  • GitHub Check: llm_evals
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (24)
evals_per_branch.json (1)

1-5: LGTM!

The eval tracking structure is correct and the path matches the new test fixture directory introduced in this PR.

tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/toolsets.yaml (1)

1-5: LGTM!

The toolset configuration correctly enables Grafana dashboards with the URL matching the port forward configuration in test_case.yaml (local_port: 3030).

tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/grafana.yaml (1)

7-7: Good adherence to test infrastructure guidelines.

The manifest correctly uses:

  • Namespace app-170 matching the test ID pattern
  • Specific image version grafana/grafana:10.4.2 instead of :latest

These practices prevent test conflicts and ensure reproducibility.

Also applies to: 26-26, 39-39, 75-75

tests/plugins/toolsets/grafana/test_dashboard_filters.py (2)

12-23: Helper function provides clean test setup.

The _build_tool helper effectively creates a test instance with a mocked Grafana request. The unused endpoint parameter in the lambda (line 16) is acceptable for test mocks where we only need to return canned data.


25-70: Comprehensive test coverage for filtering behavior.

The test suite effectively validates:

  • Depth truncation mechanics
  • JSONPath and jq filter application
  • Error handling for invalid expressions
  • Correct filter ordering (filters before depth)

This provides strong confidence in the filtering pipeline.

tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/test_case.yaml (3)

7-7: Good adherence to test isolation guidelines.

The test correctly uses namespace app-170 matching the test ID to prevent conflicts when tests run simultaneously, as per coding guidelines.

Also applies to: 16-16


36-60: Robust polling strategy for pod readiness.

The dual polling loops (for pod scheduling and readiness) with proper timeouts, retry delays, and error handling provide reliable setup in CI/CD environments where pod provisioning times vary.


25-25: The generate_dashboard.py file exists in the test fixture directory as expected.

holmes/plugins/toolsets/json_filter_mixin.py (4)

13-34: Clean recursive depth truncation implementation.

The _truncate_to_depth function correctly handles dictionaries, lists, and the boundary case where depth is None or negative. The truncation marker provides clear feedback about what was omitted.


36-58: Robust filter implementations with proper error handling.

Both JSONPath and jq filters:

  • Return single values when there's one match, arrays for multiple matches
  • Provide descriptive error messages on failure
  • Use defensive exception handling appropriate for tool operations

87-108: Correct filter pipeline ordering matches documentation.

The implementation applies filters in the documented order:

  1. Parse JSON if needed
  2. Apply jsonpath if specified
  3. Apply jq if specified
  4. Truncate to max_depth

This aligns with the docs stating "filters run before depth truncation."


109-122: Clean error propagation in filter_result.

The method correctly:

  • Preserves original result metadata (url, invocation, icon_url) when filtering fails
  • Returns ERROR status with descriptive error message
  • Updates data field with filtered result on success
pyproject.toml (1)

58-59: Address critical security vulnerability in jq dependency.

jq 1.8.0 (specified via ^1.8.0) contains CVE-2025-49014, a heap use-after-free vulnerability in the f_strflocaltime function. Upgrade to jq 1.9.1 or later. jsonpath-ng 1.6.1 has no known vulnerabilities.

tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/generate_dashboard.py (3)

4-28: LGTM!

The build_panel function is well-structured with appropriate type hints and produces valid Grafana panel JSON. The grid positioning logic correctly maps panels to a 4-column layout.


31-78: LGTM!

The dashboard generation logic correctly builds a configurable number of panels with a nested row structure for depth filtering tests. The grid positioning and nested panel structure align well with the PR's testing objectives.


81-82: LGTM!

The main block provides a simple CLI interface for generating dashboard JSON, useful for debugging or manual fixture creation.

holmes/plugins/toolsets/opensearch/opensearch.py (4)

83-108: LGTM!

The ListShards class correctly integrates JsonFilterMixin:

  • MRO places JsonFilterMixin first, ensuring its methods are accessible
  • Parameters are extended properly via extend_parameters
  • The shards API now requests JSON format (params={"format": "json"})
  • Result filtering is applied before return

The static analysis hint about unused context is a false positive—the parameter is part of the Tool interface contract.


115-142: LGTM!

The GetClusterSettings class correctly follows the mixin pattern, extending parameters and applying result filtering. The raw response dict is now suitable for JSON filtering operations.


149-174: LGTM!

The GetClusterHealth class follows the established pattern consistently with correct mixin integration and result filtering.


181-197: LGTM!

The ListOpenSearchHosts class correctly uses extend_parameters({}) to include only the filter parameters (max_depth, jsonpath, jq) since no tool-specific parameters are needed. The hosts list is JSON-friendly and suitable for filtering.

holmes/plugins/toolsets/grafana/toolset_grafana.py (4)

21-21: LGTM!

Import of JsonFilterMixin is correctly placed at the top of the file, following the coding guidelines.


241-268: LGTM!

The GetDashboardByUID class correctly integrates JsonFilterMixin:

  • Parameters are properly extended with the filter parameters
  • URL is computed before filtering and then assigned to the filtered result
  • The fallback to result.url preserves the original URL if dashboard_url fails to build

The filtering flow is clean: fetch → filter → set URL → return.


274-294: LGTM with minor observation.

The GetHomeDashboard class correctly integrates filtering. Note that the URL fallback differs from GetDashboardByUID:

  • GetDashboardByUID: falls back to result.url
  • GetHomeDashboard: falls back to None

This is likely intentional since the home dashboard endpoint URL (/api/dashboards/home) isn't meaningful for users to navigate to, whereas the computed dashboard URL is.


128-181: Design observation: SearchDashboards intentionally omits filtering.

The search endpoint returns lightweight dashboard metadata rather than full dashboard JSON, so filtering controls are less critical here. If response sizes become problematic in the future, the mixin can be added following the same pattern.

Comment on lines +63 to +79
filter_parameters: Dict[str, ToolParameter] = {
"max_depth": ToolParameter(
description="Maximum nesting depth to return from the JSON (0 returns only top-level keys). Leave empty for full response.",
type="integer",
required=False,
),
"jsonpath": ToolParameter(
description="Optional jsonpath expression to extract specific parts of the JSON.",
type="string",
required=False,
),
"jq": ToolParameter(
description="Optional jq filter to apply to the JSON.",
type="string",
required=False,
),
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Annotate mutable class attribute with ClassVar.

The filter_parameters dictionary is shared across all instances and should be annotated with typing.ClassVar for proper type checking and to make the class-level scope explicit.

🔎 Proposed fix

Add the import at the top of the file:

-from typing import Any, Dict, Optional, Tuple
+from typing import Any, ClassVar, Dict, Optional, Tuple

Then annotate the class attribute:

 class JsonFilterMixin:
     """Opt-in mixin for tools that return JSON and want filtering controls."""
 
-    filter_parameters: Dict[str, ToolParameter] = {
+    filter_parameters: ClassVar[Dict[str, ToolParameter]] = {
         "max_depth": ToolParameter(
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
filter_parameters: Dict[str, ToolParameter] = {
"max_depth": ToolParameter(
description="Maximum nesting depth to return from the JSON (0 returns only top-level keys). Leave empty for full response.",
type="integer",
required=False,
),
"jsonpath": ToolParameter(
description="Optional jsonpath expression to extract specific parts of the JSON.",
type="string",
required=False,
),
"jq": ToolParameter(
description="Optional jq filter to apply to the JSON.",
type="string",
required=False,
),
}
filter_parameters: ClassVar[Dict[str, ToolParameter]] = {
"max_depth": ToolParameter(
description="Maximum nesting depth to return from the JSON (0 returns only top-level keys). Leave empty for full response.",
type="integer",
required=False,
),
"jsonpath": ToolParameter(
description="Optional jsonpath expression to extract specific parts of the JSON.",
type="string",
required=False,
),
"jq": ToolParameter(
description="Optional jq filter to apply to the JSON.",
type="string",
required=False,
),
}
🧰 Tools
🪛 Ruff (0.14.10)

63-79: Mutable class attributes should be annotated with typing.ClassVar

(RUF012)

🤖 Prompt for AI Agents
In holmes/plugins/toolsets/json_filter_mixin.py around lines 63 to 79, the
class-level dict filter_parameters is a mutable attribute shared across
instances and should be annotated with typing.ClassVar for correct static
typing; add ClassVar to the file imports (from typing import ClassVar) and
change the filter_parameters annotation to use ClassVar[Dict[str,
ToolParameter]] so the attribute is explicitly class-scoped and recognized as
non-instance-mutable by type checkers.

Comment on lines +20 to +27
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
labels:
app: grafana
namespace: app-170
spec:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add YAML document separator between resources.

The second resource (Deployment) starts without a --- separator, causing YAML key duplication errors. Multi-document YAML files require explicit document separators.

🔎 Proposed fix
           path: /var/lib/grafana/dashboards
+---
 apiVersion: apps/v1
 kind: Deployment
 metadata:
🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 20-20: duplication of key "apiVersion" in mapping

(key-duplicates)


[error] 21-21: duplication of key "kind" in mapping

(key-duplicates)


[error] 22-22: duplication of key "metadata" in mapping

(key-duplicates)

🤖 Prompt for AI Agents
In tests/llm/fixtures/test_ask_holmes/170_grafana_dashboard_filters/grafana.yaml
around lines 20 to 27, the second resource (Deployment) begins immediately after
the previous resource without a YAML document separator, causing key duplication
and parsing errors; insert a line with three hyphens (---) immediately before
the Deployment resource to separate documents (ensure there's a single blank
line before/after separator if desired) so each Kubernetes resource is its own
YAML document.

@aantn aantn changed the title Add filtering controls to Grafana dashboard tools and eval coverage Json mixin for tools Dec 30, 2025
Signed-off-by: Codex <codex@openai.com>
@github-actions

github-actions Bot commented Dec 30, 2025 •

Copy link
Copy Markdown
Contributor

✅ Results of HolmesGPT evals

Automatically triggered by commit a8e93ff

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 30.3s 5 13 $0.1620
✅ 101_loki_historical_logs_pod_deleted 35.9s 5 12 $0.1560
✅ 111_pod_names_contain_service 40.5s 7 16 $0.1855
✅ 12_job_crashing 41.1s 7 16 $0.1841
✅ 162_get_runbooks 44.8s 7 14 $0.2029
✅ 176_network_policy_blocking_traffic_no_runbooks 43.4s 7 16 $0.1981
✅ 24_misconfigured_pvc 36.6s 7 15 $0.1705
✅ 43_current_datetime_from_prompt 3.3s 1 — $0.0616
✅ 61_exact_match_counting 10.8s 3 3 $0.0855
Total 31.8s avg 5.4 avg 13.1 avg $1.4062

📖 Legend
Icon Meaning
✅ The test was successful
➖ The test was skipped
⚠️ The test failed but is known to be flaky or known to fail
🚧 The test had a setup failure (not a code regression)
🔧 The test failed due to mock data issues (not a code regression)
🚫 The test was throttled by API rate limits/overload
❌ The test failed and should be fixed before merging the PR
🔄 Re-run evals manually

⚠️ Warning: Manual re-runs have NO default markers and will run ALL LLM tests (~100+), which can take 1+ hours. Use markers: regression or filter: test_name to limit scope.

Option 1: Comment on this PR with /eval:

/eval
markers: regression

Or with more options (one per line):

/eval
model: gpt-4o
markers: regression
filter: 09_crashpod
iterations: 5
Option Description
model Model(s) to test (default: same as automatic runs)
markers Pytest markers (no default - runs all tests!)
filter Pytest -k filter
iterations Number of runs, max 10

Option 2: Trigger via GitHub Actions UI → "Run workflow"

🏷️ Valid markers
  • chain-of-causation
  • compaction
  • context_window
  • coralogix
  • counting
  • database
  • datadog
  • datetime
  • easy
  • embeds
  • grafana-dashboard
  • hard
  • kafka
  • kubernetes
  • leaked-information
  • logs
  • loki
  • medium
  • metrics
  • network
  • newrelic
  • no-cicd
  • numerical
  • one-test
  • port-forward
  • prometheus
  • question-answer
  • regression
  • runbooks
  • slackbot
  • storage
  • toolset-limitation
  • traces
  • transparency
📋 Valid eval names (use with filter)

test_ask_holmes:

  • 01_how_many_pods
  • 02_what_is_wrong_with_pod
  • 03_what_is_the_command_to_port_forward
  • 04_related_k8s_events
  • 05_image_version
  • 06_explain_issue
  • 07_high_latency
  • 08_sock_shop_frontend
  • 09_crashpod
  • 100a_loki_historical_logs
  • 100b_loki_historical_logs_nonstandard_label
  • 101_loki_historical_logs_pod_deleted
  • 102_loki_label_discovery
  • 102a_loki_logs_transparency
  • 102b_loki_multiple_pods
  • 103_logs_transparency_default_limit
  • 104a_postgres_root_issue
  • 104b_postgres_missing_index_pgstat
  • 104c_postgres_minimal_missing_index
  • 105_redis_wrong_data_structure
  • 107_log_filter_http_status_code
  • 108_logs_nearby_lines
  • 109_logs_transparency_not_found
  • 10_image_pull_backoff
  • 110_cpu_graph_robusta_runner
  • 110_k8s_events_image_pull
  • 111_disabled_datadog_traces
  • 111_pod_names_contain_service
  • 111_tool_hallucination
  • 112_find_pvcs_by_uuid
  • 114_checkout_latency_tracing_rebuild
  • 115_checkout_errors_tracing
  • 117_new_relic_tracing
  • 117b_new_relic_block_embed
  • 118_new_relic_logs
  • 119_new_relic_metrics
  • 11_init_containers
  • 120_new_relic_traces2
  • 121_new_relic_checkout_errors_tracing
  • 122_new_relic_checkout_latency_tracing_rebuild
  • 123_new_relic_checkout_errors_tracing
  • 124_checkout_latency_prometheus
  • 12_job_crashing
  • 13a_pending_node_selector_basic
  • 13b_pending_node_selector_detailed
  • 14_pending_resources
  • 151_disabled_toolsets_fallback_only
  • 156_kafka_opensearch_latency
  • 157_disk_full_statefulset
  • 158_slack_chat_correct_date
  • 159_prometheus_high_cardinality_cpu
  • 15_failed_readiness_probe
  • 160_electricity_market_bidding_bug
  • 160a_cpu_per_namespace_graph
  • 160b_cpu_per_namespace_graph_with_prom_truncation
  • 160c_cpu_per_namespace_graph_with_global_truncation
  • 161_bidding_version_performance
  • 161_conversation_compaction
  • 162_get_runbooks
  • 163_compaction_follow_up
  • 164_datadog_traces_coupon_code
  • 165_alert_with_multiple_runbooks
  • 16_failed_no_toolset_found
  • 170_grafana_dashboard_filters
  • 173_coralogix_logs
  • 174_coralogix_traces_ad
  • 175_coralogix_metrics_frontend
  • 176_network_policy_blocking_traffic_no_runbooks
  • 177_grafana_home_dashboard
  • 178_grafana_search_dashboard_query
  • 179_grafana_big_dashboard_query
  • 17_oom_kill
  • 18_oom_kill_from_issues_history
  • 19_detect_missing_app_details
  • 20_long_log_file_search
  • 21_job_fail_curl_no_svc_account
  • 22_high_latency_dbi_down
  • 23_app_error_in_current_logs
  • 24_misconfigured_pvc
  • 25_misconfigured_ingress_class
  • 26_page_render_times
  • 27a_multi_container_logs
  • 27b_multi_container_logs
  • 28_permissions_error
  • 30_basic_promql_graph_cluster_memory
  • 32_basic_promql_graph_pod_cpu
  • 33_cpu_metrics_discovery
  • 34_memory_graph
  • 35_tempo
  • 36_argocd_find_resource
  • 37_argocd_wrong_namespace
  • 38_rabbitmq_split_head
  • 39_failed_toolset
  • 41_setup_argo
  • 42_dns_issues_result_all_tools
  • 42_dns_issues_result_new_tools
  • 42_dns_issues_result_new_tools_no_runbook
  • 42_dns_issues_result_old_tools
  • 42_dns_issues_steps_new_all_tools
  • 42_dns_issues_steps_new_tools
  • 42_dns_issues_steps_old_tools
  • 43_current_datetime_from_prompt
  • 43_slack_deployment_logs
  • 44_slack_statefulset_logs
  • 45_fetch_deployment_logs_simple
  • 46_job_crashing_no_longer_exists
  • 47_truncated_logs_context_window
  • 48_logs_since_thursday
  • 49_logs_since_last_week
  • 50_logs_since_specific_date
  • 50a_logs_since_last_specific_month
  • 51_logs_summarize_errors
  • 52_logs_login_issues
  • 53_logs_find_term
  • 54_azure_sql
  • 54_not_truncated_when_getting_pods
  • 55_kafka_runbook
  • 57_cluster_name_confusion
  • 57_wrong_namespace
  • 58_counting_pods_by_status
  • 59_label_based_counting
  • 60_count_less_than
  • 61_exact_match_counting
  • 62_fetch_error_logs_with_errors
  • 63_fetch_error_logs_no_errors
  • 64_keda_vs_hpa_confusion
  • 65_health_check_followup
  • 66_http_error_needle
  • 67_performance_degradation
  • 68_cascading_failures
  • 69_rate_limit_exhaustion
  • 70_memory_leak_detection
  • 71_connection_pool_starvation
  • 73a_time_window_anomaly
  • 73b_time_window_anomaly
  • 74_config_change_impact
  • 75_network_flapping
  • 76_service_discovery_issue
  • 77_liveness_probe_misconfiguration
  • 78a_missing_cpu_limits
  • 78b_cpu_quota_exceeded
  • 79_configmap_mount_issue
  • 80_pvc_storage_class_mismatch
  • 81_service_account_permission_denied
  • 82_pod_anti_affinity_conflict
  • 83_secret_not_found
  • 84_network_policy_blocking_traffic
  • 85_hpa_not_scaling
  • 86_configmap_like_but_secret
  • 89_runbook_missing_cloudwatch
  • 90_runbook_basic_selection
  • 91a_datadog_metrics_missing_namespace
  • 91b_datadog_metrics_pod_exists
  • 91c_datadog_metrics_deployment
  • 91d_datadog_metrics_historical_pod
  • 91e_datadog_custom_metrics
  • 91f_datadog_logs_historical_pod
  • 91g_datadog_metrics_mismatched_pod
  • 91h_datadog_logs_empty_query_with_url
  • 91i_datadog_metrics_empty_query_with_url
  • 92_cpu_graph_conversation
  • 93_calling_datadog
  • 93_events_since_specific_date
  • 94_runbook_transparency
  • 95_runbook_memory_leak_detection
  • 96_no_matching_runbook
  • 97_logs_clarification_needed
  • 99_logs_transparency_custom_time

test_investigate:

  • 01_oom_kill
  • 02_crashloop_backoff
  • 03_cpu_throttling
  • 04_image_pull_backoff
  • 05_crashpod
  • 06_job_failure
  • 07_job_syntax_error
  • 08_memory_pressure
  • 09_high_latency
  • 10_KubeDeploymentReplicasMismatch
  • 11_KubePodCrashLooping
  • 12_KubePodNotReady
  • 13_Watchdog
  • 14_tempo
  • 15_dns_resolution
  • 16_dns_resolution_no_tool
  • 17_investigate_correct_date

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
holmes/plugins/toolsets/json_filter_mixin.py (1)

63-79: Annotate mutable class attribute with ClassVar.

The filter_parameters dictionary is a class-level attribute shared across all instances and should be annotated with typing.ClassVar for proper type checking.

🔎 Proposed fix

Add ClassVar to the import statement:

-from typing import Any, Dict, Optional, Tuple
+from typing import Any, ClassVar, Dict, Optional, Tuple

Then annotate the class attribute:

-    filter_parameters: Dict[str, ToolParameter] = {
+    filter_parameters: ClassVar[Dict[str, ToolParameter]] = {
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b24cdd9 and a8e93ff.

📒 Files selected for processing (1)
  • holmes/plugins/toolsets/json_filter_mixin.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Use Ruff for formatting and linting (configured in pyproject.toml)
Type hints required (mypy configuration in pyproject.toml)
ALWAYS place Python imports at the top of the file, not inside functions or methods

Files:

  • holmes/plugins/toolsets/json_filter_mixin.py
holmes/plugins/toolsets/**

📄 CodeRabbit inference engine (CLAUDE.md)

Toolsets: organize as holmes/plugins/toolsets/{name}.yaml or {name}/ directories

Files:

  • holmes/plugins/toolsets/json_filter_mixin.py
🧬 Code graph analysis (1)
holmes/plugins/toolsets/json_filter_mixin.py (1)
holmes/core/tools.py (3)
  • StructuredToolResult (79-105)
  • StructuredToolResultStatus (52-76)
  • ToolParameter (157-163)
🪛 Ruff (0.14.10)
holmes/plugins/toolsets/json_filter_mixin.py

42-42: Consider moving this statement to an else block

(TRY300)


43-43: Do not catch blind exception: Exception

(BLE001)


54-54: Consider moving this statement to an else block

(TRY300)


55-55: Do not catch blind exception: Exception

(BLE001)


63-79: Mutable class attributes should be annotated with typing.ClassVar

(RUF012)


92-92: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build (3.10)
  • GitHub Check: build (3.12)
  • GitHub Check: build (3.11)
  • GitHub Check: llm_evals
  • GitHub Check: build
🔇 Additional comments (4)
holmes/plugins/toolsets/json_filter_mixin.py (4)

1-10: LGTM!

The imports are correctly organized and placed at the top of the file as required by the coding guidelines.


13-57: LGTM!

The helper functions implement robust filtering with appropriate error handling. The broad exception catching is justified here since these functions process user-provided filter expressions against external libraries (jq, jsonpath-ng).


81-85: LGTM!

The extend_parameters method correctly merges filter parameters with existing tool parameters, allowing existing parameters to take precedence.


87-107: LGTM!

The filtering pipeline correctly applies jsonpath, jq, and depth truncation in sequence, with appropriate error propagation.

Comment on lines +109 to +135
def filter_result(self, result: StructuredToolResult, params: Dict) -> StructuredToolResult:
base_result = (
result
if isinstance(result, StructuredToolResult)
else StructuredToolResult(
status=getattr(result, "status", StructuredToolResultStatus.SUCCESS),
data=getattr(result, "data", None),
params=getattr(result, "params", params),
url=getattr(result, "url", None),
invocation=getattr(result, "invocation", None),
icon_url=getattr(result, "icon_url", None),
)
)

filtered_data, error = self._filter_result_data(base_result.data, params)
if error:
return StructuredToolResult(
status=StructuredToolResultStatus.ERROR,
error=error,
params=params,
url=base_result.url,
invocation=base_result.invocation,
icon_url=base_result.icon_url,
)

base_result.data = filtered_data
return base_result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid mutating the input result object.

Line 134 mutates base_result.data directly. When the input result is already a StructuredToolResult (line 111), base_result is a reference to the same object, causing unexpected side effects for callers who may reuse the result object.

🔎 Proposed fix to return a new instance instead of mutating
-        base_result.data = filtered_data
-        return base_result
+        return StructuredToolResult(
+            status=base_result.status,
+            data=filtered_data,
+            params=base_result.params,
+            url=base_result.url,
+            invocation=base_result.invocation,
+            icon_url=base_result.icon_url,
+            error=base_result.error,
+            return_code=base_result.return_code,
+        )

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
holmes/plugins/toolsets/json_filter_mixin.py around lines 109 to 135: the method
currently mutates base_result.data which, when the incoming result is already a
StructuredToolResult, alters the caller's object; instead of assigning
filtered_data into base_result, construct and return a new StructuredToolResult
instance copying all fields from base_result (status, params, url, invocation,
icon_url, error if any) but with data set to filtered_data so the original
result is not mutated.

Signed-off-by: Codex <codex@openai.com>
@github-actions

github-actions Bot commented Dec 30, 2025 •

Copy link
Copy Markdown
Contributor

✅ Results of HolmesGPT evals

Automatically triggered by commit bd8a435

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 30.0s 5 13 $0.1539
✅ 101_loki_historical_logs_pod_deleted 45.4s 6 14 $0.1936
✅ 111_pod_names_contain_service 41.6s 8 18 $0.1884
✅ 12_job_crashing 49.5s 9 18 $0.2166
✅ 162_get_runbooks 46.3s 7 16 $0.2122
✅ 176_network_policy_blocking_traffic_no_runbooks 40.6s 7 15 $0.1861
✅ 24_misconfigured_pvc 39.2s 8 18 $0.1888
✅ 43_current_datetime_from_prompt 3.3s 1 — $0.0616
✅ 61_exact_match_counting 10.3s 3 3 $0.0854
Total 34.0s avg 6.0 avg 14.4 avg $1.4866

📖 Legend
Icon Meaning
✅ The test was successful
➖ The test was skipped
⚠️ The test failed but is known to be flaky or known to fail
🚧 The test had a setup failure (not a code regression)
🔧 The test failed due to mock data issues (not a code regression)
🚫 The test was throttled by API rate limits/overload
❌ The test failed and should be fixed before merging the PR
🔄 Re-run evals manually

⚠️ Warning: Manual re-runs have NO default markers and will run ALL LLM tests (~100+), which can take 1+ hours. Use markers: regression or filter: test_name to limit scope.

Option 1: Comment on this PR with /eval:

/eval
markers: regression

Or with more options (one per line):

/eval
model: gpt-4o
markers: regression
filter: 09_crashpod
iterations: 5
Option Description
model Model(s) to test (default: same as automatic runs)
markers Pytest markers (no default - runs all tests!)
filter Pytest -k filter
iterations Number of runs, max 10

Option 2: Trigger via GitHub Actions UI → "Run workflow"

🏷️ Valid markers
  • chain-of-causation
  • compaction
  • context_window
  • coralogix
  • counting
  • database
  • datadog
  • datetime
  • easy
  • embeds
  • grafana-dashboard
  • hard
  • kafka
  • kubernetes
  • leaked-information
  • logs
  • loki
  • medium
  • metrics
  • network
  • newrelic
  • no-cicd
  • numerical
  • one-test
  • port-forward
  • prometheus
  • question-answer
  • regression
  • runbooks
  • slackbot
  • storage
  • toolset-limitation
  • traces
  • transparency
📋 Valid eval names (use with filter)

test_ask_holmes:

  • 01_how_many_pods
  • 02_what_is_wrong_with_pod
  • 03_what_is_the_command_to_port_forward
  • 04_related_k8s_events
  • 05_image_version
  • 06_explain_issue
  • 07_high_latency
  • 08_sock_shop_frontend
  • 09_crashpod
  • 100a_loki_historical_logs
  • 100b_loki_historical_logs_nonstandard_label
  • 101_loki_historical_logs_pod_deleted
  • 102_loki_label_discovery
  • 102a_loki_logs_transparency
  • 102b_loki_multiple_pods
  • 103_logs_transparency_default_limit
  • 104a_postgres_root_issue
  • 104b_postgres_missing_index_pgstat
  • 104c_postgres_minimal_missing_index
  • 105_redis_wrong_data_structure
  • 107_log_filter_http_status_code
  • 108_logs_nearby_lines
  • 109_logs_transparency_not_found
  • 10_image_pull_backoff
  • 110_cpu_graph_robusta_runner
  • 110_k8s_events_image_pull
  • 111_disabled_datadog_traces
  • 111_pod_names_contain_service
  • 111_tool_hallucination
  • 112_find_pvcs_by_uuid
  • 114_checkout_latency_tracing_rebuild
  • 115_checkout_errors_tracing
  • 117_new_relic_tracing
  • 117b_new_relic_block_embed
  • 118_new_relic_logs
  • 119_new_relic_metrics
  • 11_init_containers
  • 120_new_relic_traces2
  • 121_new_relic_checkout_errors_tracing
  • 122_new_relic_checkout_latency_tracing_rebuild
  • 123_new_relic_checkout_errors_tracing
  • 124_checkout_latency_prometheus
  • 12_job_crashing
  • 13a_pending_node_selector_basic
  • 13b_pending_node_selector_detailed
  • 14_pending_resources
  • 151_disabled_toolsets_fallback_only
  • 156_kafka_opensearch_latency
  • 157_disk_full_statefulset
  • 158_slack_chat_correct_date
  • 159_prometheus_high_cardinality_cpu
  • 15_failed_readiness_probe
  • 160_electricity_market_bidding_bug
  • 160a_cpu_per_namespace_graph
  • 160b_cpu_per_namespace_graph_with_prom_truncation
  • 160c_cpu_per_namespace_graph_with_global_truncation
  • 161_bidding_version_performance
  • 161_conversation_compaction
  • 162_get_runbooks
  • 163_compaction_follow_up
  • 164_datadog_traces_coupon_code
  • 165_alert_with_multiple_runbooks
  • 16_failed_no_toolset_found
  • 170_grafana_dashboard_filters
  • 173_coralogix_logs
  • 174_coralogix_traces_ad
  • 175_coralogix_metrics_frontend
  • 176_network_policy_blocking_traffic_no_runbooks
  • 177_grafana_home_dashboard
  • 178_grafana_search_dashboard_query
  • 179_grafana_big_dashboard_query
  • 17_oom_kill
  • 18_oom_kill_from_issues_history
  • 19_detect_missing_app_details
  • 20_long_log_file_search
  • 21_job_fail_curl_no_svc_account
  • 22_high_latency_dbi_down
  • 23_app_error_in_current_logs
  • 24_misconfigured_pvc
  • 25_misconfigured_ingress_class
  • 26_page_render_times
  • 27a_multi_container_logs
  • 27b_multi_container_logs
  • 28_permissions_error
  • 30_basic_promql_graph_cluster_memory
  • 32_basic_promql_graph_pod_cpu
  • 33_cpu_metrics_discovery
  • 34_memory_graph
  • 35_tempo
  • 36_argocd_find_resource
  • 37_argocd_wrong_namespace
  • 38_rabbitmq_split_head
  • 39_failed_toolset
  • 41_setup_argo
  • 42_dns_issues_result_all_tools
  • 42_dns_issues_result_new_tools
  • 42_dns_issues_result_new_tools_no_runbook
  • 42_dns_issues_result_old_tools
  • 42_dns_issues_steps_new_all_tools
  • 42_dns_issues_steps_new_tools
  • 42_dns_issues_steps_old_tools
  • 43_current_datetime_from_prompt
  • 43_slack_deployment_logs
  • 44_slack_statefulset_logs
  • 45_fetch_deployment_logs_simple
  • 46_job_crashing_no_longer_exists
  • 47_truncated_logs_context_window
  • 48_logs_since_thursday
  • 49_logs_since_last_week
  • 50_logs_since_specific_date
  • 50a_logs_since_last_specific_month
  • 51_logs_summarize_errors
  • 52_logs_login_issues
  • 53_logs_find_term
  • 54_azure_sql
  • 54_not_truncated_when_getting_pods
  • 55_kafka_runbook
  • 57_cluster_name_confusion
  • 57_wrong_namespace
  • 58_counting_pods_by_status
  • 59_label_based_counting
  • 60_count_less_than
  • 61_exact_match_counting
  • 62_fetch_error_logs_with_errors
  • 63_fetch_error_logs_no_errors
  • 64_keda_vs_hpa_confusion
  • 65_health_check_followup
  • 66_http_error_needle
  • 67_performance_degradation
  • 68_cascading_failures
  • 69_rate_limit_exhaustion
  • 70_memory_leak_detection
  • 71_connection_pool_starvation
  • 73a_time_window_anomaly
  • 73b_time_window_anomaly
  • 74_config_change_impact
  • 75_network_flapping
  • 76_service_discovery_issue
  • 77_liveness_probe_misconfiguration
  • 78a_missing_cpu_limits
  • 78b_cpu_quota_exceeded
  • 79_configmap_mount_issue
  • 80_pvc_storage_class_mismatch
  • 81_service_account_permission_denied
  • 82_pod_anti_affinity_conflict
  • 83_secret_not_found
  • 84_network_policy_blocking_traffic
  • 85_hpa_not_scaling
  • 86_configmap_like_but_secret
  • 89_runbook_missing_cloudwatch
  • 90_runbook_basic_selection
  • 91a_datadog_metrics_missing_namespace
  • 91b_datadog_metrics_pod_exists
  • 91c_datadog_metrics_deployment
  • 91d_datadog_metrics_historical_pod
  • 91e_datadog_custom_metrics
  • 91f_datadog_logs_historical_pod
  • 91g_datadog_metrics_mismatched_pod
  • 91h_datadog_logs_empty_query_with_url
  • 91i_datadog_metrics_empty_query_with_url
  • 92_cpu_graph_conversation
  • 93_calling_datadog
  • 93_events_since_specific_date
  • 94_runbook_transparency
  • 95_runbook_memory_leak_detection
  • 96_no_matching_runbook
  • 97_logs_clarification_needed
  • 99_logs_transparency_custom_time

test_investigate:

  • 01_oom_kill
  • 02_crashloop_backoff
  • 03_cpu_throttling
  • 04_image_pull_backoff
  • 05_crashpod
  • 06_job_failure
  • 07_job_syntax_error
  • 08_memory_pressure
  • 09_high_latency
  • 10_KubeDeploymentReplicasMismatch
  • 11_KubePodCrashLooping
  • 12_KubePodNotReady
  • 13_Watchdog
  • 14_tempo
  • 15_dns_resolution
  • 16_dns_resolution_no_tool
  • 17_investigate_correct_date

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
holmes/plugins/toolsets/json_filter_mixin.py (2)

63-79: Annotate mutable class attribute with ClassVar.

This issue has already been identified in a previous review. The filter_parameters dictionary should be annotated with typing.ClassVar for proper type checking.


120-149: Avoid mutating the input result object.

This issue has already been identified in a previous review. Line 148 mutates base_result.data directly, which can cause unexpected side effects when the input result is already a StructuredToolResult. The previous review recommends returning a new StructuredToolResult instance instead of mutating the existing one.

🧹 Nitpick comments (2)
holmes/plugins/toolsets/json_filter_mixin.py (2)

36-45: Consider clarifying empty match behavior.

When the jsonpath expression matches no elements, the function returns an empty list []. This could be ambiguous—did the filter match nothing, or did it match an empty array? Consider either:

  1. Documenting this behavior explicitly, or
  2. Returning a more explicit indicator (e.g., None with a descriptive message) when no matches are found.

48-57: Consider clarifying empty match behavior.

Similar to the jsonpath filter, when the jq expression produces no results, an empty list [] is returned. The same ambiguity applies here. Consider documenting this behavior or returning a more explicit indicator when no results are produced.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a8e93ff and bd8a435.

📒 Files selected for processing (1)
  • holmes/plugins/toolsets/json_filter_mixin.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Use Ruff for formatting and linting (configured in pyproject.toml)
Type hints required (mypy configuration in pyproject.toml)
ALWAYS place Python imports at the top of the file, not inside functions or methods

Files:

  • holmes/plugins/toolsets/json_filter_mixin.py
holmes/plugins/toolsets/**

📄 CodeRabbit inference engine (CLAUDE.md)

Toolsets: organize as holmes/plugins/toolsets/{name}.yaml or {name}/ directories

Files:

  • holmes/plugins/toolsets/json_filter_mixin.py
🧬 Code graph analysis (1)
holmes/plugins/toolsets/json_filter_mixin.py (1)
holmes/core/tools.py (3)
  • StructuredToolResult (79-105)
  • StructuredToolResultStatus (52-76)
  • ToolParameter (157-163)
🪛 Ruff (0.14.10)
holmes/plugins/toolsets/json_filter_mixin.py

42-42: Consider moving this statement to an else block

(TRY300)


43-43: Do not catch blind exception: Exception

(BLE001)


54-54: Consider moving this statement to an else block

(TRY300)


55-55: Do not catch blind exception: Exception

(BLE001)


63-79: Mutable class attributes should be annotated with typing.ClassVar

(RUF012)


92-92: Do not catch blind exception: Exception

(BLE001)


117-117: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build (3.12)
  • GitHub Check: build (3.10)
  • GitHub Check: build (3.11)
  • GitHub Check: llm_evals
  • GitHub Check: build
🔇 Additional comments (5)
holmes/plugins/toolsets/json_filter_mixin.py (5)

1-10: LGTM! Imports are properly organized.

The imports follow the coding guidelines with all imports at the top of the file, and appropriate type: ignore comments for untyped external libraries.


13-33: LGTM! Depth truncation logic is correct.

The recursive truncation correctly handles dictionaries, lists, and primitive values while respecting the maximum depth constraint.


81-85: LGTM! Parameter merging is clean and non-mutating.

The method correctly creates a new dictionary and merges parameters without side effects.


87-107: LGTM! Filter pipeline is well-structured.

The sequential application of jsonpath, jq, and depth truncation with proper error handling is clear and correct. The graceful handling of non-JSON strings (lines 92-94) is appropriate.


109-118: LGTM! Defensive string normalization for test compatibility.

The method safely handles conversion to strings with appropriate fallbacks. Based on the usage in filter_result, this appears primarily designed to handle MagicMock objects in tests, which is a reasonable defensive pattern.

@aantn

aantn commented Dec 30, 2025

Copy link
Copy Markdown
Collaborator Author

/eval
filter: grafana
iterations: 5

@github-actions

Copy link
Copy Markdown
Contributor

@aantn Your eval run has finished. ✅ Completed successfully

👆 See updated results above.

@aantn

aantn commented Dec 30, 2025

Copy link
Copy Markdown
Collaborator Author

/eval
filter: grafana
iterations: 5

@github-actions

Copy link
Copy Markdown
Contributor

@aantn Your eval run has finished. ✅ Completed successfully

👆 See updated results above.

Signed-off-by: Codex <codex@openai.com>
@github-actions

github-actions Bot commented Dec 30, 2025 •

Copy link
Copy Markdown
Contributor

✅ Results of HolmesGPT evals

Automatically triggered by commit e2ce0c6

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 31.0s 5 13 $0.1536
✅ 101_loki_historical_logs_pod_deleted 40.1s 6 11 $0.1668
✅ 111_pod_names_contain_service 35.7s 6 14 $0.1589
✅ 12_job_crashing 42.2s 7 16 $0.1853
✅ 162_get_runbooks 52.6s 8 16 $0.2334
✅ 176_network_policy_blocking_traffic_no_runbooks 39.8s 7 15 $0.1887
✅ 24_misconfigured_pvc 37.8s 6 17 $0.1715
✅ 43_current_datetime_from_prompt 3.2s 1 — $0.0616
✅ 61_exact_match_counting 10.7s 3 3 $0.0854
Total 32.6s avg 5.4 avg 13.1 avg $1.4052

📖 Legend
Icon Meaning
✅ The test was successful
➖ The test was skipped
⚠️ The test failed but is known to be flaky or known to fail
🚧 The test had a setup failure (not a code regression)
🔧 The test failed due to mock data issues (not a code regression)
🚫 The test was throttled by API rate limits/overload
❌ The test failed and should be fixed before merging the PR
🔄 Re-run evals manually

⚠️ Warning: Manual re-runs have NO default markers and will run ALL LLM tests (~100+), which can take 1+ hours. Use markers: regression or filter: test_name to limit scope.

Option 1: Comment on this PR with /eval:

/eval
markers: regression

Or with more options (one per line):

/eval
model: gpt-4o
markers: regression
filter: 09_crashpod
iterations: 5
Option Description
model Model(s) to test (default: same as automatic runs)
markers Pytest markers (no default - runs all tests!)
filter Pytest -k filter
iterations Number of runs, max 10

Option 2: Trigger via GitHub Actions UI → "Run workflow"

🏷️ Valid markers
  • chain-of-causation
  • compaction
  • context_window
  • coralogix
  • counting
  • database
  • datadog
  • datetime
  • easy
  • embeds
  • grafana-dashboard
  • hard
  • kafka
  • kubernetes
  • leaked-information
  • logs
  • loki
  • medium
  • metrics
  • network
  • newrelic
  • no-cicd
  • numerical
  • one-test
  • port-forward
  • prometheus
  • question-answer
  • regression
  • runbooks
  • slackbot
  • storage
  • toolset-limitation
  • traces
  • transparency
📋 Valid eval names (use with filter)

test_ask_holmes:

  • 01_how_many_pods
  • 02_what_is_wrong_with_pod
  • 03_what_is_the_command_to_port_forward
  • 04_related_k8s_events
  • 05_image_version
  • 06_explain_issue
  • 07_high_latency
  • 08_sock_shop_frontend
  • 09_crashpod
  • 100a_loki_historical_logs
  • 100b_loki_historical_logs_nonstandard_label
  • 101_loki_historical_logs_pod_deleted
  • 102_loki_label_discovery
  • 102a_loki_logs_transparency
  • 102b_loki_multiple_pods
  • 103_logs_transparency_default_limit
  • 104a_postgres_root_issue
  • 104b_postgres_missing_index_pgstat
  • 104c_postgres_minimal_missing_index
  • 105_redis_wrong_data_structure
  • 107_log_filter_http_status_code
  • 108_logs_nearby_lines
  • 109_logs_transparency_not_found
  • 10_image_pull_backoff
  • 110_cpu_graph_robusta_runner
  • 110_k8s_events_image_pull
  • 111_disabled_datadog_traces
  • 111_pod_names_contain_service
  • 111_tool_hallucination
  • 112_find_pvcs_by_uuid
  • 114_checkout_latency_tracing_rebuild
  • 115_checkout_errors_tracing
  • 117_new_relic_tracing
  • 117b_new_relic_block_embed
  • 118_new_relic_logs
  • 119_new_relic_metrics
  • 11_init_containers
  • 120_new_relic_traces2
  • 121_new_relic_checkout_errors_tracing
  • 122_new_relic_checkout_latency_tracing_rebuild
  • 123_new_relic_checkout_errors_tracing
  • 124_checkout_latency_prometheus
  • 12_job_crashing
  • 13a_pending_node_selector_basic
  • 13b_pending_node_selector_detailed
  • 14_pending_resources
  • 151_disabled_toolsets_fallback_only
  • 156_kafka_opensearch_latency
  • 157_disk_full_statefulset
  • 158_slack_chat_correct_date
  • 159_prometheus_high_cardinality_cpu
  • 15_failed_readiness_probe
  • 160_electricity_market_bidding_bug
  • 160a_cpu_per_namespace_graph
  • 160b_cpu_per_namespace_graph_with_prom_truncation
  • 160c_cpu_per_namespace_graph_with_global_truncation
  • 161_bidding_version_performance
  • 161_conversation_compaction
  • 162_get_runbooks
  • 163_compaction_follow_up
  • 164_datadog_traces_coupon_code
  • 165_alert_with_multiple_runbooks
  • 16_failed_no_toolset_found
  • 170_grafana_dashboard_filters
  • 173_coralogix_logs
  • 174_coralogix_traces_ad
  • 175_coralogix_metrics_frontend
  • 176_network_policy_blocking_traffic_no_runbooks
  • 177_grafana_home_dashboard
  • 178_grafana_search_dashboard_query
  • 179_grafana_big_dashboard_query
  • 17_oom_kill
  • 18_oom_kill_from_issues_history
  • 19_detect_missing_app_details
  • 20_long_log_file_search
  • 21_job_fail_curl_no_svc_account
  • 22_high_latency_dbi_down
  • 23_app_error_in_current_logs
  • 24_misconfigured_pvc
  • 25_misconfigured_ingress_class
  • 26_page_render_times
  • 27a_multi_container_logs
  • 27b_multi_container_logs
  • 28_permissions_error
  • 30_basic_promql_graph_cluster_memory
  • 32_basic_promql_graph_pod_cpu
  • 33_cpu_metrics_discovery
  • 34_memory_graph
  • 35_tempo
  • 36_argocd_find_resource
  • 37_argocd_wrong_namespace
  • 38_rabbitmq_split_head
  • 39_failed_toolset
  • 41_setup_argo
  • 42_dns_issues_result_all_tools
  • 42_dns_issues_result_new_tools
  • 42_dns_issues_result_new_tools_no_runbook
  • 42_dns_issues_result_old_tools
  • 42_dns_issues_steps_new_all_tools
  • 42_dns_issues_steps_new_tools
  • 42_dns_issues_steps_old_tools
  • 43_current_datetime_from_prompt
  • 43_slack_deployment_logs
  • 44_slack_statefulset_logs
  • 45_fetch_deployment_logs_simple
  • 46_job_crashing_no_longer_exists
  • 47_truncated_logs_context_window
  • 48_logs_since_thursday
  • 49_logs_since_last_week
  • 50_logs_since_specific_date
  • 50a_logs_since_last_specific_month
  • 51_logs_summarize_errors
  • 52_logs_login_issues
  • 53_logs_find_term
  • 54_azure_sql
  • 54_not_truncated_when_getting_pods
  • 55_kafka_runbook
  • 57_cluster_name_confusion
  • 57_wrong_namespace
  • 58_counting_pods_by_status
  • 59_label_based_counting
  • 60_count_less_than
  • 61_exact_match_counting
  • 62_fetch_error_logs_with_errors
  • 63_fetch_error_logs_no_errors
  • 64_keda_vs_hpa_confusion
  • 65_health_check_followup
  • 66_http_error_needle
  • 67_performance_degradation
  • 68_cascading_failures
  • 69_rate_limit_exhaustion
  • 70_memory_leak_detection
  • 71_connection_pool_starvation
  • 73a_time_window_anomaly
  • 73b_time_window_anomaly
  • 74_config_change_impact
  • 75_network_flapping
  • 76_service_discovery_issue
  • 77_liveness_probe_misconfiguration
  • 78a_missing_cpu_limits
  • 78b_cpu_quota_exceeded
  • 79_configmap_mount_issue
  • 80_pvc_storage_class_mismatch
  • 81_service_account_permission_denied
  • 82_pod_anti_affinity_conflict
  • 83_secret_not_found
  • 84_network_policy_blocking_traffic
  • 85_hpa_not_scaling
  • 86_configmap_like_but_secret
  • 89_runbook_missing_cloudwatch
  • 90_runbook_basic_selection
  • 91a_datadog_metrics_missing_namespace
  • 91b_datadog_metrics_pod_exists
  • 91c_datadog_metrics_deployment
  • 91d_datadog_metrics_historical_pod
  • 91e_datadog_custom_metrics
  • 91f_datadog_logs_historical_pod
  • 91g_datadog_metrics_mismatched_pod
  • 91h_datadog_logs_empty_query_with_url
  • 91i_datadog_metrics_empty_query_with_url
  • 92_cpu_graph_conversation
  • 93_calling_datadog
  • 93_events_since_specific_date
  • 94_runbook_transparency
  • 95_runbook_memory_leak_detection
  • 96_no_matching_runbook
  • 97_logs_clarification_needed
  • 99_logs_transparency_custom_time

test_investigate:

  • 01_oom_kill
  • 02_crashloop_backoff
  • 03_cpu_throttling
  • 04_image_pull_backoff
  • 05_crashpod
  • 06_job_failure
  • 07_job_syntax_error
  • 08_memory_pressure
  • 09_high_latency
  • 10_KubeDeploymentReplicasMismatch
  • 11_KubePodCrashLooping
  • 12_KubePodNotReady
  • 13_Watchdog
  • 14_tempo
  • 15_dns_resolution
  • 16_dns_resolution_no_tool
  • 17_investigate_correct_date

@github-actions

github-actions Bot commented Dec 30, 2025 •

Copy link
Copy Markdown
Contributor

✅ Results of HolmesGPT evals

Automatically triggered by commit 8ca3b82

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 33.0s 5 13 $0.1051
✅ 101_loki_historical_logs_pod_deleted 36.9s 5 11 $0.1081
✅ 111_pod_names_contain_service 40.9s 7 17 $0.1222
✅ 12_job_crashing 48.8s 8 18 $0.1557
✅ 162_get_runbooks 51.4s 8 15 $0.1758
✅ 176_network_policy_blocking_traffic_no_runbooks 46.5s 7 15 $0.1418
✅ 24_misconfigured_pvc 44.5s 8 20 $0.1437
✅ 43_current_datetime_from_prompt 3.5s 1 — $0.0085
✅ 61_exact_match_counting 11.4s 3 3 $0.0324
Total 35.2s avg 5.8 avg 14.0 avg $0.9934

📖 Legend
Icon Meaning
✅ The test was successful
➖ The test was skipped
⚠️ The test failed but is known to be flaky or known to fail
🚧 The test had a setup failure (not a code regression)
🔧 The test failed due to mock data issues (not a code regression)
🚫 The test was throttled by API rate limits/overload
❌ The test failed and should be fixed before merging the PR
🔄 Re-run evals manually

⚠️ Warning: Manual re-runs have NO default markers and will run ALL LLM tests (~100+), which can take 1+ hours. Use markers: regression or filter: test_name to limit scope.

Option 1: Comment on this PR with /eval:

/eval
markers: regression

Or with more options (one per line):

/eval
model: gpt-4o
markers: regression
filter: 09_crashpod
iterations: 5
Option Description
model Model(s) to test (default: same as automatic runs)
markers Pytest markers (no default - runs all tests!)
filter Pytest -k filter
iterations Number of runs, max 10

Option 2: Trigger via GitHub Actions UI → "Run workflow"

🏷️ Valid markers
  • chain-of-causation
  • compaction
  • context_window
  • coralogix
  • counting
  • database
  • datadog
  • datetime
  • easy
  • embeds
  • grafana-dashboard
  • hard
  • kafka
  • kubernetes
  • leaked-information
  • logs
  • loki
  • medium
  • metrics
  • network
  • newrelic
  • no-cicd
  • numerical
  • one-test
  • port-forward
  • prometheus
  • question-answer
  • regression
  • runbooks
  • slackbot
  • storage
  • toolset-limitation
  • traces
  • transparency
📋 Valid eval names (use with filter)

test_ask_holmes:

  • 01_how_many_pods
  • 02_what_is_wrong_with_pod
  • 03_what_is_the_command_to_port_forward
  • 04_related_k8s_events
  • 05_image_version
  • 06_explain_issue
  • 07_high_latency
  • 08_sock_shop_frontend
  • 09_crashpod
  • 100a_loki_historical_logs
  • 100b_loki_historical_logs_nonstandard_label
  • 101_loki_historical_logs_pod_deleted
  • 102_loki_label_discovery
  • 102a_loki_logs_transparency
  • 102b_loki_multiple_pods
  • 103_logs_transparency_default_limit
  • 104a_postgres_root_issue
  • 104b_postgres_missing_index_pgstat
  • 104c_postgres_minimal_missing_index
  • 105_redis_wrong_data_structure
  • 107_log_filter_http_status_code
  • 108_logs_nearby_lines
  • 109_logs_transparency_not_found
  • 10_image_pull_backoff
  • 110_cpu_graph_robusta_runner
  • 110_k8s_events_image_pull
  • 111_disabled_datadog_traces
  • 111_pod_names_contain_service
  • 111_tool_hallucination
  • 112_find_pvcs_by_uuid
  • 114_checkout_latency_tracing_rebuild
  • 115_checkout_errors_tracing
  • 117_new_relic_tracing
  • 117b_new_relic_block_embed
  • 118_new_relic_logs
  • 119_new_relic_metrics
  • 11_init_containers
  • 120_new_relic_traces2
  • 121_new_relic_checkout_errors_tracing
  • 122_new_relic_checkout_latency_tracing_rebuild
  • 123_new_relic_checkout_errors_tracing
  • 124_checkout_latency_prometheus
  • 12_job_crashing
  • 13a_pending_node_selector_basic
  • 13b_pending_node_selector_detailed
  • 14_pending_resources
  • 151_disabled_toolsets_fallback_only
  • 156_kafka_opensearch_latency
  • 157_disk_full_statefulset
  • 158_slack_chat_correct_date
  • 159_prometheus_high_cardinality_cpu
  • 15_failed_readiness_probe
  • 160_electricity_market_bidding_bug
  • 160a_cpu_per_namespace_graph
  • 160b_cpu_per_namespace_graph_with_prom_truncation
  • 160c_cpu_per_namespace_graph_with_global_truncation
  • 161_bidding_version_performance
  • 161_conversation_compaction
  • 162_get_runbooks
  • 163_compaction_follow_up
  • 164_datadog_traces_coupon_code
  • 165_alert_with_multiple_runbooks
  • 16_failed_no_toolset_found
  • 170_grafana_dashboard_filters
  • 173_coralogix_logs
  • 174_coralogix_traces_ad
  • 175_coralogix_metrics_frontend
  • 176_network_policy_blocking_traffic_no_runbooks
  • 177_grafana_home_dashboard
  • 178_grafana_search_dashboard_query
  • 179_grafana_big_dashboard_query
  • 17_oom_kill
  • 18_oom_kill_from_issues_history
  • 19_detect_missing_app_details
  • 20_long_log_file_search
  • 21_job_fail_curl_no_svc_account
  • 22_high_latency_dbi_down
  • 23_app_error_in_current_logs
  • 24_misconfigured_pvc
  • 25_misconfigured_ingress_class
  • 26_page_render_times
  • 27a_multi_container_logs
  • 27b_multi_container_logs
  • 28_permissions_error
  • 30_basic_promql_graph_cluster_memory
  • 32_basic_promql_graph_pod_cpu
  • 33_cpu_metrics_discovery
  • 34_memory_graph
  • 35_tempo
  • 36_argocd_find_resource
  • 37_argocd_wrong_namespace
  • 38_rabbitmq_split_head
  • 39_failed_toolset
  • 41_setup_argo
  • 42_dns_issues_result_all_tools
  • 42_dns_issues_result_new_tools
  • 42_dns_issues_result_new_tools_no_runbook
  • 42_dns_issues_result_old_tools
  • 42_dns_issues_steps_new_all_tools
  • 42_dns_issues_steps_new_tools
  • 42_dns_issues_steps_old_tools
  • 43_current_datetime_from_prompt
  • 43_slack_deployment_logs
  • 44_slack_statefulset_logs
  • 45_fetch_deployment_logs_simple
  • 46_job_crashing_no_longer_exists
  • 47_truncated_logs_context_window
  • 48_logs_since_thursday
  • 49_logs_since_last_week
  • 50_logs_since_specific_date
  • 50a_logs_since_last_specific_month
  • 51_logs_summarize_errors
  • 52_logs_login_issues
  • 53_logs_find_term
  • 54_azure_sql
  • 54_not_truncated_when_getting_pods
  • 55_kafka_runbook
  • 57_cluster_name_confusion
  • 57_wrong_namespace
  • 58_counting_pods_by_status
  • 59_label_based_counting
  • 60_count_less_than
  • 61_exact_match_counting
  • 62_fetch_error_logs_with_errors
  • 63_fetch_error_logs_no_errors
  • 64_keda_vs_hpa_confusion
  • 65_health_check_followup
  • 66_http_error_needle
  • 67_performance_degradation
  • 68_cascading_failures
  • 69_rate_limit_exhaustion
  • 70_memory_leak_detection
  • 71_connection_pool_starvation
  • 73a_time_window_anomaly
  • 73b_time_window_anomaly
  • 74_config_change_impact
  • 75_network_flapping
  • 76_service_discovery_issue
  • 77_liveness_probe_misconfiguration
  • 78a_missing_cpu_limits
  • 78b_cpu_quota_exceeded
  • 79_configmap_mount_issue
  • 80_pvc_storage_class_mismatch
  • 81_service_account_permission_denied
  • 82_pod_anti_affinity_conflict
  • 83_secret_not_found
  • 84_network_policy_blocking_traffic
  • 85_hpa_not_scaling
  • 86_configmap_like_but_secret
  • 89_runbook_missing_cloudwatch
  • 90_runbook_basic_selection
  • 91a_datadog_metrics_missing_namespace
  • 91b_datadog_metrics_pod_exists
  • 91c_datadog_metrics_deployment
  • 91d_datadog_metrics_historical_pod
  • 91e_datadog_custom_metrics
  • 91f_datadog_logs_historical_pod
  • 91g_datadog_metrics_mismatched_pod
  • 91h_datadog_logs_empty_query_with_url
  • 91i_datadog_metrics_empty_query_with_url
  • 92_cpu_graph_conversation
  • 93_calling_datadog
  • 93_events_since_specific_date
  • 94_runbook_transparency
  • 95_runbook_memory_leak_detection
  • 96_no_matching_runbook
  • 97_logs_clarification_needed
  • 99_logs_transparency_custom_time

test_investigate:

  • 01_oom_kill
  • 02_crashloop_backoff
  • 03_cpu_throttling
  • 04_image_pull_backoff
  • 05_crashpod
  • 06_job_failure
  • 07_job_syntax_error
  • 08_memory_pressure
  • 09_high_latency
  • 10_KubeDeploymentReplicasMismatch
  • 11_KubePodCrashLooping
  • 12_KubePodNotReady
  • 13_Watchdog
  • 14_tempo
  • 15_dns_resolution
  • 16_dns_resolution_no_tool
  • 17_investigate_correct_date

@aantn

aantn commented Dec 30, 2025

Copy link
Copy Markdown
Collaborator Author

/eval
filter: grafana
iterations: 5

@github-actions

github-actions Bot commented Dec 30, 2025 •

Copy link
Copy Markdown
Contributor

🧪 Manual Eval Results

Parameter Value
Triggered via /eval comment
Model bedrock/eu.anthropic.claude-sonnet-4-5-20250929-v1:0
Markers all LLM tests
Filter (-k) grafana
Iterations 5
Duration 12m 2s
Workflow View logs

Results of HolmesGPT evals

  • ask_holmes: 15/20 test cases were successful, 0 regressions, 5 setup failures
Status Test case Time Turns Tools Cost
🚧 170_grafana_dashboard_filters — — — —
🚧 170_grafana_dashboard_filters — — — —
🚧 170_grafana_dashboard_filters — — — —
🚧 170_grafana_dashboard_filters — — — —
🚧 170_grafana_dashboard_filters — — — —
✅ 177_grafana_home_dashboard 13.8s 3 3 $0.0987
✅ 177_grafana_home_dashboard 14.1s 3 3 $0.0991
✅ 177_grafana_home_dashboard 14.1s 3 3 $0.0991
✅ 177_grafana_home_dashboard 14.4s 3 3 $0.0991
✅ 177_grafana_home_dashboard 15.0s 3 3 $0.0994
✅ 178_grafana_search_dashboard_query 18.5s 4 5 $0.0584
✅ 178_grafana_search_dashboard_query 18.5s 4 5 $0.0582
✅ 178_grafana_search_dashboard_query 19.4s 4 5 $0.0587
✅ 178_grafana_search_dashboard_query 18.6s 4 5 $0.0587
✅ 178_grafana_search_dashboard_query 18.8s 4 5 $0.0588
✅ 179_grafana_big_dashboard_query 20.6s 5 6 $0.1176
✅ 179_grafana_big_dashboard_query 22.8s 5 6 $0.1178
✅ 179_grafana_big_dashboard_query 24.9s 5 6 $0.1317
✅ 179_grafana_big_dashboard_query 24.4s 5 6 $0.1178
✅ 179_grafana_big_dashboard_query 25.8s 5 6 $0.1318
Total 18.9s avg 4.0 avg 4.7 avg $1.4050

📖 Legend
Icon Meaning
✅ The test was successful
➖ The test was skipped
⚠️ The test failed but is known to be flaky or known to fail
🚧 The test had a setup failure (not a code regression)
🔧 The test failed due to mock data issues (not a code regression)
🚫 The test was throttled by API rate limits/overload
❌ The test failed and should be fixed before merging the PR
🔄 Re-run evals manually

⚠️ Warning: Manual re-runs have NO default markers and will run ALL LLM tests (~100+), which can take 1+ hours. Use markers: regression or filter: test_name to limit scope.

Option 1: Comment on this PR with /eval:

/eval
markers: regression

Or with more options (one per line):

/eval
model: gpt-4o
markers: regression
filter: 09_crashpod
iterations: 5
Option Description
model Model(s) to test (default: same as automatic runs)
markers Pytest markers (no default - runs all tests!)
filter Pytest -k filter
iterations Number of runs, max 10

Option 2: Trigger via GitHub Actions UI → "Run workflow"

🏷️ Valid markers
  • chain-of-causation
  • compaction
  • context_window
  • coralogix
  • counting
  • database
  • datadog
  • datetime
  • easy
  • embeds
  • grafana-dashboard
  • hard
  • kafka
  • kubernetes
  • leaked-information
  • logs
  • loki
  • medium
  • metrics
  • network
  • newrelic
  • no-cicd
  • numerical
  • one-test
  • port-forward
  • prometheus
  • question-answer
  • regression
  • runbooks
  • slackbot
  • storage
  • toolset-limitation
  • traces
  • transparency
📋 Valid eval names (use with filter)

test_ask_holmes:

  • 01_how_many_pods
  • 02_what_is_wrong_with_pod
  • 03_what_is_the_command_to_port_forward
  • 04_related_k8s_events
  • 05_image_version
  • 06_explain_issue
  • 07_high_latency
  • 08_sock_shop_frontend
  • 09_crashpod
  • 100a_loki_historical_logs
  • 100b_loki_historical_logs_nonstandard_label
  • 101_loki_historical_logs_pod_deleted
  • 102_loki_label_discovery
  • 102a_loki_logs_transparency
  • 102b_loki_multiple_pods
  • 103_logs_transparency_default_limit
  • 104a_postgres_root_issue
  • 104b_postgres_missing_index_pgstat
  • 104c_postgres_minimal_missing_index
  • 105_redis_wrong_data_structure
  • 107_log_filter_http_status_code
  • 108_logs_nearby_lines
  • 109_logs_transparency_not_found
  • 10_image_pull_backoff
  • 110_cpu_graph_robusta_runner
  • 110_k8s_events_image_pull
  • 111_disabled_datadog_traces
  • 111_pod_names_contain_service
  • 111_tool_hallucination
  • 112_find_pvcs_by_uuid
  • 114_checkout_latency_tracing_rebuild
  • 115_checkout_errors_tracing
  • 117_new_relic_tracing
  • 117b_new_relic_block_embed
  • 118_new_relic_logs
  • 119_new_relic_metrics
  • 11_init_containers
  • 120_new_relic_traces2
  • 121_new_relic_checkout_errors_tracing
  • 122_new_relic_checkout_latency_tracing_rebuild
  • 123_new_relic_checkout_errors_tracing
  • 124_checkout_latency_prometheus
  • 12_job_crashing
  • 13a_pending_node_selector_basic
  • 13b_pending_node_selector_detailed
  • 14_pending_resources
  • 151_disabled_toolsets_fallback_only
  • 156_kafka_opensearch_latency
  • 157_disk_full_statefulset
  • 158_slack_chat_correct_date
  • 159_prometheus_high_cardinality_cpu
  • 15_failed_readiness_probe
  • 160_electricity_market_bidding_bug
  • 160a_cpu_per_namespace_graph
  • 160b_cpu_per_namespace_graph_with_prom_truncation
  • 160c_cpu_per_namespace_graph_with_global_truncation
  • 161_bidding_version_performance
  • 161_conversation_compaction
  • 162_get_runbooks
  • 163_compaction_follow_up
  • 164_datadog_traces_coupon_code
  • 165_alert_with_multiple_runbooks
  • 16_failed_no_toolset_found
  • 170_grafana_dashboard_filters
  • 173_coralogix_logs
  • 174_coralogix_traces_ad
  • 175_coralogix_metrics_frontend
  • 176_network_policy_blocking_traffic_no_runbooks
  • 177_grafana_home_dashboard
  • 178_grafana_search_dashboard_query
  • 179_grafana_big_dashboard_query
  • 17_oom_kill
  • 18_oom_kill_from_issues_history
  • 19_detect_missing_app_details
  • 20_long_log_file_search
  • 21_job_fail_curl_no_svc_account
  • 22_high_latency_dbi_down
  • 23_app_error_in_current_logs
  • 24_misconfigured_pvc
  • 25_misconfigured_ingress_class
  • 26_page_render_times
  • 27a_multi_container_logs
  • 27b_multi_container_logs
  • 28_permissions_error
  • 30_basic_promql_graph_cluster_memory
  • 32_basic_promql_graph_pod_cpu
  • 33_cpu_metrics_discovery
  • 34_memory_graph
  • 35_tempo
  • 36_argocd_find_resource
  • 37_argocd_wrong_namespace
  • 38_rabbitmq_split_head
  • 39_failed_toolset
  • 41_setup_argo
  • 42_dns_issues_result_all_tools
  • 42_dns_issues_result_new_tools
  • 42_dns_issues_result_new_tools_no_runbook
  • 42_dns_issues_result_old_tools
  • 42_dns_issues_steps_new_all_tools
  • 42_dns_issues_steps_new_tools
  • 42_dns_issues_steps_old_tools
  • 43_current_datetime_from_prompt
  • 43_slack_deployment_logs
  • 44_slack_statefulset_logs
  • 45_fetch_deployment_logs_simple
  • 46_job_crashing_no_longer_exists
  • 47_truncated_logs_context_window
  • 48_logs_since_thursday
  • 49_logs_since_last_week
  • 50_logs_since_specific_date
  • 50a_logs_since_last_specific_month
  • 51_logs_summarize_errors
  • 52_logs_login_issues
  • 53_logs_find_term
  • 54_azure_sql
  • 54_not_truncated_when_getting_pods
  • 55_kafka_runbook
  • 57_cluster_name_confusion
  • 57_wrong_namespace
  • 58_counting_pods_by_status
  • 59_label_based_counting
  • 60_count_less_than
  • 61_exact_match_counting
  • 62_fetch_error_logs_with_errors
  • 63_fetch_error_logs_no_errors
  • 64_keda_vs_hpa_confusion
  • 65_health_check_followup
  • 66_http_error_needle
  • 67_performance_degradation
  • 68_cascading_failures
  • 69_rate_limit_exhaustion
  • 70_memory_leak_detection
  • 71_connection_pool_starvation
  • 73a_time_window_anomaly
  • 73b_time_window_anomaly
  • 74_config_change_impact
  • 75_network_flapping
  • 76_service_discovery_issue
  • 77_liveness_probe_misconfiguration
  • 78a_missing_cpu_limits
  • 78b_cpu_quota_exceeded
  • 79_configmap_mount_issue
  • 80_pvc_storage_class_mismatch
  • 81_service_account_permission_denied
  • 82_pod_anti_affinity_conflict
  • 83_secret_not_found
  • 84_network_policy_blocking_traffic
  • 85_hpa_not_scaling
  • 86_configmap_like_but_secret
  • 89_runbook_missing_cloudwatch
  • 90_runbook_basic_selection
  • 91a_datadog_metrics_missing_namespace
  • 91b_datadog_metrics_pod_exists
  • 91c_datadog_metrics_deployment
  • 91d_datadog_metrics_historical_pod
  • 91e_datadog_custom_metrics
  • 91f_datadog_logs_historical_pod
  • 91g_datadog_metrics_mismatched_pod
  • 91h_datadog_logs_empty_query_with_url
  • 91i_datadog_metrics_empty_query_with_url
  • 92_cpu_graph_conversation
  • 93_calling_datadog
  • 93_events_since_specific_date
  • 94_runbook_transparency
  • 95_runbook_memory_leak_detection
  • 96_no_matching_runbook
  • 97_logs_clarification_needed
  • 99_logs_transparency_custom_time

test_investigate:

  • 01_oom_kill
  • 02_crashloop_backoff
  • 03_cpu_throttling
  • 04_image_pull_backoff
  • 05_crashpod
  • 06_job_failure
  • 07_job_syntax_error
  • 08_memory_pressure
  • 09_high_latency
  • 10_KubeDeploymentReplicasMismatch
  • 11_KubePodCrashLooping
  • 12_KubePodNotReady
  • 13_Watchdog
  • 14_tempo
  • 15_dns_resolution
  • 16_dns_resolution_no_tool
  • 17_investigate_correct_date

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
holmes/plugins/toolsets/coralogix/toolset_coralogix.py (1)

62-101: Add extend_parameters() call to expose filter parameters.

The class inherits from JsonFilterMixin but doesn't call extend_parameters() to merge the filter parameters (max_depth, jsonpath, jq) with the tool's existing parameters. This prevents users from controlling response depth and applying JSON filtering.

Update line 68 to use parameters=self.extend_parameters({...}) instead of passing the parameters dict directly, consistent with how the Grafana and OpenSearch toolsets integrate the mixin.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd8a435 and 8ca3b82.

📒 Files selected for processing (2)
  • holmes/plugins/toolsets/coralogix/toolset_coralogix.py
  • pyproject.toml
🚧 Files skipped from review as they are similar to previous changes (1)
  • pyproject.toml
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Use Ruff for formatting and linting (configured in pyproject.toml)
Type hints required (mypy configuration in pyproject.toml)
ALWAYS place Python imports at the top of the file, not inside functions or methods

Files:

  • holmes/plugins/toolsets/coralogix/toolset_coralogix.py
holmes/plugins/toolsets/**

📄 CodeRabbit inference engine (CLAUDE.md)

Toolsets: organize as holmes/plugins/toolsets/{name}.yaml or {name}/ directories

Files:

  • holmes/plugins/toolsets/coralogix/toolset_coralogix.py
🧠 Learnings (2)
📚 Learning: 2025-12-29T08:35:37.668Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T08:35:37.668Z
Learning: Applies to holmes/plugins/toolsets/** : Toolsets: organize as `holmes/plugins/toolsets/{name}.yaml` or `{name}/` directories

Applied to files:

  • holmes/plugins/toolsets/coralogix/toolset_coralogix.py
📚 Learning: 2025-12-29T08:35:37.668Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T08:35:37.668Z
Learning: Applies to holmes/plugins/toolsets/**/*.yaml : All toolsets MUST return detailed error messages from underlying APIs to enable LLM self-correction, including exact query/command executed, time ranges and parameters used, and full API error response

Applied to files:

  • holmes/plugins/toolsets/coralogix/toolset_coralogix.py
🧬 Code graph analysis (1)
holmes/plugins/toolsets/coralogix/toolset_coralogix.py (2)
holmes/plugins/toolsets/json_filter_mixin.py (2)
  • JsonFilterMixin (60-149)
  • filter_result (120-149)
holmes/core/tools.py (2)
  • Tool (178-370)
  • StructuredToolResult (80-106)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build (3.11)
  • GitHub Check: build (3.12)
  • GitHub Check: build (3.10)
  • GitHub Check: llm_evals
🔇 Additional comments (2)
holmes/plugins/toolsets/coralogix/toolset_coralogix.py (2)

16-16: LGTM: Import statement correct.

The JsonFilterMixin import is properly placed at the top of the file and is used in the class signature.


170-176: LGTM: Result filtering integration correct.

The result handling correctly:

  1. Wraps the data in a StructuredToolResult
  2. Passes it through self.filter_result(wrapped, params) for filtering
  3. Returns the filtered result

The data structure change from a JSON string to a dictionary is appropriate for enabling JSON-based filtering.

Note: This assumes filter parameters are properly exposed via extend_parameters() (see previous comment).

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

@aantn Your eval run has finished. ✅ Completed successfully

👆 See updated results above.

@aantn aantn closed this Dec 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant