Elasticsearch
What it gives you — the same query_logs, logs_error_summary and discover_log_fields tools,
speaking Lucene query_string over the classic _search DSL instead of LogsQL/LogQL, auto-detected
at startup. See OpenSearch for the same client against an
OpenSearch cluster — the two speak an identical _search/_field_caps wire format.
Minimal config
logs:
url: https://elasticsearch.observability.svc:9200
provider: elasticsearch # optional — auto-detected when omitted
index: logs-* # index patternAuthenticated:
logs:
url: https://elasticsearch.observability.svc:9200
provider: elasticsearch
index: logs-*
token_env: ES_TOKEN # bearer token, by env-var indirection
# headers: { Authorization: "ApiKey <base64 id:key>" } # ES API key instead of a bearer tokenA headers.Authorization entry is applied AFTER token_env, so it wins — use it for an
Elasticsearch API key
(Authorization: ApiKey <base64>) rather than a bearer token.
Verify it locally
curl -sk -X POST "https://elasticsearch.observability.svc:9200/logs-*/_search" \
-H 'Content-Type: application/json' -d '{"size":1,"query":{"match_all":{}}}'Then fire a test incident and confirm the logs tools appear among what the model called:
kubectl -n runlore logs deploy/runlore | grep -E 'tool=query_logs|tool=logs_error_summary|tool=discover_log_fields'Notes
- Presence enables it —
logs.urlset is all it takes;provider: elasticsearchis optional (the startup probe hitsGET /, which both Elasticsearch and VictoriaLogs answer, but only Elasticsearch/OpenSearch return aversion.numberin the response body — VictoriaLogs’ root page is HTML). Pin it explicitly when the backend is unreachable at startup or sits behind a proxy that confuses the probe — an unreachable/ambiguous probe fails safe to VictoriaLogs, not to Elasticsearch. - TLS verification is always on — there is no
insecure_skip_verifyescape hatch. Pointlogs.urlat a certificate the runtime trusts (a cluster CA bundle, or a properly-issued cert behind an ingress) rather than disabling verification. - The ECS (Elastic Common Schema) field convention is assumed by default:
container_field: kubernetes.container.name,namespace_field: kubernetes.namespace,pod_field: kubernetes.pod.name,level_field: log.level,timestamp_field: @timestamp,message_field: message. Override any of them underlogs.fieldsif your index template labels differently.unpack_pipeis ignored — Elasticsearch has no parser-pipe concept (documents are already structured).
Parity notes — read before relying on Elasticsearch for these three tools:
logs_error_summary’s top messages fall back to client-side aggregation when the message field istext-only — and by default, it is. ECS shipsmessageas a plaintextfield with nokeywordsub-field, so Elasticsearch/OpenSearch reject atermsaggregation on it (illegal_argument_exception: Fielddata is disabled on text fields). RunLore tries the server-side aggregation first (cheap and corpus-wide when it succeeds) and, on exactly that rejection, falls back to aggregating over the capped, newest-firstquery_logssample instead — counts and first→last spans are then per-sample, not corpus-wide, the same caveat Loki’s client-side fallback carries. If your index template adds an aggregatable multi-field (commonlymessage.keyword), pointlogs.fields.message_fieldat it to get the corpus-wide, server-side path instead. RunLore learns the rejection once per process and goes straight to the fallback afterwards, so the default configuration does not repeat a request the cluster will always refuse. (OpenSearch’s wording for the same rejection differs slightly — RunLore matches the part both distributions emit, verified against real clusters of each.)- Partial results are flagged, never silently reported as complete. Elasticsearch answers a
search some shards could not serve with HTTP 200 and
_shards.failed > 0— typically when a rollinglogs-*pattern spans a mapping change, so atermsaggregation succeeds on the newer indices and is rejected on the older ones.query_logsappends an explicit “partial results” line,logs_error_summary’s top messages switch to the client-side path (which is unaffected), and its histogram reports the partiality as an error rather than showing a chart that understates the spike. discover_log_fieldslists the INDEX’S MAPPED fields, not fields present only in matching documents. It uses_field_caps, a mapping-introspection endpoint with no query/window scope — broader than VictoriaLogs’/Loki’s discovery (which is scoped to what a query actually matched), and it reports no per-field hit count (every result shows no×Nfrequency), unlike VictoriaLogs'field_names.- The error-volume histogram (
date_histogram+ atermssub-aggregation onlevel_field) IS corpus-wide and server-side —log.levelships as akeyword-typed field under ECS, so it aggregates without themessagefield’s restriction.
Reference
- Configuration → Other top-level keys
for the full
logskey reference. - Data sources — the provider table across every signal.
- VictoriaLogs — the fail-safe default this auto-detect falls back to.
- OpenSearch — the same client, same DSL, same parity notes.