Query logging
Elasticsearch allows to log every querying operation performed on the cluster. This supports endpoints like _search, _msearch, ES|QL, SQL, EQL and other APIs that search or query Elasticsearch indices.
The following query types are supported:
dsl: Logs every search operation performed on using the Query DSL.esql: Logs every query operation performed on the cluster using ES|QL.eql: Logs every query operation performed on the cluster using EQL.sql: Logs every query operation performed on the cluster using SQL.
By default, the logging is turned off. To enable the logging, set the elasticsearch.activitylog.enabled property to true in the elasticsearch.yml configuration file or using the settings API:
elasticsearch.activitylog.enabled: true
By default, search (dsl) queries that query only system indices are not logged. To enable logging of such queries, use the elasticsearch.activitylog.search.include.system_indices setting described below.
The following configuration options are available:
elasticsearch.activitylog.enabled: Enables or disables query logging. The default isfalse(disabled).elasticsearch.activitylog.threshold: Sets the request duration threshold for logging events. If the threshold is set to the value greater than 0, only the requests that take as much time (in milliseconds) or longer than the threshold are logged. The default is 0 (no threshold).elasticsearch.activitylog.include.user: Enables or disables the user information logging. The default istrue(enabled by default).elasticsearch.activitylog.search.include.system_indices: Enables or disables logging of queries performed on system indices for the dsl search module. The default is not logging system indices.
The logs are output in JSON format, and include the following fields:
@timestamp: The timestamp of the log entry.event.outcome: Whether the request was successful (success) or not (failure).event.duration: How long (in nanoseconds) the request took to complete.error.typeanderror.message: Error information fields if the request failed.user.*: User information fields if enabled.http.request.headers.x_opaque_id: The X-Opaque-Id header value if enabled. See X-Opaque-Id HTTP header for details and best practices.trace.id: Trace ID information.
elasticsearch.querylog.type: The type of operation (dsl,esql,sql,eql).elasticsearch.querylog.took: How long (in nanoseconds) the request took to complete.elasticsearch.querylog.took_millis: How long (in milliseconds) the request took to complete.elasticsearch.querylog.timed_out: Boolean specifying whether the query timed out.elasticsearch.querylog.query: The query text (depending on the query language, could be string or JSON).elasticsearch.querylog.indices: Array containing the indices that were requested. These may not be fully resolved. May contain wildcards and index expressions, and it is not guaranteed these resolve to any specific index or exist at all. Note that for some queries (like ES|QL) indices are part of the query text and may not be available as a separate field.elasticsearch.querylog.result_count: The number of results actually returned in the response.elasticsearch.querylog.is_system: If system index logging is enabled, indicates whether the request was performed only on system indices.elasticsearch.querylog.has_aggregations: For adslsearch result, this boolean flag specifies whether the result has a non-empty aggregations section.elasticsearch.querylog.shards.successful,elasticsearch.querylog.shards.skipped,elasticsearch.querylog.shards.failed: How many shards were successful, skipped and failed during the query execution.elasticsearch.querylog.is_ccs- Indicates whether the request was a cross-cluster search.elasticsearch.querylog.remote_count- For cross-cluster queries, this field indicates the number of remote clusters involved in the query execution.elasticsearch.querylog.is_remote- Fordslqueries, indicates whether the query was initiated by a remote cluster.
Additional fields specific to Elasticsearch environment may be added.
In addition to the fields listed above, each query language may include fields specific to it, prefixed with elasticsearch.querylog.
search.total_count: The “total hits” value, as reported by the search response.search.total_count_partial: Set totruein case the total count does not reflect the full number of matches for some reason (liketrack_total_hitslimitation).
esql.profile.*.took: ES|QL query profiling metrics, in nanoseconds
{
"@timestamp": "2026-03-04T19:40:34.736Z",
"log.level": "INFO",
"auth.type": "REALM",
"elasticsearch.querylog.indices": [
"query_log_test_index"
],
"elasticsearch.querylog.query": "{\"size\":10,\"query\":{\"match_all\":{\"boost\":1.0}}}",
"elasticsearch.querylog.result_count": 3,
"elasticsearch.querylog.search.total_count": 3,
"elasticsearch.querylog.shards.successful": 1,
"elasticsearch.querylog.took": 1985208,
"elasticsearch.querylog.took_millis": 1,
"elasticsearch.querylog.type": "dsl",
"elasticsearch.task.id": 29848,
"event.duration": 1985208,
"event.outcome": "success",
"http.request.headers.x_opaque_id": "opaque-1773275310",
"trace.id": "0af7651916cd43dd8448eb211c80319c",
"user.name": "elastic",
"user.realm": "reserved",
"ecs.version": "1.2.0",
"service.name": "ES_ECS",
"event.dataset": "elasticsearch.querylog",
"process.thread.name": "elasticsearch[node-1][search][T#14]",
"log.logger": "elasticsearch.querylog",
"elasticsearch.cluster.uuid": "gjYgb-uQQAuLmDoKlQInZw",
"elasticsearch.node.id": "juurGSfgRYGwTP2ttZbtOQ",
"elasticsearch.node.name": "node-1",
"elasticsearch.cluster.name": "querying"
}
Example failure entry:
{
"@timestamp": "2026-03-04T19:40:35.271Z",
"log.level": "INFO",
"auth.type": "REALM",
"elasticsearch.querylog.indices": [
"nonexistent_index_xyz"
],
"elasticsearch.querylog.query": "any where true",
"elasticsearch.querylog.result_count": 0,
"elasticsearch.querylog.took": 1326334,
"elasticsearch.querylog.took_millis": 1,
"elasticsearch.querylog.type": "eql",
"error.message": "no such index [Unknown index [nonexistent_index_xyz]]",
"error.type": "org.elasticsearch.index.IndexNotFoundException",
"event.duration": 1326334,
"event.outcome": "failure",
"http.request.headers.x_opaque_id": "opaque-1772653234",
"user.name": "elastic",
"user.realm": "reserved",
"ecs.version": "1.2.0",
"service.name": "ES_ECS",
"event.dataset": "elasticsearch.querylog",
"process.thread.name": "elasticsearch[node-1][search_coordination][T#6]",
"log.logger": "elasticsearch.querylog",
"elasticsearch.cluster.uuid": "gjYgb-uQQAuLmDoKlQInZw",
"elasticsearch.node.id": "juurGSfgRYGwTP2ttZbtOQ",
"elasticsearch.node.name": "node-1",
"elasticsearch.cluster.name": "querying"
}
The logs are always emitted on the node that executed the request. These logs can be viewed in the following locations:
- If Elasticsearch monitoring is enabled, from Stack Monitoring. The query logs have the
log.loggerfield set toelasticsearch.querylog. - From the local Elasticsearch service logs directory. Query log files have a suffix of
_querylog.json, e.g.mycluster_querylog.json.
While query logging is designed to have as little impact on the performance of your cluster as possible, it will necessarily consume resources needed to create and store the logs. Thus, it is advised to enable query logging only when necessary for troubleshooting or monitoring purposes, and to disable it after the investigation is complete. It is also recommended to set the threshold to avoid logging very quick queries that are of little consequence for cluster performance.
Query logging uses an asynchronous logging mechanism that does not block query execution. As a result, if there are too many incoming queries and the logging system can not store all the logs fast enough, some log entries may be lost. If that is a problem, consider increasing the thresholds to only log the most impactful queries.
To learn about other ways to optimize your search requests, refer to tune for search speed.