001package com.nimbusds.common.monitor;
002
003
004import java.util.Map;
005import java.util.concurrent.TimeUnit;
006import java.util.function.Supplier;
007
008import com.codahale.metrics.*;
009import com.codahale.metrics.health.HealthCheck;
010import com.codahale.metrics.health.HealthCheckRegistry;
011
012import com.nimbusds.common.config.MonitorConfiguration;
013
014
015/**
016 * Shared monitor registers for Dropwizard metrics and health checks.
017 *
018 * @see com.nimbusds.common.servlet.MonitorLauncher
019 */
020public class MonitorRegistries {
021
022
023        /**
024         * The metrics registry.
025         */
026        private static MetricRegistry metricRegistry;
027
028
029        /**
030         * The health checks registry.
031         */
032        private static HealthCheckRegistry healthCheckRegistry;
033        
034        
035        /**
036         * Timeout for caching entry count results, in seconds. Zero means
037         * infinite (never expire), negative disabled.
038         */
039        private static long entryCountCacheTimeout = MonitorConfiguration.DEFAULT_ENTRY_COUNT_CACHE_TIMEOUT;
040
041
042        /**
043         * Returns the singleton shared registry for metric instances.
044         *
045         * @return The registry.
046         */
047        public static MetricRegistry getMetricRegistry() {
048                
049                if (metricRegistry == null) {
050                        metricRegistry = new MetricRegistry();
051                }
052                return metricRegistry;
053        }
054
055
056        /**
057         * Returns the singleton shared registry for health check instances.
058         *
059         * @return The registry.
060         */
061        public static HealthCheckRegistry getHealthCheckRegistry() {
062                
063                if (healthCheckRegistry == null) {
064                        healthCheckRegistry = new HealthCheckRegistry();
065                }
066                return healthCheckRegistry;
067        }
068
069
070        /**
071         * Registers a metric set.
072         *
073         * @param metricSet The metric set to register. If {@code null} the
074         *                  method will return immediately.
075         */
076        public static void register(final MetricSet metricSet) {
077
078                if (metricSet == null) {
079                        return;
080                }
081
082                for (Map.Entry<String,Metric> entry: metricSet.getMetrics().entrySet()) {
083                        register(entry.getKey(), entry.getValue());
084                }
085        }
086
087
088        /**
089         * Registers, updates or unregisters a metric.
090         *
091         * @param name   The metric name. If {@code null} the method will
092         *               return immediately.
093         * @param metric The metric, {@code null} to unregister. If a metric
094         *               with the same name exists it will be replaced.
095         */
096        public static void register(final String name, final Metric metric) {
097
098                if (name == null) {
099                        return;
100                }
101
102                if (metric != null) {
103                        if (getMetricRegistry().getNames().contains(name)) {
104                                // remove previously registered metric with same name
105                                getMetricRegistry().remove(name);
106                        }
107                        getMetricRegistry().register(name, metric);
108                } else {
109                        getMetricRegistry().remove(name);
110                }
111        }
112
113
114        /**
115         * Registers or updates an entry count gauge according to the
116         * configured {@link #getEntryCountCacheTimeout() cache timeout}.
117         *
118         * @param name     The gauge name name. If {@code null} the method will
119         *                 return immediately.
120         * @param supplier The entry count supplier.
121         */
122        public static void registerEntryCountGauge(final String name, final Supplier<Integer> supplier) {
123
124                final Metric metricToRegister;
125                
126                if (entryCountCacheTimeout < 0) {
127                        // disabled
128                        metricToRegister = (Gauge<Integer>) () -> -1;
129                } else if (entryCountCacheTimeout == 0) {
130                        // no caching
131                        metricToRegister = (Gauge<Integer>) supplier::get;
132                } else {
133                        // caching
134                        metricToRegister = new CachedGauge<Integer>(entryCountCacheTimeout, TimeUnit.SECONDS) {
135                                @Override
136                                protected Integer loadValue() {
137                                        return supplier.get();
138                                }
139                        };
140                }
141                
142                register(name, metricToRegister);
143        }
144        
145        
146        /**
147         * Gets the timeout for entry count gauges.
148         *
149         * @return The timeout for caching entry count results, in seconds.
150         *         Zero means no caching, negative disabled readings.
151         */
152        public static long getEntryCountCacheTimeout() {
153                return entryCountCacheTimeout;
154        }
155        
156        
157        /**
158         * Sets the timeout for entry count gauges.
159         *
160         * @param entryCountCacheTimeout The timeout for caching entry count
161         *                               results, in seconds. Zero means no
162         *                               caching, negative disabled readings.
163         */
164        public static void setEntryCountCacheTimeout(final long entryCountCacheTimeout) {
165                MonitorRegistries.entryCountCacheTimeout = entryCountCacheTimeout;
166        }
167        
168        
169        /**
170         * Registers, updates or unregisters a health check.
171         *
172         * @param name  The health check name. If {@code null} the method will
173         *              return immediately.
174         * @param check The health check, {@code null} to unregister. If a
175         *              metric with the same name exists it will be replaced.
176         */
177        public static void register(final String name, final HealthCheck check) {
178
179                if (name == null) {
180                        return;
181                }
182
183                if (check != null) {
184                        if (getHealthCheckRegistry().getNames().contains(name)) {
185                                // remove previously registered check with same name
186                                getHealthCheckRegistry().unregister(name);
187                        }
188                        getHealthCheckRegistry().register(name, check);
189                } else {
190                        getHealthCheckRegistry().unregister(name);
191                }
192        }
193
194
195        /**
196         * Prevents public instantiation.
197         */
198        private MonitorRegistries() { }
199}