All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.arpnetworking.metrics.jvm.JvmMetricsRunnable Maven / Gradle / Ivy

/**
 * Copyright 2015 Groupon.com
 *
 * 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
 *
 *     http://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 com.arpnetworking.metrics.jvm;

import com.arpnetworking.metrics.Metrics;
import com.arpnetworking.metrics.MetricsFactory;
import com.arpnetworking.metrics.jvm.collectors.BufferPoolMetricsCollector;
import com.arpnetworking.metrics.jvm.collectors.FileDescriptorMetricsCollector;
import com.arpnetworking.metrics.jvm.collectors.GarbageCollectionMetricsCollector;
import com.arpnetworking.metrics.jvm.collectors.HeapMemoryMetricsCollector;
import com.arpnetworking.metrics.jvm.collectors.JvmMetricsCollector;
import com.arpnetworking.metrics.jvm.collectors.NonHeapMemoryMetricsCollector;
import com.arpnetworking.metrics.jvm.collectors.ThreadMetricsCollector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.management.BufferPoolMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.ThreadMXBean;
import java.util.ArrayList;
import java.util.List;

/**
 * An implementation of Runnable that collects all JVM metrics each time its run.
 *
 * @author Deepika Misra (deepika at groupon dot com)
 */
// CHECKSTYLE.OFF: FinalClass - Allow clients to inherit from this.
public class JvmMetricsRunnable implements Runnable {
// CHECKSTYLE.ON: FinalClass

    /**
     * {@inheritDoc}
     */
    @Override
    public void run() {
        Metrics metrics = null;
        try {
            metrics = _metricsFactory.create();
            for (final JvmMetricsCollector collector : _collectorsEnabled) {
                collector.collect(metrics, _managementFactory);
            }
            // CHECKSTYLE.OFF: IllegalCatch - No checked exceptions here
        } catch (final Exception e) {
            // CHECKSTYLE.ON: IllegalCatch
            handleException(e);
        } finally {
            try {
                metrics.close();
            // CHECKSTYLE.OFF: IllegalCatch - No checked exceptions here
            } catch (final Exception e) {
            // CHECKSTYLE.ON: IllegalCatch
                handleException(e);
            }
        }
    }

