Statistics API (Port 2609)
Contents
The Statistics API exposes real-time metrics and monitoring data about the XP instance. It is commonly used for health checks, performance monitoring, and capacity planning.
| The Statistics API is intended for internal monitoring and is exposed without authentication on port 2609. Do not expose it publicly. |
Overview
Enonic XP exposes a set of named reporters on port 2609. The list of registered reporters is available at:
GET http://<host>:2609/
<host> equals localhost on the machine running the XP instance. |
Sample response:
[
"cluster.elasticsearch",
"cluster.manager",
"dump.deadlocks",
"dump.threads",
"http.filter",
"http.serverdump",
"http.servlet",
"http.threadpool",
"http.webHandler",
"index",
"jvm.gc",
"jvm.info",
"jvm.memory",
"jvm.os",
"jvm.threads",
"mediaTypes",
"metrics",
"osgi.bundle",
"osgi.component",
"osgi.service",
"server"
]
Each reporter is fetched at:
GET http://<host>:2609/<name>
The set of registered reporters depends on the deployment. The list above is from a single-node SDK; clustered installations also expose cluster.hazelcast. |
In addition to reporters, two top-level probe endpoints expose health and readiness signals - see Health and readiness.
Reporters
cluster.elasticsearch
Information about the Elasticsearch cluster - local node and members.
GET http://<host>:2609/cluster.elasticsearch
{
"name": "mycluster",
"localNode": {
"isMaster": true,
"id": "16RUH2cUS_6lCGoY27JblQ",
"hostName": "local",
"version": "2.4.6",
"numberOfNodesSeen": 1
},
"members": [
{
"isMaster": true,
"id": "16RUH2cUS_6lCGoY27JblQ",
"hostName": "local",
"version": "2.4.6",
"address": "local[1]",
"name": "8c30363f-9ba3-4af9-85d9-99c8d6827899",
"isDataNode": true,
"isClientNode": false
}
],
"state": "YELLOW"
}
For convenience, the local node is surfaced as a separate localNode entry alongside the full members list.
The state property is the most important:
-
Green: cluster is operational and all configured replicas are distributed.
-
Yellow: cluster is operational, but some replicas are not distributed to a node.
-
Red: cluster is not operational.
For shard-level distribution, see the index reporter.
cluster.manager
Aggregate health of all clusters. XP 8 currently registers a single cluster, elasticsearch.
GET http://<host>:2609/cluster.manager
{
"state": "OK",
"clusters": [
{
"id": "elasticsearch",
"healthy": true,
"numberOfNodesSeen": 1
}
]
}
cluster.hazelcast
Information about the Hazelcast cluster - state, version, and members.
| This reporter is only registered when Hazelcast clustering is active. It is not available on single-node SDK or standalone deployments. |
GET http://<host>:2609/cluster.hazelcast
{
"clusterState": "ACTIVE",
"clusterTime": 1778137547054,
"clusterVersion": "5.3",
"members": [
{
"uuid": "d7b9b75e-aacf-444b-bff9-af5c786843c2",
"address": "192.168.1.1",
"port": 5701,
"liteMember": false,
"version": "5.3.7"
},
{
"uuid": "899920a2-d9bd-4add-8b1a-133bf27af9a0",
"address": "192.168.1.2",
"port": 5701,
"liteMember": false,
"version": "5.3.7"
}
]
}
dump.deadlocks
Detects thread deadlocks. Returns plain text - the literal string No deadlocks detected! when none are found, otherwise a stack-trace dump per locked thread.
GET http://<host>:2609/dump.deadlocks
dump.threads
Plain-text snapshot of every JVM thread and its current stack.
GET http://<host>:2609/dump.threads
"Reference Handler" daemon prio=10 Id=11 RUNNABLE
at java.base@25.0.3/java.lang.ref.Reference.waitForReferencePendingList(Native Method)
at java.base@25.0.3/java.lang.ref.Reference.processPendingReferences(Reference.java:246)
at java.base@25.0.3/java.lang.ref.Reference$ReferenceHandler.run(Reference.java:208)
"Finalizer" daemon prio=8 Id=12 WAITING on java.lang.ref.ReferenceQueue$Lock
at java.base@25.0.3/java.lang.Object.wait0(Native Method)
...
http.filter
Servlet filters registered with the HTTP layer. Each entry shows class, order, URL patterns, and the connectors it applies to.
GET http://<host>:2609/http.filter
[
{
"order": -500,
"name": "HeaderFilterWrapper",
"class": "com.enonic.xp.web.impl.header.HeaderFilterWrapper",
"patterns": ["/*"],
"connectors": ["xp", "api", "status"],
"initParams": {}
},
{
"order": -400,
"name": "DosFilterWrapper",
"class": "com.enonic.xp.web.impl.dos.DosFilterWrapper",
"patterns": ["/*"],
"connectors": ["xp", "api"],
"initParams": {}
}
]
http.serverdump
Jetty’s internal server dump - thread pools, connectors, handler chain, and acceptor state. Plain text, intended for low-level debugging.
GET http://<host>:2609/http.serverdump
oejs.Server@417b362b{STARTED}[12.1.8,sto=0] ~ BLOCKING - STARTED
+= oejut.QueuedThreadPool[qtp646782988]@268d200c{STARTED,8<=18<=200,i=1,r=-1,t=-8608ms,q=0} - STARTED
| +- oejut.ThreadPoolBudget
| += oejut.ReservedThreadExecutor{capacity=8,threads=oejut.ThreadIdPool{capacity=8}} - STARTED
| ...
http.servlet
HTTP servlets registered. Same shape as http.filter.
GET http://<host>:2609/http.servlet
[
{
"order": 0,
"name": "JaxRsServlet",
"class": "com.enonic.xp.jaxrs.impl.JaxRsServlet",
"patterns": ["/admin/rest-v2/apps/*"],
"connectors": ["xp"],
"initParams": {}
},
{
"order": 100,
"name": "WebDispatcherServlet",
"class": "com.enonic.xp.web.impl.handler.WebDispatcherServlet",
"patterns": ["/*"],
"connectors": ["xp"],
"initParams": {}
}
]
http.threadpool
Status of Jetty’s HTTP thread pool.
GET http://<host>:2609/http.threadpool
{
"threads": 18,
"idleThreads": 1,
"isLowOnThreads": false
}
http.webHandler
The chain of WebHandler instances that requests are dispatched through, ordered by priority.
GET http://<host>:2609/http.webHandler
[
{ "order": -100, "class": "com.enonic.xp.web.impl.trace.TraceWebFilter" },
{ "order": -51, "class": "com.enonic.app.contentstudio.site.AdminSiteHandler" },
{ "order": -50, "class": "com.enonic.xp.admin.impl.portal.AdminToolPortalHandler" },
{ "order": -50, "class": "com.enonic.xp.portal.impl.handler.portal.SiteHandler" },
...
]
index
Elasticsearch index status: total/started/unassigned shards, plus per-shard placement.
GET http://<host>:2609/index
{
"summary": {
"total": 16,
"started": 8,
"unassigned": 8,
"relocating": 0,
"initializing": 0
},
"shards": {
"started": [
{
"id": "storage-system-repo(0)",
"nodeId": "16RUH2cUS_6lCGoY27JblQ",
"nodeAddress": "0.0.0.0",
"type": "PRIMARY"
},
{
"id": "search-system-repo(0)",
"nodeId": "16RUH2cUS_6lCGoY27JblQ",
"nodeAddress": "0.0.0.0",
"type": "PRIMARY"
}
],
"unassigned": [],
"relocating": [],
"initializing": []
}
}
A shard is either PRIMARY or REPLICA (a copy of the primary). The summary buckets:
-
total: total shards across repositories and replicas.
-
started: shards currently assigned to a node.
-
unassigned: shards waiting to be distributed - typically a multi-replica setup with one or more nodes down.
-
relocating: shards moving from one node to another.
-
initializing: shards being recovered from disk during startup.
jvm.gc
Cumulative JVM garbage-collection stats.
GET http://<host>:2609/jvm.gc
{
"collectionTime": 2111,
"collectionCount": 383
}
jvm.info
JVM identity and uptime.
GET http://<host>:2609/jvm.info
{
"name": "Java HotSpot(TM) 64-Bit Server VM",
"vendor": "Oracle Corporation",
"version": "25.0.3+9-LTS-jvmci-b01",
"startTime": 1778137547054,
"upTime": 45129597
}
jvm.memory
Heap, non-heap, and per-pool memory usage.
GET http://<host>:2609/jvm.memory
{
"heap": {
"init": 402653184,
"max": 6442450944,
"committed": 268435456,
"used": 231056848
},
"nonHeap": {
"init": 7667712,
"max": -1,
"committed": 255983616,
"used": 232611296
},
"pools": [
{
"name": "G1 Eden Space",
"type": "Heap memory",
"usage": { "init": 50331648, "max": -1, "committed": 125829120, "used": 109051904 }
},
{
"name": "Metaspace",
"type": "Non-heap memory",
"usage": { "init": 0, "max": -1, "committed": 182190080, "used": 176992680 }
}
]
}
jvm.os
Operating system the JVM is running on.
GET http://<host>:2609/jvm.os
{
"name": "Mac OS X",
"version": "26.2",
"arch": "aarch64",
"cores": 8,
"loadAverage": 2.366
}
jvm.threads
JVM thread counts.
GET http://<host>:2609/jvm.threads
{
"count": 100,
"peak": 118,
"daemonCount": 72,
"totalStarted": 572,
"numDeadLocks": 0
}
mediaTypes
File-extension to media-type mappings used by the runtime.
GET http://<host>:2609/mediaTypes
{
"css": "text/css",
"html": "text/html",
"js": "application/javascript",
"json": "application/json",
"jpg": "image/jpeg",
"png": "image/png",
"svg": "image/svg+xml",
"pdf": "application/pdf"
}
metrics
Prometheus / OpenMetrics-formatted metrics for the instance. Point Prometheus, Grafana Agent, or any compatible scraper at this endpoint.
GET http://<host>:2609/metrics
# TYPE com_enonic_xp_event_EventPublisher_event counter
com_enonic_xp_event_EventPublisher_event_total 367.0
# TYPE jetty_connections_bytes_in_bytes summary
# HELP jetty_connections_bytes_in_bytes Bytes received by tracked connections
jetty_connections_bytes_in_bytes_count{connector_name="xp"} 0
jetty_connections_bytes_in_bytes_sum{connector_name="xp"} 0.0
jetty_connections_bytes_in_bytes_count{connector_name="api"} 0
jetty_connections_bytes_in_bytes_sum{connector_name="api"} 0.0
...
osgi.bundle
All OSGi bundles installed in the runtime.
GET http://<host>:2609/osgi.bundle
{
"count": 120,
"bundles": [
{ "id": 0, "name": "org.apache.felix.framework", "state": "ACTIVE" },
{ "id": 1, "name": "jakarta.activation-api", "state": "ACTIVE" },
{ "id": 9, "name": "org.apache.felix.scr", "state": "ACTIVE" }
]
}
osgi.component
SCR (Declarative Services) components and their instance state.
GET http://<host>:2609/osgi.component
{
"count": 336,
"components": [
{
"name": "com.enonic.xp.server.internal.metrics.MetricsReporter",
"enabled": true,
"bundle": 21,
"instances": [{ "id": 1, "state": "ACTIVE" }]
},
{
"name": "com.enonic.xp.server.impl.status.DeadlockReporter",
"enabled": true,
"bundle": 70,
"instances": [{ "id": 4, "state": "ACTIVE" }]
}
]
}
osgi.service
All OSGi services currently registered.
GET http://<host>:2609/osgi.service
{
"count": 375,
"services": [
{
"id": "320",
"iface": "com.enonic.xp.web.handler.WebHandler",
"bundle": "com.enonic.xp.portal.impl"
},
{
"id": "92",
"iface": "com.enonic.xp.blob.BlobStore",
"bundle": "com.enonic.xp.core"
}
]
}
server
Build and version of the running XP instance.
GET http://<host>:2609/server
{
"version": "8.0.0-B4",
"installation": "Sandbox7",
"runMode": "DEV",
"build": {
"hash": "a0f053aa204fb51cc70a388bc99efd446e37059b",
"shortHash": "a0f053a",
"branch": "a0f053aa204fb51cc70a388bc99efd446e37059b",
"timestamp": "2026-04-30T15:26:12Z"
}
}
Health and readiness
In addition to reporters, two probe endpoints expose simple health signals on the same port - useful for load balancers, Kubernetes liveness/readiness probes, and similar.
health
Validates that essential data services are available.
GET http://<host>:2609/health
Returns 200 OK with an empty {} body when healthy. On failure, returns 503 with a list of errors:
{
"errors": [
"org.elasticsearch.client.Client service is not available"
]
}
ready
Validates that all services required for full operation are available.
GET http://<host>:2609/ready
Returns 200 OK with an empty {} body when ready. On failure, returns 503 with a list of errors:
{
"errors": [
"com.enonic.xp.portal.websocket.WebSocketManager service is not available",
"com.enonic.xp.mail.MailService service is not available"
]
}