Skip to content

feat: Victoria Logs Integration#663

Closed
aniruddhaadak80 wants to merge 18 commits intoTracer-Cloud:mainfrom
aniruddhaadak80:feat/126-victoria-logs-integration
Closed

feat: Victoria Logs Integration#663
aniruddhaadak80 wants to merge 18 commits intoTracer-Cloud:mainfrom
aniruddhaadak80:feat/126-victoria-logs-integration

Conversation

@aniruddhaadak80
Copy link
Copy Markdown
Contributor

Resolves #126 by adding a complete Victoria Logs integration. This implements a VictoriaLogsClient and a new VictoriaLogsTool that queries using LogsQL.

Copilot AI review requested due to automatic review settings April 19, 2026 09:47
Comment thread app/services/victoria_logs/client.py Fixed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds first-class VictoriaLogs support to the investigation toolchain (Issue #126), alongside a broad formatting pass and several prompt/routing refinements to improve RCA correctness and avoid speculative diagnoses.

Changes:

  • Introduces VictoriaLogsClient + VictoriaLogsTool to query VictoriaLogs via LogsQL.
  • Adds VictoriaLogs integration config model and updates RCA / routing prompts for stricter evidence-first behavior.
  • Applies repo-wide formatting/line-wrapping refactors across tools, integrations, services, and CLI modules.

Reviewed changes

Copilot reviewed 231 out of 232 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
app/webapp.py Formatting-only change for health status assignment.
app/utils/ingest_delivery.py Formatting-only change for payload construction.
app/utils/discord_delivery.py Formatting-only change for function signatures.
app/utils/config.py Formatting-only change for env parsing helpers and signatures.
app/tools/utils/data_validation.py Formatting-only change (line wrap).
app/tools/utils/compaction.py Formatting-only change (signature + multiline condition).
app/tools/tool_decorator.py Formatting-only change; adds blank line before wrapper.
app/tools/registry.py Formatting-only change for function signature.
app/tools/registered_tool.py Formatting-only change for exception and dict construction.
app/tools/investigation_registry/docstring_parser.py Formatting-only change for list comprehension and regex call.
app/tools/base.py Formatting-only change (wrap outputs + metadata dict).
app/tools/VictoriaLogsTool/init.py New tool to query VictoriaLogs (currently has execution/registration issues).
app/tools/VercelLogsTool/init.py Formatting-only changes.
app/tools/VercelDeploymentStatusTool/init.py Formatting-only changes.
app/tools/TracerTasksTool/init.py Formatting-only change in schema.
app/tools/TracerFailedRunTool/init.py Formatting-only changes.
app/tools/TracerFailedJobsTool/init.py Formatting-only changes (multiline calls + dict literal).
app/tools/TracerErrorLogsTool/init.py Formatting-only changes.
app/tools/SentrySearchIssuesTool/init.py Formatting-only changes (dict literals).
app/tools/SentryIssueEventsTool/init.py Formatting-only changes (availability + error payload).
app/tools/SentryIssueDetailsTool/init.py Formatting-only changes (availability + error payload).
app/tools/SREGuidanceTool/knowledge_base.py Formatting-only changes (keyword lists).
app/tools/S3MarkerTool/init.py Formatting-only changes (error payload + signature).
app/tools/S3ListTool/init.py Formatting-only changes (error payload).
app/tools/S3InspectTool/init.py Formatting-only changes (availability + error payloads).
app/tools/S3GetObjectTool/init.py Formatting-only changes (availability + error payloads).
app/tools/PrefectWorkerHealthTool/init.py Formatting-only changes.
app/tools/PrefectFlowRunsTool/init.py Formatting-only changes.
app/tools/PostgreSQLReplicationStatusTool/init.py Formatting-only change (import grouping).
app/tools/OpsGenieAlertsTool/init.py Formatting-only changes.
app/tools/OpsGenieAlertDetailTool/init.py Formatting-only changes.
app/tools/OpenClawMCPTool/init.py Formatting-only changes.
app/tools/MongoDBAtlasMetricsTool/init.py Formatting-only changes.
app/tools/MariaDBStatusTool/init.py Formatting-only changes.
app/tools/MariaDBSlowQueriesTool/init.py Formatting-only changes.
app/tools/MariaDBReplicationTool/init.py Formatting-only changes.
app/tools/MariaDBProcessListTool/init.py Formatting-only changes.
app/tools/MariaDBInnoDBStatusTool/init.py Formatting-only changes.
app/tools/LambdaInvocationLogsTool/init.py Formatting-only changes.
app/tools/LambdaInspectTool/init.py Formatting-only changes.
app/tools/LambdaErrorsTool/init.py Formatting-only changes.
app/tools/LambdaConfigTool/init.py Formatting-only changes.
app/tools/JiraSearchIssuesTool/init.py Formatting-only changes.
app/tools/JiraIssueDetailTool/init.py Formatting-only changes.
app/tools/JiraCreateIssueTool/init.py Formatting-only changes.
app/tools/JiraAddCommentTool/init.py Formatting-only changes.
app/tools/HoneycombTracesTool/init.py Formatting-only changes.
app/tools/GrafanaTracesTool/init.py Formatting-only changes.
app/tools/GrafanaServiceNamesTool/init.py Formatting-only changes.
app/tools/GrafanaMetricsTool/init.py Formatting-only changes.
app/tools/GrafanaLogsTool/init.py Formatting-only changes.
app/tools/GrafanaAlertRulesTool/init.py Formatting-only changes.
app/tools/GitLabPipelinesTool/init.py Formatting-only changes.
app/tools/GitLabMRsTool/init.py Formatting-only changes.
app/tools/GitLabFileTool/init.py Formatting-only changes.
app/tools/GitLabCommitsTool/init.py Formatting-only + trailing comma fix.
app/tools/GitHubSearchCodeTool/init.py Formatting-only changes.
app/tools/GitHubRepositoryTreeTool/init.py Formatting-only changes.
app/tools/GitHubFileContentsTool/init.py Formatting-only changes.
app/tools/GitHubCommitsTool/init.py Formatting-only changes.
app/tools/ElasticsearchLogsTool/_client.py Formatting-only changes (helper + dict literal).
app/tools/ElasticsearchLogsTool/init.py Formatting-only changes.
app/tools/EKSPodLogsTool/init.py Formatting-only changes (logging + payload dict).
app/tools/EKSNodegroupHealthTool/init.py Formatting-only changes (payload dict).
app/tools/EKSNodeHealthTool/init.py Formatting-only changes (payload dict).
app/tools/EKSListNamespacesTool/init.py Formatting-only changes (list/dict construction).
app/tools/EKSListDeploymentsTool/init.py Formatting-only changes (payload dict + conditional).
app/tools/EKSEventsTool/init.py Formatting-only changes (payload dict + conditional).
app/tools/EKSDescribeClusterTool/init.py Formatting-only changes (payload dict).
app/tools/EKSDescribeAddonTool/init.py Formatting-only changes (payload dict).
app/tools/EKSDeploymentStatusTool/init.py Formatting-only changes (logging + payload dict).
app/tools/DataDogNodePodsTool/init.py Formatting-only changes.
app/tools/DataDogMonitorsTool/init.py Formatting-only changes.
app/tools/DataDogMetricsTool/init.py Formatting-only changes.
app/tools/DataDogLogsTool/_client.py Formatting-only changes (helper + dict literal).
app/tools/DataDogLogsTool/init.py Formatting-only changes (call + list comprehension wrap).
app/tools/DataDogEventsTool/init.py Formatting-only changes.
app/tools/DataDogContextTool/init.py Formatting-only changes.
app/tools/CoralogixLogsTool/init.py Formatting-only changes.
app/tools/CloudWatchLogsTool/init.py Formatting-only changes (schema + boto args).
app/tools/CloudWatchBatchMetricsTool/init.py Formatting-only changes (schema + helper calls).
app/tools/ClickHouseSystemHealthTool/init.py Formatting-only changes (import grouping).
app/tools/BitbucketSearchCodeTool/init.py Formatting-only changes.
app/tools/BitbucketFileContentsTool/init.py Formatting-only changes.
app/tools/BitbucketCommitsTool/init.py Formatting-only changes.
app/tools/AlertmanagerAlertsTool/init.py Formatting-only changes.
app/tools/AWSOperationTool/init.py Formatting-only changes.
app/state/factory.py Formatting-only changes (dict comprehension + cast wrapping).
app/state/agent_state.py Formatting-only changes (ConfigDict wrapping).
app/services/victoria_logs/client.py New VictoriaLogs HTTP client (NDJSON parsing + tenant header logic).
app/services/victoria_logs/init.py New service factory/export for VictoriaLogs.
app/services/tracer_client/tracer_integrations.py Formatting-only changes (signature + logging wrap).
app/services/tracer_client/aws_batch_jobs.py Formatting-only changes (ternary + comprehension wrap).
app/services/s3_client.py Formatting-only changes (payload dict + expression wrap).
app/services/lambda_client.py Formatting-only changes (credential checks + conditional wrap).
app/services/honeycomb/client.py Formatting-only changes (payload extraction + error payloads).
app/services/grafana/config.py Formatting-only changes (boolean expressions wrap).
app/services/grafana/base.py Formatting-only changes (list/dict construction + debug log).
app/services/google_docs/client.py Minor logic fix for 403/404 error messaging + formatting.
app/services/env.py Formatting-only changes (helper signature + string wrap).
app/services/eks/eks_k8s_client.py Formatting-only changes (logging + signature wrap).
app/services/eks/eks_client.py Formatting-only changes (kwargs dict + indexing wrap).
app/services/coralogix/client.py Formatting-only changes.
app/services/cloudwatch_client.py Formatting-only changes (credential checks).
app/services/aws_sdk_client.py Formatting-only changes (tuple return + list truncation wrap).
app/services/alertmanager/client.py Formatting-only changes (payload dict construction).
app/sandbox/runner.py Formatting-only changes (NamedTemporaryFile call).
app/remote/stream.py Formatting-only changes (slice spacing).
app/remote/slack_context.py Formatting-only changes (ValueError + warning wrap).
app/remote/renderer.py Formatting-only changes (frozenset literals).
app/remote/ops.py Formatting-only changes (exceptions + signature wrap).
app/pipeline/runners.py Formatting-only changes (ternary expression + imports + calls).
app/pipeline/routing.py Formatting-only changes (logger.exception wrap).
app/pipeline/graph.py Formatting-only changes (conditional edges call formatting).
app/nodes/root_cause_diagnosis/evidence_checker.py Formatting-only changes (constants + conditionals wrap).
app/nodes/resolve_integrations/node.py Formatting-only changes (tracker message wrap).
app/nodes/publish_findings/urls/aws.py Formatting-only change (single-line return).
app/nodes/publish_findings/renderers/terminal.py Formatting-only changes (slices + function signatures + print wrap).
app/nodes/publish_findings/formatters/report.py Formatting-only changes (regex + string assembly + comprehension wrap).
app/nodes/publish_findings/formatters/lineage.py Formatting-only changes (helpers + string wrap).
app/nodes/plan_actions/plan_actions.py Formatting-only changes (signature + calls + conditionals wrap).
app/nodes/investigate/node.py Formatting-only changes (casts + calls wrap).
app/nodes/investigate/models.py Formatting-only changes (field wraps + helpers).
app/nodes/extract_alert/models.py Updates alert source description (adds more sources) + formatting.
app/nodes/extract_alert/extract_node.py Formatting-only changes (logging, tracker fields, reaction calls).
app/nodes/extract_alert/extract.py Tightens LLM extraction instructions to reduce misrouting/speculation; formatting.
app/nodes/chat.py Formatting-only changes (blank line + bind_tools wrap).
app/masking/detectors.py Formatting-only changes (ternary + generator wrap).
app/masking/context.py Formatting-only changes (compiled patterns + signature wrap).
app/integrations/trello.py Formatting-only changes.
app/integrations/store.py Formatting-only changes (warning wrap).
app/integrations/sentry.py Formatting-only changes.
app/integrations/posthog.py Formatting-only changes.
app/integrations/postgresql.py Formatting-only changes (config dict + messages).
app/integrations/models.py Adds VictoriaLogsIntegrationConfig model + formatting changes.
app/integrations/mariadb.py Formatting-only changes.
app/integrations/kafka.py Formatting-only changes.
app/integrations/gitlab.py Formatting-only changes + minor quoting consistency.
app/integrations/github_issue_comments.py Formatting-only changes (string wrap + exception wrap).
app/integrations/clients/prefect/client.py Formatting-only changes (payload dicts + logging wrap).
app/integrations/clients/notion/client.py Formatting-only changes (payload dicts + logging wrap).
app/integrations/clickhouse.py Formatting-only changes (config parsing + error payload).
app/integrations/bitbucket.py Formatting-only changes.
app/integrations/azure_sql.py Formatting-only changes (builder + error payload).
app/integrations/main.py Formatting-only change (print wrap).
app/guardrails/rules.py Formatting-only changes (warning wrap).
app/guardrails/engine.py Formatting-only changes (super call + matches append + slicing).
app/guardrails/cli.py Formatting-only changes (redaction wrap).
app/guardrails/audit.py Formatting-only changes (preview wrap).
app/entrypoints/mcp.py Formatting-only changes (Field wraps).
app/dockerfile_test.py Formatting-only changes (assert formatting).
app/deployment/provider_config.py Formatting-only changes (function signatures + error strings).
app/deployment/ec2_config.py Formatting-only changes (write_text wrap).
app/constants/prompts.py Adds stricter evidence-first + anti-speculation requirements; updates router prompt.
app/cli/wizard/prompts.py Formatting-only changes (prompt tokens + signature wrap).
app/cli/wizard/init.py Formatting-only change (blank line).
app/cli/update.py Formatting-only changes (constants + exception messages + prompt).
app/cli/tests/runner.py Formatting-only change (call wrap).
app/cli/tests/catalog.py Formatting-only changes (signature + any() wrap).
app/cli/tests/init.py Formatting-only changes (import grouping).
app/cli/prompt_support.py Formatting-only changes (signature wrap).
app/cli/payload.py Formatting-only change (print wrap).
app/cli/local_llm/ollama.py Formatting-only changes (print wrap + subprocess call).
app/cli/local_llm/hardware.py Formatting-only changes (exception tuple + returns).
app/cli/local_llm/command.py Formatting-only changes (print wrap).
app/cli/layout.py Formatting-only changes (Text assembly wrap).
app/cli/investigate_input.py Formatting-only change (list comprehension wrap).
app/cli/investigate.py Formatting-only changes (tuple assignment wrap).
app/cli/health_view.py Formatting-only changes (Panel + json.dumps wrap).
app/cli/errors.py Formatting-only changes (click.echo wrap).
app/cli/deploy.py Formatting-only changes (subprocess run wrap + logging wrap).
app/cli/commands/tests.py Formatting-only changes (option formatting + signature wrap).
app/cli/commands/remote_health.py Formatting-only changes (rich panel composition wrap).
app/cli/commands/onboard.py Formatting-only changes (signature wrap).
app/cli/commands/integrations.py Formatting-only changes (import grouping + click args/options).
app/cli/commands/general.py Formatting-only changes (options + json.dumps wrap).
app/cli/commands/doctor.py Formatting-only changes (list comp + dict literal wrap).
app/cli/commands/deploy.py Formatting-only changes (signature wrap + imports + option wrap).
app/cli/args.py Formatting-only changes (argument wrap).
app/cli/main.py Formatting-only changes (click option wrap + blank line).
app/auth/jwt_auth.py Formatting-only changes (blank lines + exception tuple + error wrap).
app/analytics/provider.py Formatting-only change (Thread init wrap).
app/analytics/cli.py Formatting-only changes (env parsing + capture call wrap).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/tools/VictoriaLogsTool/__init__.py Outdated
Comment on lines +8 to +11
class VictoriaLogsTool(BaseTool):
name = "victoria_logs_query"
source = "victoria_logs"
description = "Query structured logs from VictoriaLogs using LogsQL to investigate application errors or anomalies."
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

source = "victoria_logs" is not a valid EvidenceSource value (see app/types/evidence.py). Because BaseTool.__init_subclass__() validates metadata at import time, this will raise during module import and prevent the tool registry from loading. Add "victoria_logs" to the EvidenceSource Literal (or change this tool's source to an existing value if that's intended).

Copilot uses AI. Check for mistakes.
Comment on lines +39 to +60
def extract_params(self, sources: dict) -> dict[str, Any]:
return {}

def run(
self, query: str, limit: int = 50, start: str = "-1h", **kwargs: Any
) -> dict[str, Any]:
vl_conf = kwargs.get("sources", {}).get("victoria_logs", {})
config = VictoriaLogsIntegrationConfig(
base_url=vl_conf.get("base_url", ""),
tenant_id=vl_conf.get("tenant_id", "0"),
)

if not config.base_url:
return {
"source": "victoria_logs",
"available": False,
"error": "VictoriaLogs base_url is required.",
}

client = VictoriaLogsClient(config)
result = client.query_logs(query=query, limit=limit, start=start)

Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

extract_params() returns {}, but the investigation executor calls action.run(**action.extract_params(...)). That means run() will be invoked without the required query argument and will raise a TypeError. Implement extract_params() to supply at least query/limit/start (and any needed connection params), and update run() to accept those explicitly rather than relying on kwargs["sources"] which will never be passed by the executor.

Copilot uses AI. Check for mistakes.
Comment thread app/services/victoria_logs/client.py Outdated
Comment on lines +23 to +27
params = {"query": query, "limit": limit, "start": start}
headers = {}
if self.config.tenant_id:
headers["AccountID"] = self.config.tenant_id

Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

tenant_id defaults to the string "0", which is truthy, so this client will always send an AccountID: 0 header. If "0" is intended to mean “no tenant scoping” (as implied elsewhere in the codebase), consider only setting this header when tenant_id is non-empty and not "0" to avoid unintended scoping or auth failures.

Copilot uses AI. Check for mistakes.
Comment on lines +32 to +40
rows = []
for line in resp.text.splitlines():
if not line.strip():
continue
try:
rows.append(json.loads(line))
except Exception:
pass

Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

The NDJSON parsing loop silently ignores JSON decoding failures (except Exception: pass). This can turn partial/invalid responses into “success” with missing rows and no signal to callers. Catch json.JSONDecodeError explicitly and return a warning/error (e.g., include a parse_errors count or fail the request if any non-empty line is invalid).

Copilot uses AI. Check for mistakes.
Fix formatting and typing issues previously caught by the CI pipelines, and constrain formatting strictly to the modified files.
@aniruddhaadak80 aniruddhaadak80 force-pushed the feat/126-victoria-logs-integration branch from 8858ebc to bdfbfe4 Compare April 19, 2026 09:55
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 19, 2026

Greptile Summary

This PR adds a VictoriaLogsClient, VictoriaLogsTool, and associated verification/model plumbing for Victoria Logs integration. Several supporting files (prompts, alert extraction) receive unrelated improvements.

  • P1 — Tool permanently non-functional: victoria_logs is absent from both the direct_services tuple and load_env_integrations() in catalog.py, so resolve_effective_integrations never populates sources[\"victoria_logs\"]. VictoriaLogsTool.run() will always hit the empty-base_url guard and return an error regardless of configuration.
  • The EffectiveIntegrations model gap and integration_id injection issues flagged in prior threads remain open and compound this problem.

Confidence Score: 3/5

Not safe to merge — the VictoriaLogsTool is permanently non-functional due to missing catalog wiring, and two issues flagged in prior threads remain unresolved.

A P1 defect means the primary deliverable of this PR (a working VictoriaLogs query tool) cannot function at all at runtime. Combined with two open prior-thread P1s (EffectiveIntegrations missing field, integration_id injection), the integration has no usable path to production.

app/integrations/catalog.py (missing direct_services entry + load_env_integrations block), app/integrations/models.py (EffectiveIntegrations missing victoria_logs field)

Important Files Changed

Filename Overview
app/integrations/catalog.py Formatting-only changes; victoria_logs is missing from direct_services and load_env_integrations, so integration is never promoted to effective config
app/tools/VictoriaLogsTool/init.py New VictoriaLogsTool; permanently non-functional because resolve_effective_integrations never populates sources["victoria_logs"]
app/services/victoria_logs/client.py New VictoriaLogsClient wrapping LogsQL HTTP API; uses synchronous httpx.get which may block the event loop
app/integrations/models.py Adds VictoriaLogsIntegrationConfig (correct); victoria_logs field still missing from EffectiveIntegrations (flagged in prior thread)
app/integrations/verify.py Adds _verify_victoria_logs and registers it in SUPPORTED_VERIFY_SERVICES and CORE_VERIFY_SERVICES; verification logic is correct

Sequence Diagram

sequenceDiagram
    participant LLM as LLM Planner
    participant Tool as VictoriaLogsTool
    participant Catalog as catalog.py
    participant Client as VictoriaLogsClient
    participant VL as VictoriaLogs API

    LLM->>Tool: run(query, sources={})
    Note over Catalog: ❌ victoria_logs missing from direct_services & load_env_integrations
    Tool->>Tool: vl_conf = sources.get(victoria_logs) → {}
    Tool->>Tool: config.base_url == empty → guard fires
    Tool-->>LLM: {available: false, error: base_url required}

    Note over Tool,VL: Happy path (after fix)
    LLM->>Tool: run(query, sources={victoria_logs: {base_url:...}})
    Tool->>Client: query_logs(query, limit, start)
    Client->>VL: GET /select/logsql/query
    VL-->>Client: NDJSON rows
    Client-->>Tool: {success: true, rows: [...]}
    Tool-->>LLM: {available: true, logs: [...]}
Loading

Comments Outside Diff (1)

  1. app/integrations/catalog.py, line 1525-1551 (link)

    P1 victoria_logs absent from direct_services and load_env_integrations

    resolve_effective_integrations populates effective["victoria_logs"] only for services listed in direct_services (lines 1525–1551) and/or those loaded in load_env_integrations. Neither list includes victoria_logs, so the key is never added to effective. At runtime, VictoriaLogsTool.run() reads its config from kwargs.get("sources", {}).get("victoria_logs", {}), which will always be an empty dict, hitting the base_url guard immediately and returning an error on every invocation.

    Two additions are needed:

    1. Add "victoria_logs" to the direct_services tuple so a DB-stored credential is promoted to effective.
    2. Add a VICTORIA_LOGS_BASE_URL block to load_env_integrations() so env-var-backed configuration is picked up (following the same pattern used for alertmanager at line 1423).

    Without these, the tool is unreachable through normal operation regardless of how the integration is configured.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: app/integrations/catalog.py
    Line: 1525-1551
    
    Comment:
    **`victoria_logs` absent from `direct_services` and `load_env_integrations`**
    
    `resolve_effective_integrations` populates `effective["victoria_logs"]` only for services listed in `direct_services` (lines 1525–1551) and/or those loaded in `load_env_integrations`. Neither list includes `victoria_logs`, so the key is never added to `effective`. At runtime, `VictoriaLogsTool.run()` reads its config from `kwargs.get("sources", {}).get("victoria_logs", {})`, which will always be an empty dict, hitting the `base_url` guard immediately and returning an error on every invocation.
    
    Two additions are needed:
    1. Add `"victoria_logs"` to the `direct_services` tuple so a DB-stored credential is promoted to `effective`.
    2. Add a `VICTORIA_LOGS_BASE_URL` block to `load_env_integrations()` so env-var-backed configuration is picked up (following the same pattern used for `alertmanager` at line 1423).
    
    Without these, the tool is unreachable through normal operation regardless of how the integration is configured.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: app/integrations/catalog.py
Line: 1525-1551

Comment:
**`victoria_logs` absent from `direct_services` and `load_env_integrations`**

`resolve_effective_integrations` populates `effective["victoria_logs"]` only for services listed in `direct_services` (lines 1525–1551) and/or those loaded in `load_env_integrations`. Neither list includes `victoria_logs`, so the key is never added to `effective`. At runtime, `VictoriaLogsTool.run()` reads its config from `kwargs.get("sources", {}).get("victoria_logs", {})`, which will always be an empty dict, hitting the `base_url` guard immediately and returning an error on every invocation.

Two additions are needed:
1. Add `"victoria_logs"` to the `direct_services` tuple so a DB-stored credential is promoted to `effective`.
2. Add a `VICTORIA_LOGS_BASE_URL` block to `load_env_integrations()` so env-var-backed configuration is picked up (following the same pattern used for `alertmanager` at line 1423).

Without these, the tool is unreachable through normal operation regardless of how the integration is configured.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: app/services/victoria_logs/client.py
Line: 30

Comment:
**Synchronous HTTP blocks the event loop**

`httpx.get()` is a blocking call. If `VictoriaLogsClient.query_logs` is invoked from an async route handler or an async node in the investigation graph, it will block the entire event loop for the full 30-second timeout in the worst case. All other comparable log-service clients (Coralogix, OpenObserve, OpenSearch) that the platform uses should be checked for consistency; if this codebase runs these synchronously in a thread pool that is acceptable, but if any callers are async `await`-ing the result, consider switching to `httpx.AsyncClient` with an `async def query_logs`.

If keeping synchronous, wrap call sites with `asyncio.to_thread`.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (3): Last reviewed commit: "Merge upstream/main and resolve conflict..." | Re-trigger Greptile

Comment thread app/integrations/catalog.py Outdated
Comment on lines +190 to +196
victoria_logs_config = VictoriaLogsIntegrationConfig.model_validate(
{
"base_url": credentials.get("base_url", ""),
"tenant_id": credentials.get("tenant_id", "0"),
"integration_id": integration.get("id", ""),
}
)
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.

P1 Extra field integration_id breaks DB-configured Victoria Logs

VictoriaLogsIntegrationConfig extends StrictConfigModel which sets extra="forbid". Passing integration_id to model_validate() will always raise a ValidationError, which is silently swallowed by the surrounding except Exception: continue. This means any Victoria Logs integration stored in the database will be permanently skipped — only env-var-backed (VICTORIA_LOGS_BASE_URL) configurations will work.

Suggested change
victoria_logs_config = VictoriaLogsIntegrationConfig.model_validate(
{
"base_url": credentials.get("base_url", ""),
"tenant_id": credentials.get("tenant_id", "0"),
"integration_id": integration.get("id", ""),
}
)
victoria_logs_config = VictoriaLogsIntegrationConfig.model_validate(
{
"base_url": credentials.get("base_url", ""),
"tenant_id": credentials.get("tenant_id", "0"),
}
)
Prompt To Fix With AI
This is a comment left during a code review.
Path: app/integrations/catalog.py
Line: 190-196

Comment:
**Extra field `integration_id` breaks DB-configured Victoria Logs**

`VictoriaLogsIntegrationConfig` extends `StrictConfigModel` which sets `extra="forbid"`. Passing `integration_id` to `model_validate()` will always raise a `ValidationError`, which is silently swallowed by the surrounding `except Exception: continue`. This means any Victoria Logs integration stored in the database will be permanently skipped — only env-var-backed (`VICTORIA_LOGS_BASE_URL`) configurations will work.

```suggestion
                victoria_logs_config = VictoriaLogsIntegrationConfig.model_validate(
                    {
                        "base_url": credentials.get("base_url", ""),
                        "tenant_id": credentials.get("tenant_id", "0"),
                    }
                )
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 508 to 510
openclaw: EffectiveIntegrationEntry | None = None
mysql: EffectiveIntegrationEntry | None = None
alertmanager: EffectiveIntegrationEntry | None = None
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.

P1 victoria_logs missing from EffectiveIntegrations

EffectiveIntegrations also extends StrictConfigModel (extra="forbid"). Any code that hydrates this model from the resolved integrations dict will raise a ValidationError if victoria_logs is present. All other integrations (grafana, datadog, coralogix, alertmanager, etc.) have a corresponding field here; victoria_logs needs one too.

Suggested change
openclaw: EffectiveIntegrationEntry | None = None
mysql: EffectiveIntegrationEntry | None = None
alertmanager: EffectiveIntegrationEntry | None = None
alertmanager: EffectiveIntegrationEntry | None = None
victoria_logs: EffectiveIntegrationEntry | None = None
Prompt To Fix With AI
This is a comment left during a code review.
Path: app/integrations/models.py
Line: 508-510

Comment:
**`victoria_logs` missing from `EffectiveIntegrations`**

`EffectiveIntegrations` also extends `StrictConfigModel` (`extra="forbid"`). Any code that hydrates this model from the resolved integrations dict will raise a `ValidationError` if `victoria_logs` is present. All other integrations (grafana, datadog, coralogix, alertmanager, etc.) have a corresponding field here; `victoria_logs` needs one too.

```suggestion
    alertmanager: EffectiveIntegrationEntry | None = None
    victoria_logs: EffectiveIntegrationEntry | None = None
```

How can I resolve this? If you propose a fix, please make it concise.

Comment thread app/services/victoria_logs/client.py Outdated
Comment on lines +36 to +38
import contextlib
with contextlib.suppress(Exception):
rows.append(json.loads(line))
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.

P2 import contextlib inside the loop

Module imports should be at the top of the file, not inside a for loop. Python caches them so it won't crash, but it's non-idiomatic and obscures intent. Move the import to the module level alongside the other imports.

Suggested change
import contextlib
with contextlib.suppress(Exception):
rows.append(json.loads(line))
import contextlib
import json
from typing import Any
import httpx

Then remove the in-loop import and keep only with contextlib.suppress(Exception):.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/services/victoria_logs/client.py
Line: 36-38

Comment:
**`import contextlib` inside the loop**

Module imports should be at the top of the file, not inside a `for` loop. Python caches them so it won't crash, but it's non-idiomatic and obscures intent. Move the import to the module level alongside the other imports.

```suggestion
import contextlib
import json
from typing import Any

import httpx
```
Then remove the in-loop import and keep only `with contextlib.suppress(Exception):`.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines 23 to 29
alert_source: str | None = Field(
default=None,
description=(
"Platform that fired the alert: 'grafana', 'datadog', 'honeycomb', "
"'coralogix', 'cloudwatch', or None if unknown"
"'coralogix', 'cloudwatch', 'eks', 'alertmanager', or None if unknown"
),
)
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.

P2 alert_source description omits victoria_logs

All other log/observability integrations added to the platform are listed in this field's description to guide the LLM. The extract prompt in extract.py also enumerates them explicitly. If VictoriaLogs can be the origin of an alert (e.g. alerting rules inside VictoriaLogs), the LLM will have no hint to set alert_source = "victoria_logs". Consider adding it to the allowed set if applicable.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/nodes/extract_alert/models.py
Line: 23-29

Comment:
**`alert_source` description omits `victoria_logs`**

All other log/observability integrations added to the platform are listed in this field's description to guide the LLM. The extract prompt in `extract.py` also enumerates them explicitly. If VictoriaLogs can be the origin of an alert (e.g. alerting rules inside VictoriaLogs), the LLM will have no hint to set `alert_source = "victoria_logs"`. Consider adding it to the allowed set if applicable.

How can I resolve this? If you propose a fix, please make it concise.

- Remove forbidden extra field integration_id passed to VictoriaLogsIntegrationConfig
- Add �ictoria_logs to EffectiveIntegrations model
- Move import contextlib to top of module in VictoriaLogsClient
Copy link
Copy Markdown
Member

@VaibhavUpreti VaibhavUpreti left a comment

Choose a reason for hiding this comment

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

Hi @aniruddhaadak80, Could you please add a demo image or video showcasing the feature? Also, kindly update the documentation with any relevant setup instructions.

Once that’s done, please tag @yashksaini-coder and @Devesh36 for an initial review.

Thank you!

yashksaini-coder

This comment was marked as duplicate.

Copy link
Copy Markdown
Collaborator

@yashksaini-coder yashksaini-coder left a comment

Choose a reason for hiding this comment

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

A few things need to be fixed before this can move forward — detailed inline comments below on each file.

Comment thread app/constants/prompts.py Outdated
You can query connected systems (e.g., Tracer run/task data, logs, metrics, failed jobs/tools) and developer tooling (e.g., GitHub and Sentry) using available tools.

CRITICAL RCA BEHAVIORS:
- Evidence First: Clearly separate direct observations from inferences. Do not make premature root-cause claims before sufficient evidence is gathered.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

These prompt changes (CRITICAL RCA BEHAVIORS block and the general chat rewrite) have nothing to do with Victoria Logs. Please remove them from this PR. If you think they're worth making, open a separate PR for them.

@classmethod
def _normalize_dataset(cls, value: object) -> str:
return str(value or DEFAULT_HONEYCOMB_DATASET).strip() or DEFAULT_HONEYCOMB_DATASET
return (
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

VictoriaLogsIntegrationConfig is imported in verify.py, the service init, and the tool — but it's never actually defined anywhere in this PR or in main. This will throw an ImportError the moment any of those modules are loaded. You need to add the Pydantic model class here, something like:\n\npython\nclass VictoriaLogsIntegrationConfig(StrictConfigModel):\n base_url: str = ""\n tenant_id: str = "0"\n integration_id: str = ""\n

from typing import Any

from app.integrations.models import VictoriaLogsIntegrationConfig
from app.services.victoria_logs.client import VictoriaLogsClient
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This import will crash at load time because VictoriaLogsIntegrationConfig doesn't exist in models.py. Fix the model definition first (see comment on models.py).

@@ -276,13 +300,33 @@ def _build_sts_client(config: dict[str, Any]) -> tuple[Any, str, str]:
region_name=region,
aws_access_key_id=credentials.access_key_id if credentials else "",
aws_secret_access_key=credentials.secret_access_key if credentials else "",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The verify function itself looks fine, but it won't actually get called. For victoria_logs to appear in effective_integrations, catalog.py needs a classification block for it (similar to how other services are handled in _classify_service_instance). Without that, the config will never reach here. Please also add load_env_integrations() support with env vars like VICTORIA_LOGS_URL and VICTORIA_LOGS_TENANT_ID.

Comment thread app/nodes/extract_alert/extract.py Outdated
is_noise=false (default) for: any alert, error, failure, incident, warning, monitoring notification (including health checks and informational states).
When in doubt, set is_noise=false.

CRITICAL INSTRUCTIONS FOR RCA CAPABILITY:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

These changes to alert_source routing and the new CRITICAL INSTRUCTIONS block are not related to Victoria Logs at all. Please remove them from this PR — they change core routing behaviour and would need their own review and tests.

Comment thread tests/integrations/test_victoria_logs.py Fixed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Copy Markdown
Collaborator

@yashksaini-coder yashksaini-coder left a comment

Choose a reason for hiding this comment

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

Great progress — all the P1 blockers from prior rounds are fixed (EvidenceSource, catalog wiring, EffectiveIntegrations, integration_id injection). Thank you for working through those. One critical runtime bug remains before this can merge.


🔴 Critical — extract_params() returns {}TypeError on every real invocation

File: app/tools/VictoriaLogsTool/__init__.py lines 40–50

The investigation executor calls:

kwargs = action.extract_params(available_sources)  # → {}
data = action.run(**kwargs)                         # → run() with no args

But run(self, query: str, ...) declares query as a required positional argument with no default. Python raises TypeError: run() missing 1 required positional argument: 'query' every time the tool fires. The tool will never successfully execute in an investigation.

Fix — implement extract_params following the same pattern as CoralogixLogsTool / ElasticsearchLogsTool:

def extract_params(self, sources: dict) -> dict[str, Any]:
    vl = sources.get("victoria_logs", {})
    return {
        "query": vl.get("default_query", "*"),
        "limit": vl.get("limit", 50),
        "start": vl.get("start", "-1h"),
        "sources": sources,   # so run() can pull credentials from kwargs
    }

🟡 Major — tenant_id = "0" always truthy → AccountID: 0 sent on every request

bool("0") is True, so the if self.config.tenant_id: guard in client.py always fires and adds AccountID: 0 to every HTTP request — even when no multi-tenancy is configured. Non-multi-tenant VictoriaLogs deployments may reject or misroute this header.

Fix: Change to tenant_id: str | None = None in the config model and update the guard to if self.config.tenant_id is not None:. Update catalog.py line 1544 accordingly.


🟠 Minor — 'victorialogs' vs 'victoria_logs' inconsistency

extract.py and models.py tell the LLM to output "victorialogs" (no underscore) as alert_source, but EvidenceSource, tool.source, and all catalog keys use "victoria_logs" (underscore). Please standardize on "victoria_logs" throughout — catalog.py already has the alias.

🟠 Minor — No VictoriaLogsTool unit tests

The 3 existing tests cover integration plumbing (env load, classification, verify). There are no tests for VictoriaLogsTool.is_available(), extract_params(), or run() happy/error paths. Please add tests/tools/test_victoria_logs_tool.py.

🟠 Minor — Missing integration docs

The contributor checklist in CONTRIBUTING.md requires a docs/<integration>.mdx page. Please add docs/victoria_logs.mdx with setup, env vars, and verification steps.


Once those are addressed this will be in good shape to merge. The core integration work is solid.

fix: VictoriaLogsTool extract_params implementation
fix: VictoriaLogs tenant_id truthiness bug and multi-tenancy guards
refactor: Standardize victoria_logs naming and support env vars
revert: Out-of-scope changes in extract_alert/extract.py
@muddlebee
Copy link
Copy Markdown
Collaborator

@aniruddhaadak80 CI is still red.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Victoria logs integration

6 participants