Elasticsearch / OpenSearch logs monitoring with Topologix

Monitoring & Observability

Application logs stored in Elasticsearch 7.x / 8.x or OpenSearch 1.x / 2.x: per-service error counts with error types, the log error baselines and new-type warnings of the Graylog All Services source, or a windowed count of a Lucene query. The field names are configurable — the ECS names (service.name, log.level, …) are the defaults. (This is not the HTTP / JSON integration's Elasticsearch pack, which reads a cluster's own health.)

Requirements

  • HTTP(S) reach to the cluster's REST port (default 9200) from the Topologix server or — for an on-prem cluster — from a proxy agent 1.265.0 or later. A proxy-polled source on an older proxy is refused at save ("needs proxy 1.265.0 or later").
  • Elasticsearch 7.x / 8.x (self-managed or Elastic Cloud) or OpenSearch 1.x / 2.x. OpenSearch Serverless is not supported.
  • Authentication: an Elasticsearch API key (the encoded value — base64 of id:api_key — sent as Authorization: ApiKey …), Basic (username + password), a Bearer token (an OpenSearch JWT, an Elasticsearch service-account token) or None for a cluster with security disabled. OpenSearch has no API keys: use Basic or Bearer.
  • Privileges: read and view_index_metadata on the log index patterns. The cluster monitor privilege is optional — with it the Test shows the cluster health. Example role: {"indices":[{"names":["logs-*","filebeat-*"],"privileges":["read","view_index_metadata"]}],"cluster":["monitor"]}.
  • Self-signed HTTPS is accepted by unticking Verify TLS certificate.

1 · Set up the integration

  1. Open the Integrations pageClick Integrations in the toolbar and pick Elasticsearch / OpenSearch logs from the catalogue (Monitoring & Observability).
  2. Enter the URL and the credentialsE.g. https://es.example.local:9200; choose API key, Basic, Bearer token or None. Every credential field is masked and sealed at rest.
  3. Index patternsComma-separated; empty = logs-*,filebeat-*,logstash-*. Every source of the integration reads these unless it names its own.
  4. Field mapping (optional)Empty = ECS: timestamp @timestamp, service service.name, level log.level, message message, host host.name, type error.type, traceId trace.id. On a saved integration Load fields from the cluster reads _field_caps over the patterns and offers the names (aggregatable first); Use suggested fills the empty inputs. A field you group by (service, error type, host) must be a keyword field — for a text field pick its .keyword sub-field. Enter - for an optional field (host, error type, trace id) the logs do not have. Examples: Logstash service → service.keyword, Kubernetes kubernetes.labels.app, Serilog fields.Application + level level.
  5. Create, then TestClick Create, reopen the integration and click Test: GET / (flavour + version), _cat/health and _field_caps over the patterns — “Connected — Elasticsearch 8.13.4 (green) · 12 indices match logs-*,filebeat-*,logstash-*” or “OpenSearch 2.11.1 (yellow) · …”, with four rows: Connection, Cluster health, Indices, Field mapping. No matching index, a missing field or a text field turns it amber with the reason (the .keyword advice for a text field).
Target on a private network? Route it through a proxy agent. Proxy agents run inside your network — behind NAT, on a management VLAN, in an air-gapped segment — and reach targets the Topologix server can't. The agent polls the server every 15 seconds for its assignments, runs the checks locally, and pushes results back every 5 seconds, so no inbound firewall rules are ever needed. Set a default proxy on the integration; every metric source can override it. If a proxy goes offline, its sources are marked stale within ~90 seconds and the last known values stay visible.

2 · Add it to a flow

  1. Select the service nodeClick the node, open Metrics, then + Add and choose the Elasticsearch integration.
  2. Pick the modeErrors per service (the log-baseline source) or Count a query.
  3. Narrow it (optional)A Lucene query (Elasticsearch query-string syntax, ≤ 500 characters; a bare word searches the message field) and the index patterns. Advanced: the error-line query that replaces the level rule, the sample lines per service (default 10, 1–50) and a field-mapping override.
  4. Alarm and saveErrors per service: the log-error baseline rule (baseline or a count threshold, N of M, new error types) and the optional RECAP correlation. Count: the threshold field. Click Add Source; the source stores the resolved index patterns and field mapping.

3 · The two modes

Errors per service

