Connectors

How Horus reads runtime evidence from Elasticsearch, Grafana, MongoDB, PostgreSQL, Redis/BullMQ, Sentry, Axiom, and Shopify.

Connectors are how Horus reads runtime evidence. They are read-only adapters to your existing systems. Horus does not write to production, replace your observability stack, or require you to change your applications.

Source intelligence is separate

Connectors are for runtime evidence. Source intelligence is for code context. You can use one without the other, but investigations are strongest when both are configured. See Source intelligence.

Supported runtime connectors

ConnectorEvidence typeWhen to use it
ElasticsearchLogs and error signaturesYou aggregate application logs in Elasticsearch and want error counts, first/last occurrences, and trace IDs.
GrafanaMetricsYou have dashboards in Grafana and want latency, error-rate, throughput, and queue-growth evidence.
MongoDBApplication stateYou store operational or domain state in MongoDB and want counts, staleness, and anomalous statuses.
Redis / BullMQQueue runtime stateYou run BullMQ on Redis and want queue depths, failed jobs, and worker health.
PostgreSQLApplication stateYou store operational or domain state in PostgreSQL and want counts, staleness, and anomalous rows from allowlisted tables.
SentryError eventsYou track exceptions in Sentry and want grouped errors with a direct seed into the implicated code.
AxiomLogs and error signaturesYou ship structured logs to Axiom and want incident-relevant error signatures (with counts) and recent events folded in as evidence.
ShopifyAdmin / business stateYou run a Shopify store and want order, inventory, and fulfillment state as evidence — supplied via your own read-only Admin GraphQL queries (--shopify-query, or config queries for watch).

Git evidence — recent commits, ownership, and change history — is read from the local repository directly and does not require a connector.

Shared concepts

Every connector is scoped to a project and environment. The horus connect command writes non-secret settings into .horus/config.json and encrypts credentials (AES-256-GCM) into .horus/secrets.local.json. You can have different Elasticsearch, Grafana, MongoDB, PostgreSQL, Redis, Sentry, Axiom, or Shopify endpoints for staging and production inside the same project.

By default, horus connect tests the connection before saving. Use --no-test to skip the probe, for example when credentials are rotated separately.

bash
horus connect --help

Elasticsearch logs

The Elasticsearch connector reads log indices and turns them into error-signature evidence. It groups similar log lines, counts occurrences, finds the first and last timestamps, and extracts trace and request IDs when available.

When to use it

  • Your services ship logs to Elasticsearch.
  • You want to know whether an error is new, worsening, or correlated with a deployment.
  • You need trace IDs to correlate log lines across services.

Setup

bash
horus connect elasticsearch --url https://es.example.com:9200 --username horus --password $ES_PASSWORD --index-pattern 'my-service-*' --service my-service-prod

Required: --url and --index-pattern. --service scopes log queries to a single service.

Field presets

Horus ships two built-in field mappings: meritt (default) and ecs. You can override individual fields under elasticsearch.fields in .horus/config.json (or horus.config.js) if your indices use custom field names.

How it appears in investigations

During an investigation, Elasticsearch evidence shows up as error signatures: message patterns, counts, time range, and trace/request IDs. It supports correlation by trace ID, not full distributed tracing.

Troubleshooting

SymptomFix
horus connect fails with 401Check username, password, and that the user has read access to the target indices.
Investigation returns no log evidenceVerify --service matches the value stored in your logs and that --index-pattern covers the right time range.
Wrong timestamp or level field usedOverride the field mapping under elasticsearch.fields in .horus/config.json (or horus.config.js) or use the ecs preset if your logs follow ECS.

Grafana metrics

The Grafana connector queries metrics through Grafana's datasource proxy. It discovers dashboards and panels matching an incident hint, then surfaces latency spikes, error-rate changes, throughput drops, and queue growth.

When to use it

  • Your team already uses Grafana dashboards.
  • You want metric evidence tied to the same services and time windows as your investigation.
  • You need hints like 'latency spike' or 'error rate' resolved to concrete panels.

Setup

bash
horus connect grafana --url https://grafana.example.com --username horus --password $GRAFANA_PASSWORD --dashboard abc123

Required: --url. --dashboard sets a default dashboard UID; Horus can also discover dashboards automatically during an investigation.

