Micrometer: Feature: Undertow metrics

Created on 12 Feb 2019  路  7Comments  路  Source: micrometer-metrics/micrometer

I would very much like to measure Undertow using Micrometer, but I notice that there is no UndertowMetrics class like there is for Tomcat (TomcatMetrics) or Jetty (JettyStatisticsMetrics et.al).

Has anyone already built this somewhere else, or are there any ongoing efforts to build this?

I noticed that there are multiple issues mentioning Undertow metrics, but none that come to any conclusion.

Thank you for considering my request.

enhancement help wanted

Most helpful comment

Hi..

What you think about this kind of implementation? It's very simple and give us metrics about ThreadPoolWorkers and ioThreadCount of Undertow. It is generics for Servlet or Reactive application.

If you prefer I can make a pull request. What do you think?

public class UndertowMetrics implements MeterBinder {
    private static final String OBJECT_NAME = "org.xnio:type=Xnio,provider=\"nio\",worker=\"XNIO-1\"";
    private static final String GAUGE_NAME_WORKER_QUEUE_SIZE = "undertow.worker.queue.size";
    private static final String GAUGE_NAME_WORKER_POOL_SIZE = "undertow.worker.pool.size";
    private static final String GAUGE_NAME_MAX_WORKER_POOL_SIZE = "undertow.worker.pool.max";
    private static final String GAUGE_NAME_IO_THREAD_COUNT = "undertow.io.thread-count";
    private static final String ATTR_WORKER_QUEUE_SIZE = "WorkerQueueSize";
    private static final String ATTR_WORKER_POOL_SIZE = "CoreWorkerPoolSize";
    private static final String ATTR_MAX_WORKER_POOL_SIZE = "MaxWorkerPoolSize";
    private static final String ATTR_IO_THREAD_COUNT = "IoThreadCount";
    private final MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();

    @Override
    public void bindTo(@NonNull MeterRegistry registry) {
        buildAndRegisterGauge(GAUGE_NAME_WORKER_QUEUE_SIZE,
            ATTR_WORKER_QUEUE_SIZE,
            "Undertow worker queue size",
            registry);

        buildAndRegisterGauge(GAUGE_NAME_WORKER_POOL_SIZE,
            ATTR_WORKER_POOL_SIZE,
            "Undertow worker pool size",
            registry);

        buildAndRegisterGauge(GAUGE_NAME_MAX_WORKER_POOL_SIZE,
            ATTR_MAX_WORKER_POOL_SIZE,
            "Undertow max worker pool size",
            registry);

        buildAndRegisterGauge(GAUGE_NAME_IO_THREAD_COUNT,
            ATTR_IO_THREAD_COUNT,
            "Undertow IO thread count",
            registry);
    }

    private void buildAndRegisterGauge(@NonNull String name, @NonNull String attributeName, @NonNull String description, @NonNull MeterRegistry registry) {
        Gauge.builder(name,
                platformMBeanServer,
                mBeanServer -> getWorkerAttribute(mBeanServer, attributeName))
                .description(description)
                .register(registry);
    }

    private double getWorkerAttribute(@NonNull MBeanServer mBeanServer, @NonNull String attributeName) {
        Object attributeValueObj = null;
        try {
            attributeValueObj = mBeanServer.getAttribute(workerObjectName(), attributeName);
        } catch (Exception e) {
            log.warn("Unable to get {} from JMX", ATTR_WORKER_QUEUE_SIZE, e);
        }
        return Optional.ofNullable(attributeValueObj)
                .map(value -> (Number) value)
                .map(Number::doubleValue)
                .orElse(0d);
    }

    private ObjectName workerObjectName() throws MalformedObjectNameException {
        return new ObjectName(OBJECT_NAME);
    }
}

All 7 comments

Hey @shakuzen
Can please review my PR?

@dharmeshjogadia thank you for the pull request. I've optimistically marked this for inclusion in 1.3.0, but I can't guarantee we'll be able to get it reviewed and merged in time.