Error lines per service over each check, with the log error baselines of the Graylog All Services source — usual count per weekday and hour, breach rule, new-type warnings, the banner (Elasticsearch Errors), the Alerts page and the Catalogue Logs section. The window is the polling interval (30 s to 24 h).

  • The level rule: ONE lenient query_string — the level field holds one of emerg emergency alert crit critical fatal err error severe (lower, UPPER or Capitalised) or a syslog number ≤ 3. Lenient matters: a list of words against a numeric level field would make Elasticsearch answer 400 for the whole search. Advanced → Error lines are replaces the rule with your own Lucene.
  • Two searches per check: (1) a size:0 search over the window — terms on the service field (Max services, default 200; lines without the field count as (unknown)), terms on the error-type field (10 per service) and the newest sample lines per service; (2) a cardinality of the service field over the last hour for Services reporting (if it fails, the counts stand and a caveat says so).
  • Error types are the error-type field's values (exact); lines without it are typed by fingerprints of the sampled lines (marked approx), with the same noise guard as Graylog. Services past Max services are one (other) row with a caveat. A service seen in the last 24 hours with no errors reads a measured 0.
  • Both the 8.x nested and the 7.x flattened field names are read; numeric levels 0–7 and OpenTelemetry severity numbers 9–24 are understood. Sample lines are redacted (on the proxy, before they leave the network) and kept for View logs.

Count a query

The number of log lines matching a Lucene query over each check — one search, the exact total. Errors only adds the level rule. Alarm on it with the threshold field (the source health rule reads value).

No value is not zero

Every failure reads no value with the reason, never 0: a 401 / 403 (“needs the read and view_index_metadata privileges”), index patterns that match no index (“No index matches logs-* — check the index patterns”), every shard failing, an unreachable cluster. A partial shard failure keeps the count and names it in a caveat.

  • A text service / error-type / host field cannot be grouped: the source reads no value with “service.name is a text field: pick its .keyword sub-field (service.name.keyword) in the field mapping” — the Test row says the same before you add a source.

Catalogue and AI

The integration's services (the service field's values of the last 24 hours) appear in the Catalogue; an Errors-per-service source adds them to its Logs section. The runtime host of a service is probed from host.ip / the host field / kubernetes.pod.name / kubernetes.node.name. The AI log auto-scan and the per-source Analyze with AI stay Graylog-only.

Searching

Beyond the counts, the same integration is searched live — every search is ONE absolute window (gte / lt in epoch milliseconds) over the source's index patterns and field mapping (else the integration's), a service / host / trace id is an exact filter (the field or its .keyword, then only the exact value is kept), a text-field error is retried once on the .keyword sub-field, and every line is redacted (on the proxy, then with the organisation's rules). Through a proxy the searches need 1.265.1 or later — an older proxy is told “update the proxy” and asked nothing.

  • View logs (the card, the banner rows, the Catalogue Logs section): the lines cached by the last checks first, else one search of the service's error lines over the window (≤ 7 days, ≤ 200 lines) — with Ack, groups and errors-only as for Graylog.
  • The monitoring bot (search_logs, source elasticsearch): a service, host or trace id over the asked window (≤ 24 h, 100 lines, the coverage names the indices, the query and the total); text alone is a fleet search — the exact matching-line count per host (the busiest 20, and how many lines are on other hosts) plus the newest 20 lines, over up to 7 days.
  • Forensics → Advanced → Elasticsearch (Lucene): your Lucene over the page's window (≤ 31 days and the Admin range), newest first with a histogram, ≤ 1000 lines (Admin → Forensics → Elasticsearch lines), on the integration's wired index patterns unless Elasticsearch: any index is on. KQL is Kibana's own language and is not accepted. The Logs section reads the service's lines the same way.
  • Change reports: the warn-or-worse lines of each changed service (≤ 1 day, ≤ 100 a service) beside Graylog's, within the same 25 reads a pass; the report names “Elasticsearch · <integration>”.
  • Zipkin / OTLP traces: pick the integration under Augment with logs (Graylog or Elasticsearch) — the trace viewer's “Show logs” reads the lines carrying the trace id (the mapped trace field, trace.id by default) over the last hour, ≤ 100 lines. Set up monitoring can link it too, so each node's “Search logs & traces” lists the service's lines.

Good to know

  • Every read is an ABSOLUTE window (gte / lt in epoch milliseconds from the poller's clock), so a proxy and the server count the same window.
  • Index patterns accept letters, digits and _ . * , : + - (a remote cluster cluster:logs-* works); a missing index is not an error by itself — the shards guard tells "no index matches" apart from a quiet window.
  • Keep one mapping per pattern set: when the patterns match indices that map the SAME field differently (a keyword host.name in one, a text one in another), the indices with the text mapping fail their shards — counts and fleet host counts then cover only the shards that answered, and the answer says so (“cover only the shards that answered … narrow the index patterns”). Give such indices their own source / patterns, or map the field as keyword everywhere.

All integrations →

See it on your own infrastructure

Book a demo and we will walk you through Topologix with your systems in mind: on our cloud, or self-hosted in your own network.