    /**
     * Handles exceptions based on a boolean flag. If the flag is true, it logs and swallows the exception, else it will
     * throw.
     *
     * @param e An instance of RuntimeException.
     */
    protected void handleException(final Exception e) {
        if (_swallowException) {
            LOGGER.warn("JVM metrics collection failed.", e);
        } else {
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            } else {
                throw new RuntimeException(e);
            }
        }
    }

    private JvmMetricsRunnable(final Builder builder) {
        _metricsFactory = builder._metricsFactory;
        _managementFactory = builder._managementFactory;
        _swallowException = builder._swallowException;
        if (builder._collectGarbageCollectionMetrics) {
            _collectorsEnabled.add(builder._garbageCollectionMetricsCollector);
        }
        if (builder._collectHeapMemoryMetrics) {
            _collectorsEnabled.add(builder._heapMemoryMetricsCollector);
        }
        if (builder._collectNonHeapMemoryMetrics) {
            _collectorsEnabled.add(builder._nonHeapMemoryMetricsCollector);
        }
        if (builder._collectThreadMetrics) {
            _collectorsEnabled.add(builder._threadMetricsCollector);
        }
        if (builder._collectBufferPoolMetrics) {
            _collectorsEnabled.add(builder._bufferPoolMetricsCollector);
        }
        if (builder._collectFileDescriptorMetrics) {
            _collectorsEnabled.add(builder._fileDescriptorMetricsCollector);
        }
    }

    private final MetricsFactory _metricsFactory;
    private final ManagementFactory _managementFactory;
    private final boolean _swallowException;
    private final List _collectorsEnabled = new ArrayList<>();

    private static final Logger LOGGER = LoggerFactory.getLogger(JvmMetricsRunnable.class);

    /**
     * Builder for JvmMetricsRunnable.
     *
     * @author Deepika Misra (deepika at groupon dot com)
     */
    // CHECKSTYLE.OFF: FinalClass - Allow clients to inherit from this.
    public static class Builder {
    // CHECKSTYLE.ON: FinalClass

        /**
         * Builds an instance of JvmMetricsRunnable.
         *
         * @return An instance of JvmMetricsRunnable.
         */
        public JvmMetricsRunnable build() {
            if (_metricsFactory == null) {
                throw new IllegalArgumentException("MetricsFactory cannot be null.");
            }
            if (_managementFactory == null) {
                throw new IllegalArgumentException("ManagementFactory cannot be null.");
            }
            if (_swallowException == null) {
                throw new IllegalArgumentException("SwallowException cannot be null.");
            }
            if (_collectNonHeapMemoryMetrics == null) {
                throw new IllegalArgumentException("CollectNonHeapMemoryMetrics cannot be null.");
            }
            if (_collectHeapMemoryMetrics == null) {
                throw new IllegalArgumentException("CollectHeapMemoryMetrics cannot be null.");
            }
            if (_collectThreadMetrics == null) {
                throw new IllegalArgumentException("CollectThreadMetrics cannot be null.");
            }
            if (_collectGarbageCollectionMetrics == null) {
                throw new IllegalArgumentException("CollectGarbageCollectionMetrics cannot be null.");
            }
            if (_collectBufferPoolMetrics == null) {
                throw new IllegalArgumentException("CollectBufferPoolMetrics cannot be null.");
            }
            if (_collectFileDescriptorMetrics == null) {
                throw new IllegalArgumentException("CollectFileDescriptorMetrics cannot be null.");
            }
            if (_nonHeapMemoryMetricsCollector == null) {
                throw new IllegalArgumentException("NonHeapMemoryMetricsCollector cannot be null.");
            }
            if (_heapMemoryMetricsCollector == null) {
                throw new IllegalArgumentException("HeapMemoryMetricsCollector cannot be null.");
            }
            if (_threadMetricsCollector == null) {
                throw new IllegalArgumentException("ThreadMetricsCollector cannot be null.");
            }
            if (_garbageCollectionMetricsCollector == null) {
                throw new IllegalArgumentException("GarbageCollectionMetricsCollector cannot be null.");
            }
            if (_bufferPoolMetricsCollector == null) {
                throw new IllegalArgumentException("BufferPoolMetricsCollector cannot be null.");
            }
            if (_fileDescriptorMetricsCollector == null) {
                throw new IllegalArgumentException("FileDescriptorMetricsCollector cannot be null.");
            }
            return new JvmMetricsRunnable(this);
        }

        /**
         * Set the MetricsFactory instance. Required. Cannot be null.
         *
         * @param value The value for the MetricsFactory instance.
         * @return This Builder instance.
         */
        public Builder setMetricsFactory(final MetricsFactory value) {
            _metricsFactory = value;
            return this;
        }

        /**
         * Set the flag indicating if any exception caught during the process of metrics collection should be logged and
         * swallowed. Optional. Defaults to true. True indicates that the exception will be logged and swallowed.
         *
         * @param value The value for the Boolean instance.
         * @return This Builder instance.
         */
        public Builder setSwallowException(final Boolean value) {
            _swallowException = value;
            return this;
        }

        /**
         * Set the flag indicating if Heap Memory metrics should be collected. A true value indicates that these
         * metrics need to be collected. Optional. Defaults to true.
         *
         * @param value A Boolean value.
         * @return This Builder instance.
         */
        public Builder setCollectHeapMemoryMetrics(final Boolean value) {
            _collectHeapMemoryMetrics = value;
            return this;
        }

        /**
         * Set the flag indicating if Non-Heap Memory metrics should be collected. A true value indicates that these
         * metrics need to be collected. Optional. Defaults to true.
         *
         * @param value A Boolean value.
         * @return This Builder instance.
         */
        public Builder setCollectNonHeapMemoryMetrics(final Boolean value) {
            _collectNonHeapMemoryMetrics = value;
            return this;
        }


        /**
         * Set the flag indicating if Thread metrics should be collected. A true value indicates that these metrics
         * need to be collected. Optional. Defaults to true.
         *
         * @param value A Boolean value.
         * @return This Builder instance.
         */
        public Builder setCollectThreadMetrics(final Boolean value) {
            _collectThreadMetrics = value;
            return this;
        }

        /**
         * Set the flag indicating if Garbage Collection metrics should be collected. A true value indicates that these
         * metrics need to be collected. Optional. Defaults to true.
         *
         * @param value A Boolean value.
         * @return This Builder instance.
         */
        public Builder setCollectGarbageCollectionMetrics(final Boolean value) {
            _collectGarbageCollectionMetrics = value;
            return this;
        }

        /**
         * Set the flag indicating if Buffer Pool metrics should be collected. A true value indicates that these
         * metrics need to be collected. Optional. Defaults to true.
         *
         * @param value A Boolean value.
         * @return This Builder instance.
         */
        public Builder setCollectBufferPoolMetrics(final Boolean value) {
            _collectBufferPoolMetrics = value;
            return this;
        }

        /**
         * Set the flag indicating if File Descriptor metrics should be collected. A true value indicates that these
         * metrics need to be collected. Optional. Defaults to true.
         *
         * @param value A Boolean value.
         * @return This Builder instance.
         */
        public Builder setCollectFileDescriptorMetrics(final Boolean value) {
            _collectFileDescriptorMetrics = value;
            return this;
        }

        /**
         * Set the ManagementFactory instance. Defaults to an instance of
         * ManagementFactoryDefault. This is for testing purposes only and should never be used by clients.
         *
         * @param value The value for the ManagementFactory instance.
         * @return This Builder instance.
         */
        /* package private */ Builder setManagementFactory(final ManagementFactory value) {
            _managementFactory = value;
            return this;
        }

        /**
         * Set the HeapMemoryMetricsCollector. Defaults to an instance of
         * HeapMemoryMetricsCollector. This is for testing purposes only and should never be used by
         * clients.
         *
         * @param value A HeapMemoryMetricsCollector instance.
         * @return This Builder instance.
         */
        /* package private */ Builder setHeapMemoryMetricsCollector(final JvmMetricsCollector value) {
            _heapMemoryMetricsCollector = value;
            return this;
        }

        /**
         * Set the NonHeapMemoryMetricsCollector. Defaults to an instance of
         * NonHeapMemoryMetricsCollector. This is for testing purposes only and should never be used by
         * clients.
         *
         * @param value A NonHeapMemoryMetricsCollector instance.
         * @return This Builder instance.
         */
        /* package private */ Builder setNonHeapMemoryMetricsCollector(final JvmMetricsCollector value) {
            _nonHeapMemoryMetricsCollector = value;
            return this;
        }

        /**
         * Set the ThreadMetricsCollector. Defaults to an instance of
         * ThreadMetricsCollector. This is for testing purposes only and should never be used by clients.
         *
         * @param value A ThreadMetricsCollector instance.
         * @return This Builder instance.
         */
        /* package private */ Builder setThreadMetricsCollector(final JvmMetricsCollector value) {
            _threadMetricsCollector = value;
            return this;
        }

        /**
         * Set the GarbageCollectionMetricsCollector. Defaults to an instance of
         * GarbageCollectionMetricsCollector. This is for testing purposes only and should never be used
         * by clients.
         *
         * @param value A GarbageCollectionMetricsCollector instance.
         * @return This Builder instance.
         */
        /* package private */ Builder setGarbageCollectionMetricsCollector(final JvmMetricsCollector value) {
            _garbageCollectionMetricsCollector = value;
            return this;
        }

        /**
         * Set the BufferPoolMetricsCollector. Defaults to an instance of
         * BufferPoolMetricsCollector. This is for testing purposes only and should never be used
         * by clients.
         *
         * @param value A BufferPoolMetricsCollector instance.
         * @return This Builder instance.
         */
        /* package private */ Builder setBufferPoolMetricsCollector(final JvmMetricsCollector value) {
            _bufferPoolMetricsCollector = value;
            return this;
        }

        /**
         * Set the FileDescriptorMetricsCollector. Defaults to an instance of
         * FileDescriptorMetricsCollector. This is for testing purposes only and should never be used
         * by clients.
         *
         * @param value A FileDescriptorMetricsCollector instance.
         * @return This Builder instance.
         */
        /* package private */ Builder setFileDescriptorMetricsCollector(final JvmMetricsCollector value) {
            _fileDescriptorMetricsCollector = value;
            return this;
        }

        private MetricsFactory _metricsFactory;
        private ManagementFactory _managementFactory = MANAGEMENT_FACTORY_DEFAULT;
        private Boolean _swallowException = true;
        private Boolean _collectNonHeapMemoryMetrics = true;
        private Boolean _collectHeapMemoryMetrics = true;
        private Boolean _collectThreadMetrics = true;
        private Boolean _collectGarbageCollectionMetrics = true;
        private Boolean _collectBufferPoolMetrics = true;
        private Boolean _collectFileDescriptorMetrics = true;
        private JvmMetricsCollector _nonHeapMemoryMetricsCollector = NonHeapMemoryMetricsCollector.newInstance();
        private JvmMetricsCollector _heapMemoryMetricsCollector = HeapMemoryMetricsCollector.newInstance();
        private JvmMetricsCollector _threadMetricsCollector = ThreadMetricsCollector.newInstance();
        private JvmMetricsCollector _garbageCollectionMetricsCollector = GarbageCollectionMetricsCollector.newInstance();
        private JvmMetricsCollector _bufferPoolMetricsCollector = BufferPoolMetricsCollector.newInstance();
        private JvmMetricsCollector _fileDescriptorMetricsCollector = FileDescriptorMetricsCollector.newInstance();

        private static final ManagementFactory MANAGEMENT_FACTORY_DEFAULT = ManagementFactoryDefault.newInstance();
    }

    /**
    * An implementation class of ManagementFactory that is to be used for getting the actual values for jvm
    * metrics from the java management API. This class exists to facilitate testing only and the clients should never
    * have to explicitly instantiate this.
    *
    * @author Deepika Misra (deepika at groupon dot com)
    */
    /* package private */ static final class ManagementFactoryDefault implements ManagementFactory {

        /**
         * Creates a new instance of ManagementFactoryDefault.
         *
         * @return An instance of ManagementFactoryDefault
         */
        /* package private */ static ManagementFactory newInstance() {
            return new ManagementFactoryDefault();
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public List getGarbageCollectorMXBeans() {
            return java.lang.management.ManagementFactory.getGarbageCollectorMXBeans();
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public MemoryMXBean getMemoryMXBean() {
            return java.lang.management.ManagementFactory.getMemoryMXBean();
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public List getMemoryPoolMXBeans() {
            return java.lang.management.ManagementFactory.getMemoryPoolMXBeans();
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public ThreadMXBean getThreadMXBean() {
            return java.lang.management.ManagementFactory.getThreadMXBean();
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public List getBufferPoolMXBeans() {
            return java.lang.management.ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public OperatingSystemMXBean getOperatingSystemMXBean() {
            return java.lang.management.ManagementFactory.getOperatingSystemMXBean();
        }

        private ManagementFactoryDefault() {}
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy