-
Notifications
You must be signed in to change notification settings - Fork 984
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit adds two new `MeterBinder` implementations for instrumenting Netty 4.x: `NettyAllocatorMetrics` and `NettyEventExecutorMetrics`. `NettyAllocatorMetrics` will instrument any `ByteBufAllocatorMetricProvider` and gather information about heap/direct memory allocated; additional metrics are provided for pooled allocators. `NettyEventExecutorMetrics` will instrument `Iterable<EventExecutor>` (typically, `EventLoop` or `EventLoopGroup` instances) and count the number of pending tasks for all. Metrics and tags are described in the `NettyMeters` class. Closes gh-522
- Loading branch information
Showing
7 changed files
with
737 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
...core/src/main/java/io/micrometer/core/instrument/binder/netty4/NettyAllocatorMetrics.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/* | ||
* Copyright 2023 VMware, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.micrometer.core.instrument.binder.netty4; | ||
|
||
import io.micrometer.core.instrument.Gauge; | ||
import io.micrometer.core.instrument.MeterRegistry; | ||
import io.micrometer.core.instrument.Tags; | ||
import io.micrometer.core.instrument.binder.MeterBinder; | ||
import io.netty.buffer.ByteBufAllocatorMetric; | ||
import io.netty.buffer.ByteBufAllocatorMetricProvider; | ||
import io.netty.buffer.PooledByteBufAllocator; | ||
import io.netty.buffer.PooledByteBufAllocatorMetric; | ||
|
||
/** | ||
* {@link MeterBinder} for Netty memory allocators. | ||
* | ||
* @author Brian Clozel | ||
* @since 1.11.0 | ||
* @see NettyMeters | ||
*/ | ||
public class NettyAllocatorMetrics implements MeterBinder { | ||
|
||
private final ByteBufAllocatorMetricProvider allocator; | ||
|
||
/** | ||
* Create a binder instance for the given allocator. | ||
* @param allocator the {@code ByteBuf} allocator to instrument | ||
*/ | ||
public NettyAllocatorMetrics(ByteBufAllocatorMetricProvider allocator) { | ||
this.allocator = allocator; | ||
} | ||
|
||
@Override | ||
public void bindTo(MeterRegistry registry) { | ||
int allocatorId = this.allocator.hashCode(); | ||
|
||
ByteBufAllocatorMetric allocatorMetric = this.allocator.metric(); | ||
Tags tags = Tags.of(NettyMeters.AllocatorMeterTags.ID.asString(), String.valueOf(allocatorId), | ||
NettyMeters.AllocatorMeterTags.ALLOCATOR_TYPE.asString(), this.allocator.getClass().getSimpleName()); | ||
|
||
Gauge | ||
.builder(NettyMeters.ALLOCATOR_MEMORY_USED.getName(), allocatorMetric, | ||
ByteBufAllocatorMetric::usedHeapMemory) | ||
.tags(tags.and(NettyMeters.AllocatorMemoryMeterTags.MEMORY_TYPE.asString(), "heap")) | ||
.register(registry); | ||
|
||
Gauge | ||
.builder(NettyMeters.ALLOCATOR_MEMORY_USED.getName(), allocatorMetric, | ||
ByteBufAllocatorMetric::usedDirectMemory) | ||
.tags(tags.and(NettyMeters.AllocatorMemoryMeterTags.MEMORY_TYPE.asString(), "direct")) | ||
.register(registry); | ||
|
||
if (this.allocator instanceof PooledByteBufAllocator) { | ||
PooledByteBufAllocator pooledByteBufAllocator = (PooledByteBufAllocator) this.allocator; | ||
PooledByteBufAllocatorMetric pooledAllocatorMetric = pooledByteBufAllocator.metric(); | ||
|
||
Gauge | ||
.builder(NettyMeters.ALLOCATOR_MEMORY_PINNED.getName(), pooledByteBufAllocator, | ||
PooledByteBufAllocator::pinnedHeapMemory) | ||
.tags(tags.and(NettyMeters.AllocatorMemoryMeterTags.MEMORY_TYPE.asString(), "heap")) | ||
.register(registry); | ||
|
||
Gauge | ||
.builder(NettyMeters.ALLOCATOR_MEMORY_PINNED.getName(), pooledByteBufAllocator, | ||
PooledByteBufAllocator::pinnedDirectMemory) | ||
.tags(tags.and(NettyMeters.AllocatorMemoryMeterTags.MEMORY_TYPE.asString(), "direct")) | ||
.register(registry); | ||
|
||
Gauge | ||
.builder(NettyMeters.ALLOCATOR_POOLED_ARENAS.getName(), pooledAllocatorMetric, | ||
PooledByteBufAllocatorMetric::numHeapArenas) | ||
.tags(tags.and(NettyMeters.AllocatorMemoryMeterTags.MEMORY_TYPE.asString(), "heap")) | ||
.register(registry); | ||
Gauge | ||
.builder(NettyMeters.ALLOCATOR_POOLED_ARENAS.getName(), pooledAllocatorMetric, | ||
PooledByteBufAllocatorMetric::numDirectArenas) | ||
.tags(tags.and(NettyMeters.AllocatorMemoryMeterTags.MEMORY_TYPE.asString(), "direct")) | ||
.register(registry); | ||
|
||
Gauge | ||
.builder(NettyMeters.ALLOCATOR_POOLED_CACHE_SIZE.getName(), pooledAllocatorMetric, | ||
PooledByteBufAllocatorMetric::normalCacheSize) | ||
.tags(tags.and(NettyMeters.AllocatorPooledCacheMeterTags.CACHE_TYPE.asString(), "normal")) | ||
.register(registry); | ||
Gauge | ||
.builder(NettyMeters.ALLOCATOR_POOLED_CACHE_SIZE.getName(), pooledAllocatorMetric, | ||
PooledByteBufAllocatorMetric::smallCacheSize) | ||
.tags(tags.and(NettyMeters.AllocatorPooledCacheMeterTags.CACHE_TYPE.asString(), "small")) | ||
.register(registry); | ||
|
||
Gauge | ||
.builder(NettyMeters.ALLOCATOR_POOLED_THREADLOCAL_CACHES.getName(), pooledAllocatorMetric, | ||
PooledByteBufAllocatorMetric::numThreadLocalCaches) | ||
.tags(tags) | ||
.register(registry); | ||
|
||
Gauge | ||
.builder(NettyMeters.ALLOCATOR_POOLED_CHUNK_SIZE.getName(), pooledAllocatorMetric, | ||
PooledByteBufAllocatorMetric::chunkSize) | ||
.tags(tags) | ||
.register(registry); | ||
} | ||
} | ||
|
||
} |
78 changes: 78 additions & 0 deletions
78
.../src/main/java/io/micrometer/core/instrument/binder/netty4/NettyEventExecutorMetrics.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* Copyright 2023 VMware, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.micrometer.core.instrument.binder.netty4; | ||
|
||
import io.micrometer.core.instrument.Gauge; | ||
import io.micrometer.core.instrument.MeterRegistry; | ||
import io.micrometer.core.instrument.binder.MeterBinder; | ||
import io.netty.channel.EventLoop; | ||
import io.netty.util.concurrent.EventExecutor; | ||
import io.netty.util.concurrent.SingleThreadEventExecutor; | ||
|
||
/** | ||
* {@link MeterBinder} for Netty event executors. | ||
* | ||
* @author Brian Clozel | ||
* @since 1.11.0 | ||
* @see NettyMeters | ||
*/ | ||
public class NettyEventExecutorMetrics implements MeterBinder { | ||
|
||
private final Iterable<EventExecutor> eventExecutors; | ||
|
||
/** | ||
* Create a binder instance for the given event executors. | ||
* <p> | ||
* An {@link io.netty.channel.EventLoopGroup} (all its executors) can be instrumented | ||
* at startup like: <pre> | ||
* MeterRegistry registry = //... | ||
* EventLoopGroup group = //... | ||
* new NettyEventExecutorMetrics(group).bindTo(registry); | ||
* </pre> Alternatively, an {@link EventLoop} can be instrumented at runtime during | ||
* channel initialization. In this case, developers should ensure that this instance | ||
* has not been registered already as re-binding metrics at runtime is inefficient | ||
* here. <pre> | ||
* @Override | ||
* public void initChannel(SocketChannel channel) throws Exception { | ||
* // this concurrent check must be implemented by micrometer users | ||
* if (!isEventLoopInstrumented(channel.eventLoop())) { | ||
* new EventExecutorMetrics(channel.eventLoop()).bindTo(registry); | ||
* } | ||
* //... | ||
* } | ||
* </pre> | ||
* @param eventExecutors the event executors to instrument | ||
*/ | ||
public NettyEventExecutorMetrics(Iterable<EventExecutor> eventExecutors) { | ||
this.eventExecutors = eventExecutors; | ||
} | ||
|
||
@Override | ||
public void bindTo(MeterRegistry registry) { | ||
this.eventExecutors.forEach(eventExecutor -> { | ||
if (eventExecutor instanceof SingleThreadEventExecutor) { | ||
SingleThreadEventExecutor singleThreadEventExecutor = (SingleThreadEventExecutor) eventExecutor; | ||
Gauge | ||
.builder(NettyMeters.EVENT_EXECUTOR_TASKS_PENDING.getName(), | ||
singleThreadEventExecutor::pendingTasks) | ||
.tag(NettyMeters.EventLoopTasksPendingMeterTags.NAME.asString(), | ||
singleThreadEventExecutor.threadProperties().name()) | ||
.register(registry); | ||
} | ||
}); | ||
} | ||
|
||
} |
Oops, something went wrong.