I use undertow without servlets, and https://github.com/micrometer-metrics/micrometer/pull/1575 only cover servlets part (which more specific), but not the undertow server itself, which based on handlers. Example of built-in metric handler: https://github.com/undertow-io/undertow/blob/master/core/src/main/java/io/undertow/server/handlers/MetricsHandler.java

Hi..

What you think about this kind of implementation? It's very simple and give us metrics about ThreadPoolWorkers and ioThreadCount of Undertow. It is generics for Servlet or Reactive application.

If you prefer I can make a pull request. What do you think?

public class UndertowMetrics implements MeterBinder {
    private static final String OBJECT_NAME = "org.xnio:type=Xnio,provider=\"nio\",worker=\"XNIO-1\"";
    private static final String GAUGE_NAME_WORKER_QUEUE_SIZE = "undertow.worker.queue.size";
    private static final String GAUGE_NAME_WORKER_POOL_SIZE = "undertow.worker.pool.size";
    private static final String GAUGE_NAME_MAX_WORKER_POOL_SIZE = "undertow.worker.pool.max";
    private static final String GAUGE_NAME_IO_THREAD_COUNT = "undertow.io.thread-count";
    private static final String ATTR_WORKER_QUEUE_SIZE = "WorkerQueueSize";
    private static final String ATTR_WORKER_POOL_SIZE = "CoreWorkerPoolSize";
    private static final String ATTR_MAX_WORKER_POOL_SIZE = "MaxWorkerPoolSize";
    private static final String ATTR_IO_THREAD_COUNT = "IoThreadCount";
    private final MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();

    @Override
    public void bindTo(@NonNull MeterRegistry registry) {
        buildAndRegisterGauge(GAUGE_NAME_WORKER_QUEUE_SIZE,
            ATTR_WORKER_QUEUE_SIZE,
            "Undertow worker queue size",
            registry);

        buildAndRegisterGauge(GAUGE_NAME_WORKER_POOL_SIZE,
            ATTR_WORKER_POOL_SIZE,
            "Undertow worker pool size",
            registry);

        buildAndRegisterGauge(GAUGE_NAME_MAX_WORKER_POOL_SIZE,
            ATTR_MAX_WORKER_POOL_SIZE,
            "Undertow max worker pool size",
            registry);

        buildAndRegisterGauge(GAUGE_NAME_IO_THREAD_COUNT,
            ATTR_IO_THREAD_COUNT,
            "Undertow IO thread count",
            registry);
    }

    private void buildAndRegisterGauge(@NonNull String name, @NonNull String attributeName, @NonNull String description, @NonNull MeterRegistry registry) {
        Gauge.builder(name,
                platformMBeanServer,
                mBeanServer -> getWorkerAttribute(mBeanServer, attributeName))
                .description(description)
                .register(registry);
    }

    private double getWorkerAttribute(@NonNull MBeanServer mBeanServer, @NonNull String attributeName) {
        Object attributeValueObj = null;
        try {
            attributeValueObj = mBeanServer.getAttribute(workerObjectName(), attributeName);
        } catch (Exception e) {
            log.warn("Unable to get {} from JMX", ATTR_WORKER_QUEUE_SIZE, e);
        }
        return Optional.ofNullable(attributeValueObj)
                .map(value -> (Number) value)
                .map(Number::doubleValue)
                .orElse(0d);
    }

    private ObjectName workerObjectName() throws MalformedObjectNameException {
        return new ObjectName(OBJECT_NAME);
    }
}

@ignacio83 is there a reason to use org.xnio:type=Xnio,provider="nio",worker="XNIO-1" over jboss.threads:name="XNIO-1",type=thread-pool ? Genuine question, as they both seem to contain similar information

Hi @austinarbor

Are you using Wildly as application server? Undertow is servlet container of Wildly.
I believe that鈥檚 why you鈥檙e seeing the two metrics who the same value.

In my case I am using only Undertow.

I am using it from within spring boot as an embedded server, AFAIK wildfly is not being used but I could be wrong

Was this page helpful?
0 / 5 - 0 ratings