001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.fcrepo.config;
020
021import io.micrometer.core.instrument.Meter;
022import io.micrometer.core.instrument.MeterRegistry;
023import io.micrometer.core.instrument.Metrics;
024import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics;
025import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics;
026import io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics;
027import io.micrometer.core.instrument.binder.system.ProcessorMetrics;
028import io.micrometer.core.instrument.binder.system.UptimeMetrics;
029import io.micrometer.core.instrument.config.MeterFilter;
030import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
031import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
032import io.micrometer.prometheus.PrometheusConfig;
033import io.micrometer.prometheus.PrometheusMeterRegistry;
034import io.prometheus.client.CollectorRegistry;
035import org.springframework.beans.factory.annotation.Value;
036import org.springframework.context.annotation.Bean;
037import org.springframework.context.annotation.Configuration;
038
039import java.time.Duration;
040
041/**
042 * @author pwinckles
043 */
044@Configuration
045public class MetricsConfig extends BasePropsConfig {
046
047    @Value("${fcrepo.metrics.enable:false}")
048    private boolean metricsEnabled;
049
050    @Bean
051    public MeterRegistry meterRegistry() {
052        final MeterRegistry registry;
053
054        if (metricsEnabled) {
055            registry = new PrometheusMeterRegistry(new PrometheusConfig() {
056                @Override
057                public Duration step() {
058                    return Duration.ofSeconds(30);
059                }
060                @Override
061                public String get(final String key) {
062                    return null;
063                }
064            });
065            // Enables distribution stats for all timer metrics
066            registry.config().meterFilter(new MeterFilter() {
067                @Override
068                public DistributionStatisticConfig configure(final Meter.Id id,
069                                                             final DistributionStatisticConfig config) {
070                    if (id.getType() == Meter.Type.TIMER) {
071                        return DistributionStatisticConfig.builder()
072                                .percentilesHistogram(true)
073                                .percentiles(0.5, 0.90, 0.99)
074                                .build().merge(config);
075                    }
076                    return config;
077                }
078            });
079            new JvmThreadMetrics().bindTo(registry);
080            new JvmGcMetrics().bindTo(registry);
081            new JvmMemoryMetrics().bindTo(registry);
082            new ProcessorMetrics().bindTo(registry);
083            new UptimeMetrics().bindTo(registry);
084        } else {
085            registry = new SimpleMeterRegistry();
086        }
087
088        Metrics.addRegistry(registry);
089
090        return registry;
091    }
092
093    @Bean
094    public CollectorRegistry collectorRegistry(final MeterRegistry meterRegistry) {
095        if (meterRegistry instanceof PrometheusMeterRegistry) {
096            return ((PrometheusMeterRegistry) meterRegistry).getPrometheusRegistry();
097        }
098        return CollectorRegistry.defaultRegistry;
099    }
100
101    /**
102     * @return whether metrics are enabled
103     */
104    public boolean isMetricsEnabled() {
105        return metricsEnabled;
106    }
107
108}