How it appears in investigations

Metric evidence includes panel titles, datasource queries, detected anomalies, and the time window covered. It is evidence, not a replacement for your Grafana UI.

Troubleshooting

SymptomFix
horus connect cannot reach GrafanaConfirm the URL and credentials. Check that the datasource proxy is accessible.
No panels match the hintBroaden the hint or set a relevant default dashboard with --dashboard.
Queries return empty seriesVerify the Prometheus/Loki/other datasource behind Grafana covers the service and time range.

MongoDB state

The MongoDB connector reads application and operational state from allowlisted collections. It is intentionally scoped: you specify which databases and collections Horus can query, and Horus only runs read-only, allowlisted operations.

When to use it

  • You store operational state in MongoDB that helps explain incidents: job statuses, user states, event records.
  • You want to detect stale documents, anomalous status distributions, or recent spikes in collection counts.

Setup

bash
horus connect mongodb --url mongodb://horus:password@mongodb.example.com:27017 --database my_app --collections users,orders,jobs

Required: --url and --database. --collections is optional: omit it to auto-discover and allow all collections in the database, or supply it to restrict the allowlist.

How it appears in investigations

MongoDB evidence shows collection counts, stale-document counts, and unusual status distributions. It is summarized; Horus does not dump full documents into the report.

Troubleshooting

SymptomFix
horus connect fails with authentication errorCheck the connection string, user, password, and authSource if you use one.
Investigation cannot see a collectionAdd the collection to --collections and re-run horus connect.
Counts look wrongVerify the MongoDB user has read permission on the allowlisted collections.

Redis / BullMQ queues

The Redis connector is used by the BullMQ provider to read queue runtime state. It reports queue depths, failed-job counts, delayed-job counts, and worker presence. It does not modify jobs, queues, or Redis keys.

When to use it

  • You run BullMQ on Redis and want queue evidence in investigations.
  • You suspect a backlog, worker crash, or job failure cascade.

Setup

bash
horus connect redis --url redis://:password@redis.example.com:6379

Required: --url. For authenticated Redis, embed the password in the URL as redis://:password@host:port. The CLI connect type is redis; the runtime provider is BullMQ.

How it appears in investigations

Queue evidence appears alongside source-intelligence queue stitching. You can see which queue is backing up, how many jobs failed, and whether workers are connected. Use horus queues --live for a standalone queue status view.

Troubleshooting

SymptomFix
horus connect cannot reach RedisCheck the URL, password, network, and TLS settings.
Queue evidence is missingConfirm the queue names match between code and Redis, and that horus init has built the queue map.
Counts differ from BullMQ DashboardHorus reads the same Redis keys but may sample or summarize differently. Treat its numbers as evidence, not canonical ops metrics.

PostgreSQL state

The PostgreSQL connector reads application and operational state from allowlisted tables. Like MongoDB, it is intentionally scoped: you specify the schema and tables Horus may query, and Horus runs only read-only, allowlisted operations.

When to use it

  • You store operational or domain state in PostgreSQL: job rows, order status, user state, outbox tables.
  • You want to detect stale rows, anomalous status distributions, or recent spikes in table counts.

Setup

bash
horus connect postgres --url postgres://horus:password@db.example.com:5432/my_app --schema public --tables orders,jobs,users

Required: --url. --schema defaults to public; --tables allowlists which tables Horus may read (omit to allow all in the schema). Run horus connect postgres with no flags for an interactive prompt.

How it appears in investigations

PostgreSQL evidence shows table counts, stale-row counts, and unusual status distributions, tagged as state. It is summarized; Horus does not dump full rows into the report.

Troubleshooting

SymptomFix
horus connect fails to connectCheck the connection string, credentials, SSL mode, and that the host is reachable.
Investigation cannot see a tableAdd it to --tables (and confirm the --schema), then re-run horus connect postgres.
Counts look wrongVerify the Postgres role has SELECT on the allowlisted tables.

Sentry errors

The Sentry connector reads grouped exceptions (issues) from your Sentry project and turns them into error evidence. Each issue is summarized with its count and time range, and seeded with the top in-app stack frame so Horus can point directly at the implicated code.

