/{index}/_search with size:0 and reads a named aggregation’s numeric
value as the metric. OpenSearch uses the same search API, so this source
covers both; the flavor setting only changes labels.
Observer is not a log store. The source extracts one number from an
aggregation; it never reads or keeps documents. Same shape as the SQL
and Loki sources: the query returns a number, that number is the metric.
When to use it
Anything you have indexed in Elasticsearch / OpenSearch and want as a status signal: error counts from log events, average or p95 request latency, unique active users, business event rates.Query structure
Provide the full search body with aquery (optional) and an aggs
block. Name the aggregation; the source reads its value.
error_count; the source reads
aggregations.error_count.value. The agent always sends size:0, so
documents are never returned.
Supported aggregations
Single-value metric aggregations are read from.value:
percentiles is read from .values. Set the Percentile field to the
key you want (for example 95.0):
value_count over no matches
returns 0; avg/min/max over no matches return null, which the
probe reports as es_no_data.
Configuration shape
Field reference
Authentication
Auth secrets stay on the agent. You store the NAME of an environment variable on the agent host; the agent reads the value at query time, so the credential never reaches the cloud and never appears in logs. For Elastic Cloud, the usual choice is an API key. Create one in Kibana (Stack Management, API keys); Elastic gives you a base64id:api_key value. Export it on the agent and reference it:
Authorization: ApiKey <value>. Bearer and basic
auth work the same way through token_ref and username +
password_ref.
OpenSearch
OpenSearch is a fork of Elasticsearch with a compatible search API. Set the flavor to OpenSearch for clarity; the request is identical. Known differences (security plugin endpoints, version fields) don’t affect the_search + aggregations path this source uses. Basic auth and bearer
tokens both work; OpenSearch doesn’t use the Elastic API-key format, so
prefer basic auth there.
Testing the query
Observer cannot reach a private Elasticsearch from the cloud, so there is no live “run query” button. Validate the query in Kibana Dev Tools (or OpenSearch Dashboards) against the same cluster, confirm the aggregation returns a single number, then paste the body in. The first value arrives on the next agent tick.Reason codes
es_agg_not_found: the aggregation name isn’t in the response. The available names are in the metadata; check the name matches a key underaggs.es_agg_unsupported: the named aggregation didn’t yield a single number. Use a metric aggregation (and set the percentile forpercentiles).es_no_data: the aggregation value was null (often an empty match set onavg/min/max).es_index_not_found: 404 for the index pattern. Check it exists.es_unreachable: couldn’t connect (refused, DNS, network).es_timeout: the search didn’t finish in time.es_unauthorized: 401/403. Check auth + the credential env var.es_auth_ref_missing: the token / password / API-key env var isn’t set on the agent.es_query_error: 400/422. The Query DSL is invalid; the parser error is in the metadata. Test it in Dev Tools.es_server_error: 5xx from the cluster. Usually transient.es_error: any other failure, such as an unexpected HTTP status or a network error not listed above.
Troubleshooting
es_agg_not_foundwith the right query. Theagg_namemust match the key underaggsexactly. For nested aggregations, name the top-level one whose.valueyou want.es_no_dataonavg. No documents matched.avgover an empty set is null; if you want 0, usevalue_countor widen the time range.es_unauthorizedon Elastic Cloud. Confirm the API key is the base64id:api_key, not the raw key, and that the env var is set on the agent.

