It will be nice to see metrics added around Netty. For example,
I recently added the following netty-micrometer glue code to a spring boot project to monitor memory usage by the default PooledByteBufAllocator.
Although not in your list, this may be useful to some...
lots of code hidden...
package x.y.z;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.Tags;
import io.netty.buffer.*;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@Configuration
public class NettyMetricsConfig {
private static final String NETTY = "netty";
private static final String ALLOC = "alloc";
private static final String POOLED = "pooled";
private static final String UNPOOLED = "unpooled";
private static final String MEMORY = "memory";
private static final String DIRECT = "direct";
private static final String HEAP = "heap";
private static final String ARENA = "arena";
private static final String CHUNK = "chunk";
private static final String THREAD = "thread";
private static final String LOCAL = "local";
private static final String CACHE = "cache";
private static final String SIZE = "size";
private static final String TINY = "tiny";
private static final String SMALL = "small";
private static final String NORMAL = "normal";
private static final String HUGE = "huge";
private static final String SUBPAGE = "subpage";
private static final String CHUNKLIST = "chunklist";
private static final String NUMBER = "number";
private static final String USED = "used";
private static final String COUNT = "count";
private static final String ALLOCATION = "allocation";
private static final String DEALLOCATION = "deallocation";
private static final String ACTIVE = "active";
private static final String BYTE = "byte";
private static final String ELEMENT = "element";
private static final String MAX = "max";
private static final String MIN = "min";
private static final String AVAILABLE = "available";
private static final String PAGE = "page";
private static final String USAGE = "usage";
@PostConstruct
public void configureNettyMetrics() {
PooledByteBufAllocatorMetric pooledMetric = PooledByteBufAllocator.DEFAULT.metric();
Tags pooled = Tags.of(ALLOC, POOLED);
Metrics.gauge(dot(NETTY, ALLOC, MEMORY, USED), pooled.and(MEMORY, DIRECT), pooledMetric, ByteBufAllocatorMetric::usedDirectMemory);
Metrics.gauge(dot(NETTY, ALLOC, MEMORY, USED), pooled.and(MEMORY, HEAP), pooledMetric, ByteBufAllocatorMetric::usedHeapMemory);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, COUNT), pooled.and(MEMORY, DIRECT), pooledMetric, PooledByteBufAllocatorMetric::numDirectArenas);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, COUNT), pooled.and(MEMORY, HEAP), pooledMetric, PooledByteBufAllocatorMetric::numHeapArenas);
Metrics.gauge(dot(NETTY, ALLOC, THREAD, LOCAL, CACHE, COUNT), pooled, pooledMetric, PooledByteBufAllocatorMetric::numThreadLocalCaches);
Metrics.gauge(dot(NETTY, ALLOC, CACHE, SIZE), pooled.and(CACHE, TINY), pooledMetric, PooledByteBufAllocatorMetric::tinyCacheSize);
Metrics.gauge(dot(NETTY, ALLOC, CACHE, SIZE), pooled.and(CACHE, SMALL), pooledMetric, PooledByteBufAllocatorMetric::smallCacheSize);
Metrics.gauge(dot(NETTY, ALLOC, CACHE, SIZE), pooled.and(CACHE, NORMAL), pooledMetric, PooledByteBufAllocatorMetric::normalCacheSize);
Metrics.gauge(dot(NETTY, ALLOC, CHUNK, SIZE), pooled, pooledMetric, PooledByteBufAllocatorMetric::chunkSize);
for (int i = 0; i < pooledMetric.directArenas().size(); i++) {
Tags tags = Tags.of(MEMORY, DIRECT)
.and(dot(ARENA, NUMBER), Integer.toString(i));
meterPoolArena(tags, pooledMetric.directArenas().get(i));
}
for (int i = 0; i < pooledMetric.heapArenas().size(); i++) {
Tags tags = Tags.of(MEMORY, HEAP)
.and(dot(ARENA, NUMBER), Integer.toString(i));
meterPoolArena(tags, pooledMetric.heapArenas().get(i));
}
ByteBufAllocatorMetric unpooledMetric = UnpooledByteBufAllocator.DEFAULT.metric();
Tags unpooled = Tags.of(ALLOC, UNPOOLED);
Metrics.gauge(dot(NETTY, ALLOC, MEMORY, USED), unpooled.and(MEMORY, DIRECT), unpooledMetric, ByteBufAllocatorMetric::usedDirectMemory);
Metrics.gauge(dot(NETTY, ALLOC, MEMORY, USED), unpooled.and(MEMORY, HEAP), unpooledMetric, ByteBufAllocatorMetric::usedHeapMemory);
}
private void meterPoolArena(Tags tags, PoolArenaMetric pam) {
Metrics.gauge(dot(NETTY, ALLOC, ARENA, THREAD, CACHE, COUNT), tags, pam, PoolArenaMetric::numThreadCaches);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, SUBPAGE, COUNT), tags.and(SUBPAGE, TINY), pam, PoolArenaMetric::numTinySubpages);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, SUBPAGE, COUNT), tags.and(SUBPAGE, SMALL), pam, PoolArenaMetric::numSmallSubpages);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, CHUNKLIST, COUNT), tags, pam, PoolArenaMetric::numChunkLists);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, ALLOCATION, COUNT), tags, pam, PoolArenaMetric::numAllocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, ALLOCATION, COUNT), tags.and(SIZE, TINY), pam, PoolArenaMetric::numTinyAllocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, ALLOCATION, COUNT), tags.and(SIZE, SMALL), pam, PoolArenaMetric::numSmallAllocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, ALLOCATION, COUNT), tags.and(SIZE, NORMAL), pam, PoolArenaMetric::numNormalAllocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, ALLOCATION, COUNT), tags.and(SIZE, HUGE), pam, PoolArenaMetric::numHugeAllocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, DEALLOCATION, COUNT), tags, pam, PoolArenaMetric::numDeallocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, DEALLOCATION, COUNT), tags.and(SIZE, TINY), pam, PoolArenaMetric::numTinyDeallocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, DEALLOCATION, COUNT), tags.and(SIZE, SMALL), pam, PoolArenaMetric::numSmallDeallocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, DEALLOCATION, COUNT), tags.and(SIZE, NORMAL), pam, PoolArenaMetric::numNormalDeallocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, DEALLOCATION, COUNT), tags.and(SIZE, HUGE), pam, PoolArenaMetric::numHugeDeallocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, ALLOCATION, ACTIVE, COUNT), tags, pam, PoolArenaMetric::numActiveAllocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, ALLOCATION, ACTIVE, COUNT), tags.and(SIZE, TINY), pam, PoolArenaMetric::numActiveTinyAllocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, ALLOCATION, ACTIVE, COUNT), tags.and(SIZE, SMALL), pam, PoolArenaMetric::numActiveSmallAllocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, ALLOCATION, ACTIVE, COUNT), tags.and(SIZE, NORMAL), pam, PoolArenaMetric::numActiveNormalAllocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, ALLOCATION, ACTIVE, COUNT), tags.and(SIZE, HUGE), pam, PoolArenaMetric::numActiveHugeAllocations);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, ACTIVE, BYTE, COUNT), tags, pam, PoolArenaMetric::numActiveHugeAllocations);
for (int i = 0; i < pam.tinySubpages().size(); i++) {
Tags tinySubpage = tags.and(SUBPAGE, TINY)
.and(dot(SUBPAGE, NUMBER), Integer.toString(i));
meterSubpage(tinySubpage, pam.tinySubpages().get(i));
}
for (int i = 0; i < pam.smallSubpages().size(); i++) {
Tags tinySubpage = tags.and(SUBPAGE, SMALL)
.and(dot(SUBPAGE, NUMBER), Integer.toString(i));
meterSubpage(tinySubpage, pam.smallSubpages().get(i));
}
for (int i = 0; i < pam.chunkLists().size(); i++) {
Tags chunkList = tags.and(dot(CHUNKLIST, NUMBER), Integer.toString(i));
meterChunkList(chunkList, pam.chunkLists().get(i));
}
}
private void meterSubpage(Tags tags, PoolSubpageMetric psm) {
Metrics.gauge(dot(NETTY, ALLOC, ARENA, SUBPAGE, ELEMENT, MAX), tags, psm, PoolSubpageMetric::maxNumElements);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, SUBPAGE, AVAILABLE, COUNT), tags, psm, PoolSubpageMetric::numAvailable);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, SUBPAGE, ELEMENT, SIZE), tags, psm, PoolSubpageMetric::elementSize);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, SUBPAGE, PAGE, SIZE), tags, psm, PoolSubpageMetric::pageSize);
}
private void meterChunkList(Tags tags, PoolChunkListMetric pclm) {
Metrics.gauge(dot(NETTY, ALLOC, ARENA, CHUNKLIST, USAGE, MIN), tags, pclm, PoolChunkListMetric::minUsage);
Metrics.gauge(dot(NETTY, ALLOC, ARENA, CHUNKLIST, USAGE, MAX), tags, pclm, PoolChunkListMetric::maxUsage);
}
private String dot(String... strings) {
return String.join(".", strings);
}
}
Hi, I've just implemented for https://github.com/apache/activemq-artemis/ a Netty pooled allocator MeterBinder: right now I'm pushing it in a PR for artemis but I would be more then happy to send a PR here as well...anyone interested? :)
Most helpful comment
Hi, I've just implemented for https://github.com/apache/activemq-artemis/ a Netty pooled allocator
MeterBinder: right now I'm pushing it in a PR for artemis but I would be more then happy to send a PR here as well...anyone interested? :)