--- title: "groundcover" --- Investigate incidents with [groundcover](https://groundcover.com) logs and traces, queried with **gcQL** (groundcover Query Language) over groundcover's public, read-only **MCP** endpoint. This is the initial integration: configuration, verification, and three read-only tools (logs, traces, and the gcQL reference). More signals (metrics, APM, Kubernetes events/entities, monitors, monitor issues) and alert-source routing land in follow-up releases. v1 is read-only — no monitor creation, silencing, or other mutating actions. ## Commands | Command | What it does | | --- | --- | | `opensre integrations setup groundcover` | Store a groundcover service-account token and routing settings | | `opensre integrations verify groundcover` | Connect to the MCP endpoint, list tools, and check workspace routing | ## 1. Create a read-only service-account token In groundcover: **Settings → Access → Service Accounts** → create a service account with a **read-only** policy → create an **API key** and copy it (shown once). OpenSRE never performs write actions. ## 2. Configure Run the interactive setup: ```bash opensre integrations setup groundcover ``` …or set environment variables: ```bash export GROUNDCOVER_API_KEY="" # alias: GROUNDCOVER_MCP_TOKEN # Optional — defaults shown: export GROUNDCOVER_MCP_URL="https://mcp.groundcover.com/api/mcp" export GROUNDCOVER_TIMEZONE="UTC" # Only for multi-workspace / multi-backend accounts: export GROUNDCOVER_TENANT_UUID="" export GROUNDCOVER_BACKEND_ID="" ``` Single-workspace accounts need only the token. If your account has multiple workspaces or backends, verification tells you exactly which value to set. Multiple instances: ```bash export GROUNDCOVER_INSTANCES='[ {"name":"prod","api_key":"...","tenant_uuid":"...","backend_id":"prod"}, {"name":"staging","api_key":"...","tenant_uuid":"...","backend_id":"staging"} ]' ``` `opensre integrations list` shows integrations saved to the local store (via `setup`); environment-variable configuration is still picked up by `verify` and at runtime. ## 3. Verify ```bash opensre integrations verify groundcover ``` Verification connects to the MCP endpoint, confirms the expected read-only tool surface is present, and lists your workspaces. It returns `passed`, `missing` (token not configured), or `failed` with an actionable message — for example, naming the missing or mistyped `GROUNDCOVER_TENANT_UUID` / `GROUNDCOVER_BACKEND_ID` when the account is ambiguous. Tokens are never printed. ## Tools | Tool | Use it for | | --- | --- | | `get_groundcover_query_reference` | The gcQL syntax reference — call once before writing queries | | `query_groundcover_logs` | Application errors, exceptions, and log events | | `query_groundcover_traces` | Slow/failing spans and request correlations | ## Writing efficient gcQL gcQL is a pipe-based language: a query starts with a filter (or `*`) and pipes through operators. These rules keep queries fast and valid: - **Lead with the filter directly** — `level:error | …`, not `* | filter level:error`. The `| filter` pipe is for post-aggregation conditions on computed aliases. - **Project or aggregate — don't pull raw rows blindly.** Use `| fields a, b, …` to select columns, or `| stats …` to aggregate. A bare select-all (` | limit N`) can be rejected by the backend. - **Keep the time window narrow.** The default is the last 1 hour; widen only after an empty or inconclusive result. - **Always include `| limit N`** — it caps rows returned (not data scanned), so for wide ranges prefer `stats`/aggregations. - **Discover fields** with `* | field_names` (or `get_groundcover_query_reference`). Examples: ```text # Recent error logs for a workload (projected) level:error workload:checkout | fields _time, instance, content | limit 50 # Error count per workload in one query level:error | stats by (env, cluster, namespace, workload) count() as errors | sort by (errors desc) | limit 20 # Slowest spans for a service (projected) duration_seconds>0.5 workload:checkout | fields _time, span_name, duration_seconds, status_code | limit 50 # 5xx rate per workload (HTTP spans use status_code; status:error is universal) status_code>=500 | stats by (workload) count() as errors | sort by (errors desc) | limit 20 ``` ## Troubleshooting | Symptom | Fix | | --- | --- | | `missing` on verify | Set `GROUNDCOVER_API_KEY` (or `GROUNDCOVER_MCP_TOKEN`). | | `401 Unauthorized` | Regenerate the service-account token; ensure it has read access. | | `Account has N workspaces…` | Set `GROUNDCOVER_TENANT_UUID` to the listed tenant. | | `…has N backends…` | Set `GROUNDCOVER_BACKEND_ID` to the listed backend. | | `failed to query …` | Project with `| fields …` or aggregate with `| stats …`; narrow the time window; avoid a bare raw select-all. | | Empty results | Run `* | field_names` to find real field names; avoid leading-wildcard globs. | | Not shown in `integrations list` | `list` shows the local store — run `opensre integrations setup groundcover` (env vars still work for `verify`/runtime). |