When to use it

  • You track exceptions in Sentry and want them correlated with code and other evidence during an investigation.
  • You want a direct jump from a production error to the function and file most likely responsible.

Setup

bash
horus connect sentry --org my-org --sentry-project my-project --auth-token $SENTRY_AUTH_TOKEN

Required: --org, --sentry-project, and --auth-token. For self-hosted Sentry, pass --url https://sentry.example.com. Use a read-only auth token. Running horus connect sentry with no flags prompts interactively.

How it appears in investigations

Sentry evidence is tagged logs (kind log) — the same source tier as Elasticsearch and Axiom — carrying the group's event count, first/last seen, and a code seed from the top in-app frame. It is evidence, not a replacement for the Sentry UI.

Troubleshooting

SymptomFix
horus connect returns 401 or 403Check the auth token scope (issues and events read) and that the org and project slugs are correct.
No issues appearConfirm the project slug and that the incident window overlaps recent Sentry activity.
Self-hosted Sentry not reachablePass --url with your Sentry base URL and verify network access.

Axiom logs

The Axiom connector reads structured logs from an Axiom dataset and turns them into log evidence. It is incident-aware: rather than dumping the freshest lines, it queries the top error signatures over the window — grouped by message and level, highest-volume first, with occurrence counts — alongside a few recent raw error rows for grounding. When no error-level rows match, it falls back to a recent all-levels sample so non-error datasets still produce evidence.

Requires CLI 0.11.0 or newer

The Axiom connector shipped in Horus CLI 0.11.0. Run horus --version and update if needed.

When to use it

  • You ship application logs to Axiom and want error counts and signatures correlated with code during an investigation.
  • You want a high-volume error storm surfaced as one ranked signature with its real count, not buried under newer info lines.
  • You query Axiom with APL today and want the same datasets folded into Horus evidence.

Setup

Run horus connect axiom with no flags for the interactive flow: it prompts for your API token (hidden input), lets you pick the region — US (api.axiom.co) or EU (api.eu.axiom.co), or a custom base URL — then lists your datasets live so you can select one (discover-then-select). If the dataset list cannot be fetched, you can type the name manually.

bash
# Interactive: token (hidden) -> region -> pick a dataset from the live list
horus connect axiom

# Non-interactive
horus connect axiom --token $AXIOM_TOKEN --dataset my-logs
horus connect axiom --token $AXIOM_TOKEN --dataset my-logs --url https://api.eu.axiom.co

Required: --token and --dataset. --url selects the region or a self-hosted base URL and defaults to the US region (https://api.axiom.co); only a non-default URL is persisted to .horus/config.json. Supply the token via an environment variable rather than committing it.

How it appears in investigations

Axiom evidence is tagged logs. Each row becomes one log evidence item with its fields on the payload, a redacted message in the title, and provenance (the dataset query plus a collection timestamp). High-volume error signatures carry their occurrence count and latest-seen time in the title, and relevance is weighted by hint-term match, recency, and log level.

Troubleshooting

SymptomFix
horus connect cannot list datasetsCheck the token, network, and region. You can also enter the dataset name manually, or pass --dataset directly.
No log evidence appearsConfirm the dataset name and that the incident window overlaps recent events. Verify the region with --url (EU is https://api.eu.axiom.co).
horus connect axiom is not recognizedUpdate the CLI — the Axiom connector requires version 0.11.0 or newer.

Shopify Admin state

The Shopify connector reads admin and business data — orders, inventory, fulfillment, customers, and more — from the Shopify Admin GraphQL API and folds each query result into an investigation as state evidence. It embeds no queries of its own: you supply the GraphQL document, either with --shopify-query at investigate time or as named default queries in .horus/config.json that horus watch runs each cycle. It is strictly read-only.

Requires CLI 0.19.0 or newer

The Shopify Admin connector shipped in Horus CLI 0.19.0. Run horus --version and update if needed.

When to use it

  • You run a Shopify store and want admin state — order, fulfillment, and inventory counts and statuses — correlated with code and other evidence.
  • You want horus watch to poll named Shopify queries each cycle and fold the results in as evidence.

Setup

Shopify supports two auth models: a static Admin API access token (a Custom App shpat_… token used directly, with no access id), or a client-credentials app (client_id + client_secret, exchanged for a short-lived token that Horus caches and refreshes on 401).

bash
# Static Admin API access token
horus connect shopify --store acme-store --secret $SHOPIFY_TOKEN

# Client-credentials app
horus connect shopify --store acme-store --access-id $SHOPIFY_CLIENT_ID --secret $SHOPIFY_CLIENT_SECRET

Required: --store and --secret. --store is the subdomain only (acme-store); Horus appends .myshopify.com automatically, and a full domain is also accepted. --access-id is the app client_id — omit it for a static token. --api-version defaults to 2025-10. The secret is encrypted at rest into .horus/secrets.local.json, never config.json. Running horus connect shopify with no flags prompts interactively and asks which auth model to use.

Supplying queries

At investigate time, pass your own read-only Admin GraphQL document: --shopify-query is repeatable and accepts @file, - (stdin), or a raw GraphQL string; --shopify-variables (@file or inline JSON object) applies to every query. $from and $to in the query are auto-bound to the investigation window.

bash
horus investigate "orders stuck unfulfilled" \
  --shopify-query @orders.graphql \
  --shopify-variables '{"status":"OPEN"}'

For horus watch, declare default queries under connectors.shopify.queries[] in .horus/config.json. Each entry has a name, a verbatim read-only query, optional variables, a kind (state | log | metric, default state), a relevance (0–1), and bindWindow to auto-bind the investigation window.

How it appears in investigations

Each query result becomes one evidence item, tagged state by default (a query may map to logs or metrics via its kind). The title reads Shopify <store> <query name>: N results · <time> (redacted), the GraphQL data rides on the payload, and provenance is shopify <store> <query name>. Relevance seeds at 0.6 (or the query's relevance), gains +0.2 on a hint-term match, and is clamped to 0.5–0.95. A configured Shopify connector with no queries contributes nothing — that is negative evidence, not a gap.

Troubleshooting

SymptomFix
Token exchange returns 401Client-credentials: check --access-id/--secret and that the app is installed with the read scopes it needs. Static token: confirm the shpat_… token is valid and unexpired.
No Shopify evidence appearsSupply at least one query — --shopify-query at investigate time, or connectors.shopify.queries[] for horus watch. With no query the connector returns nothing.
Requests are slow or rate-limitedThe client bounds every request to 8s and retries HTTP 429 and GraphQL THROTTLED responses with backoff; reduce query scope if throttling persists.

How connector evidence appears together

During horus investigate, Horus asks every configured connector for evidence related to the hint. Each piece is tagged by source: logs (Elasticsearch, Axiom, Sentry), metrics (Grafana), state (MongoDB, PostgreSQL, Shopify), queue (BullMQ), and history (git). The report surfaces only the evidence that is relevant and non-empty.

Connector evidence is combined with source-intelligence evidence and git evidence. The scoring engine ranks causes based on the full set; no single source overrides another.

Security and permissions

  • All connectors are read-only.
  • Use dedicated read-only users where possible.
  • Connector credentials are AES-256-GCM encrypted at rest into .horus/secrets.local.json (never config.json), unlocked by a master key held by your OS. horus connect auto-adds .horus/ to .gitignore; manage the store with horus secrets status|migrate|key.
  • MongoDB collections and PostgreSQL tables can be allowlisted with --collections/--tables; an empty allowlist auto-discovers all. It is a scoping option, not an enforced boundary.
  • The Redis connection URL (including any embedded password) is itself an encrypted secret at rest.
  • Shopify uses a client_secret or static Admin API token, encrypted at rest; env fallbacks are SHOPIFY_ACCESS_ID / SHOPIFY_SECRET.
  • Sentry uses a read-only auth token; supply it via an environment variable rather than committing it.
  • Axiom uses an API token; supply it via an environment variable rather than committing it.

What is not a runtime connector

These capabilities are handled differently and are not configured through horus connect:

  • Source intelligence — configured via horus init (use --source to point at an external host).
  • Git evidence — read from the local repository; no URL or credentials needed.
  • Distributed tracing — Horus can correlate by trace ID when present in logs, but it does not ingest trace spans directly today.

Next steps

See Getting started for the first-run workflow, Source intelligence for code context, and CLI reference for every horus connect option.