Skip to content

Commit fa4bc4d

Browse files
authored
Merge pull request #48511 from brunobat/document-netty-metrics
Netty Micrometer metrics doc
2 parents ac78cdc + 3811759 commit fa4bc4d

File tree

1 file changed

+151
-32
lines changed

1 file changed

+151
-32
lines changed

docs/src/main/asciidoc/telemetry-micrometer.adoc

Lines changed: 151 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,8 @@ Precomputed percentile values can not. Percentiles are unique to each dataset (t
489489

490490
== Automatically generated metrics
491491

492+
=== HTTP server
493+
492494
The Micrometer extension automatically times HTTP server requests. Following Prometheus naming conventions for
493495
timers, look for `http_server_requests_seconds_count`, `http_server_requests_seconds_sum`, and
494496
`http_server_requests_seconds_max`. Dimensional labels have been added for the requested uri, the HTTP method
@@ -523,6 +525,155 @@ For example, setting
523525
By default, the metrics are exported using the Prometheus format `application/openmetrics-text`,
524526
you can revert to the former format by specifying the `Accept` request header to `text/plain` (`curl -H "Accept: text/plain" localhost:8080/q/metrics/`).
525527

528+
=== Netty memory management metrics
529+
530+
https://netty.io/[Netty] memory management metrics are important because Quarkus is built on top of https://vertx.io/[Eclipse Vert.x], which is a framework built on top of Netty to create reactive applications in Java. Even if you use imperative style programing in Quarkus, under the surface it is conveniently handled by Vert.x in a reactive way.
531+
532+
In short, Netty provides an _efficient_ memory management system for asynchronous applications.
533+
It offers different types of memory allocation strategies, including **heap** (stored in the JVM heap) and direct memory (allocated outside the JVM memory), along with a **buffer pooling mechanism** to optimize allocations and reduce garbage collection (GC) overhead.
534+
535+
==== Memory Categories in Netty
536+
Netty uses two primary memory categories:
537+
538+
1. **Heap Memory**
539+
- Allocated from the JVM heap (`byte[]`).
540+
- Managed by the garbage collector.
541+
- Slower for I/O operations because it requires copying data to/from direct memory before sending over a socket.
542+
543+
2. **Direct Memory**
544+
- Allocated outside the JVM heap using `ByteBuffer.allocateDirect()`.
545+
- Not managed by the garbage collector, reducing GC pressure.
546+
- Faster for I/O operations as it avoids unnecessary copying.
547+
548+
[NOTE]
549+
====
550+
Using a very high value for -XX:MaxRAMPercentage (allocating most of the available RAM to the Java heap) is not recommended for Quarkus applications, as it’s important to leave room for Netty's native memory allocations.
551+
552+
These Netty metrics help evaluate how much room is needed.
553+
====
554+
555+
==== Pooling Mechanism
556+
Netty uses **PooledByteBufAllocator** to reduce memory allocation overhead and fragmentation. It is based on a **jemalloc-style arena system** (see https://github.com/jemalloc/jemalloc[jemalloc/jemalloc]), which includes:
557+
558+
- **Arenas**: Large memory blocks that manage allocations.
559+
- **Chunks**: Memory segments within arenas (typically 16MB in size).
560+
- **Pages**: Fixed-size portions of a chunk (usually 8KB).
561+
- **Subpages**: Smaller allocations within a page for tiny objects.
562+
- **Thread-local Caches**: Per-thread cache for frequently used small buffers, reducing contention.
563+
564+
==== Metrics for Netty Memory Management
565+
The Micrometer metrics report key metrics from Netty's allocator, helping monitor memory usage, pinned memory, pooling efficiency, and cache behavior.
566+
567+
===== **1. Memory Usage Metrics (Every allocator)**
568+
These metrics track the current memory usage by Netty allocators (in bytes)
569+
570+
|===
571+
| Metric Name | Description | Type | Tags
572+
573+
|`allocator.memory.used`
574+
|Amount of memory currently used by the allocator
575+
|Gauge
576+
|`memory_type=[heap, direct]`, `name=allocator-name`
577+
578+
|===
579+
580+
===== **2. Pooled Allocator - Pinned Memory Metrics**
581+
Pinned memory refers to buffers that cannot be recycled due to active references, preventing reuse by the allocator. A _high_ number may indicate some kind of leak (as reference are not released).
582+
583+
|===
584+
| Metric Name | Description | Type | Tags
585+
586+
| `allocator.memory.pinned`
587+
|Amount of pinned memory that cannot be reused
588+
|Gauge
589+
|`memory_type=[heap, direct]`, `name=allocator-name`
590+
591+
|===
592+
593+
===== **3. Pooled Allocator - Arena Metrics**
594+
Arenas (large size of memory) manage memory allocations efficiently by grouping chunks of memory. So this metric is the number of arenas allocated for a given allocator.
595+
596+
|===
597+
| Metric Name | Description | Type | Tags
598+
599+
| `allocator.pooled.arenas`
600+
|Number of arenas handling memory allocation
601+
|Gauge
602+
| `memory_type=[heap, direct]`
603+
604+
|===
605+
606+
===== **4. Cache Size Metrics**
607+
Netty caches small buffers within a given thread to avoid frequent memory allocations and improve performance. If the same thread needs memory, it will first check in its own cache. This is particularly efficient due to the event loop threading model (low number of threads). Note that the tiny caches are now merged into the small ones.
608+
609+
|===
610+
| Metric Name | Description | Type | Tags
611+
612+
| `allocator.pooled.cache.size`
613+
|Size of the buffer cache
614+
|Gauge
615+
| `cache_type=[small, normal]`
616+
617+
|===
618+
619+
===== **5. Thread-Local Cache Metrics**
620+
These metrics indicate the number of active thread-local caches used for memory pooling. It complements the cache size metrics (cache being the size, and this being the number of cache)
621+
622+
|===
623+
| Metric Name | Description | Type | Tags
624+
625+
| `allocator.pooled.threadlocal.caches`
626+
|Number of thread-local caches for buffers
627+
|Gauge
628+
| None
629+
630+
|===
631+
632+
===== **6. Chunk Size Metrics**
633+
Chunks are the primary unit of memory allocation in Netty's arenas.
634+
635+
|===
636+
| Metric Name | Description | Type | Tags
637+
638+
| `allocator.pooled.chunk.size`
639+
|Size of a memory chunk in pooled allocator
640+
|Gauge
641+
| None
642+
643+
|===
644+
645+
[[quarkus-extensions-using-micrometer]]
646+
=== List of Quarkus core extensions automatically instrumented with Micrometer
647+
648+
* https://quarkus.io/extensions/io.quarkus/quarkus-agroal[`quarkus-agroal`]
649+
* https://quarkus.io/guides/cache[`quarkus-cache`]
650+
* https://quarkus.io/extensions/io.quarkus/quarkus-caffeine[`quarkus-caffeine`]
651+
* https://quarkus.io/guides/smallrye-fault-tolerance[`quarkus-smallrye-fault-tolerance`]
652+
* https://quarkus.io/guides/grpc-getting-started[`quarkus-grpc`]
653+
* https://quarkus.io/guides/hibernate-orm[`quarkus-hibernate-orm`]
654+
* https://quarkus.io/extensions/io.quarkus/quarkus-jaxrs-client-reactive[`quarkus-jaxrs-client-reactive`]
655+
* https://quarkus.io/guides/deploying-to-kubernetes[`quarkus-kubernetes`]
656+
* https://quarkus.io/guides/logging[`jboss-logging`] (logging API in Quarkus)
657+
* https://quarkus.io/guides/mongodb[`quarkus-mongodb-client`]
658+
* https://quarkus.io/extensions/io.quarkus/quarkus-netty[`quarkus-netty`]
659+
* https://quarkus.io/guides/redis[`quarkus-redis-client`]
660+
* https://quarkus.io/guides/rest[`quarkus-rest`]
661+
* https://quarkus.io/guides/resteasy[`quarkus-resteasy-jackson`]
662+
* https://quarkus.io/guides/resteasy-client[`quarkus-resteasy-client`]
663+
* https://quarkus.io/guides/scheduler[`quarkus-scheduler`]
664+
* https://quarkus.io/guides/smallrye-graphql[`quarkus-smallrye-graphql`]
665+
* https://quarkus.io/extensions/io.quarkus/quarkus-messaging[`quarkus-messaging`]
666+
** AMQP 1.0
667+
** RabbitMQ
668+
** Kafka
669+
** Pulsar
670+
** JMS
671+
** MQTT
672+
** Camel Messaging
673+
* https://quarkus.io/guides/stork-reference[`quarkus-smallrye-stork`]
674+
* https://quarkus.io/guides/vertx[`quarkus-vertx`] (http requests)
675+
* xref:websockets-next-reference.adoc[`websockets-next`]
676+
526677
== Customizing Micrometer
527678

528679
Quarkus provides a variety of way to customize Micrometer.
@@ -741,38 +892,6 @@ The Prometheus metrics will be available from `http://0.0.0.0:9000/q/metrics/pro
741892

742893
Refer to the xref:./management-interface-reference.adoc[management interface reference] for more information.
743894

744-
[[quarkus-extensions-using-micrometer]]
745-
== Quarkus core extensions instrumented with Micrometer
746-
747-
* https://quarkus.io/extensions/io.quarkus/quarkus-agroal[`quarkus-agroal`]
748-
* https://quarkus.io/guides/cache[`quarkus-cache`]
749-
* https://quarkus.io/extensions/io.quarkus/quarkus-caffeine[`quarkus-caffeine`]
750-
* https://quarkus.io/guides/smallrye-fault-tolerance[`quarkus-smallrye-fault-tolerance`]
751-
* https://quarkus.io/guides/grpc-getting-started[`quarkus-grpc`]
752-
* https://quarkus.io/guides/hibernate-orm[`quarkus-hibernate-orm`]
753-
* https://quarkus.io/extensions/io.quarkus/quarkus-jaxrs-client-reactive[`quarkus-jaxrs-client-reactive`]
754-
* https://quarkus.io/guides/deploying-to-kubernetes[`quarkus-kubernetes`]
755-
* https://quarkus.io/guides/logging[`jboss-logging`] (logging API in Quarkus)
756-
* https://quarkus.io/guides/mongodb[`quarkus-mongodb-client`]
757-
* https://quarkus.io/extensions/io.quarkus/quarkus-netty[`quarkus-netty`]
758-
* https://quarkus.io/guides/redis[`quarkus-redis-client`]
759-
* https://quarkus.io/guides/rest[`quarkus-rest`]
760-
* https://quarkus.io/guides/resteasy[`quarkus-resteasy-jackson`]
761-
* https://quarkus.io/guides/resteasy-client[`quarkus-resteasy-client`]
762-
* https://quarkus.io/guides/scheduler[`quarkus-scheduler`]
763-
* https://quarkus.io/guides/smallrye-graphql[`quarkus-smallrye-graphql`]
764-
* https://quarkus.io/extensions/io.quarkus/quarkus-messaging[`quarkus-messaging`]
765-
** AMQP 1.0
766-
** RabbitMQ
767-
** Kafka
768-
** Pulsar
769-
** JMS
770-
** MQTT
771-
** Camel Messaging
772-
* https://quarkus.io/guides/stork-reference[`quarkus-smallrye-stork`]
773-
* https://quarkus.io/guides/vertx[`quarkus-vertx`] (http requests)
774-
* xref:websockets-next-reference.adoc[`websockets-next`]
775-
776895
== Configuration Reference
777896

778897
include::{generated-dir}/config/quarkus-micrometer.adoc[opts=optional, leveloffset=+1]

0 commit comments

Comments
 (0)