xref: /OpenGrok/opengrok-indexer/src/main/java/org/opengrok/indexer/Metrics.java (revision 5d9f3aa0ca3da3a714233f987fa732f62c0965f6)
161b71b09SAdam Hornacek /*
261b71b09SAdam Hornacek  * CDDL HEADER START
361b71b09SAdam Hornacek  *
461b71b09SAdam Hornacek  * The contents of this file are subject to the terms of the
561b71b09SAdam Hornacek  * Common Development and Distribution License (the "License").
661b71b09SAdam Hornacek  * You may not use this file except in compliance with the License.
761b71b09SAdam Hornacek  *
861b71b09SAdam Hornacek  * See LICENSE.txt included in this distribution for the specific
961b71b09SAdam Hornacek  * language governing permissions and limitations under the License.
1061b71b09SAdam Hornacek  *
1161b71b09SAdam Hornacek  * When distributing Covered Code, include this CDDL HEADER in each
1261b71b09SAdam Hornacek  * file and include the License file at LICENSE.txt.
1361b71b09SAdam Hornacek  * If applicable, add the following below this CDDL HEADER, with the
1461b71b09SAdam Hornacek  * fields enclosed by brackets "[]" replaced with your own identifying
1561b71b09SAdam Hornacek  * information: Portions Copyright [yyyy] [name of copyright owner]
1661b71b09SAdam Hornacek  *
1761b71b09SAdam Hornacek  * CDDL HEADER END
1861b71b09SAdam Hornacek  */
1961b71b09SAdam Hornacek 
2061b71b09SAdam Hornacek /*
21*5d9f3aa0SAdam Hornáček  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2261b71b09SAdam Hornacek  */
2361b71b09SAdam Hornacek package org.opengrok.indexer;
2461b71b09SAdam Hornacek 
250d7ace53SVladimir Kotal import io.micrometer.core.instrument.Clock;
260d7ace53SVladimir Kotal import io.micrometer.core.instrument.MeterRegistry;
270d7ace53SVladimir Kotal import io.micrometer.core.instrument.Tag;
289808407dSAdam Hornacek import io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics;
299808407dSAdam Hornacek import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics;
309808407dSAdam Hornacek import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics;
319808407dSAdam Hornacek import io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics;
329808407dSAdam Hornacek import io.micrometer.core.instrument.binder.system.ProcessorMetrics;
33073595b0SAdam Hornacek import io.micrometer.prometheus.PrometheusConfig;
34073595b0SAdam Hornacek import io.micrometer.prometheus.PrometheusMeterRegistry;
350d7ace53SVladimir Kotal import io.micrometer.statsd.StatsdConfig;
360d7ace53SVladimir Kotal import io.micrometer.statsd.StatsdMeterRegistry;
370d7ace53SVladimir Kotal import io.micrometer.statsd.StatsdFlavor;
380d7ace53SVladimir Kotal import org.opengrok.indexer.configuration.RuntimeEnvironment;
390d7ace53SVladimir Kotal import org.opengrok.indexer.index.Indexer;
400d7ace53SVladimir Kotal import org.opengrok.indexer.logger.LoggerFactory;
4161b71b09SAdam Hornacek 
420d7ace53SVladimir Kotal import java.util.Collections;
430d7ace53SVladimir Kotal import java.util.List;
440d7ace53SVladimir Kotal import java.util.logging.Level;
450d7ace53SVladimir Kotal import java.util.logging.Logger;
460d7ace53SVladimir Kotal import java.util.stream.Collectors;
470d7ace53SVladimir Kotal 
480d7ace53SVladimir Kotal /**
490d7ace53SVladimir Kotal  * Encapsulates logic of meter registry setup and handling.
500d7ace53SVladimir Kotal  * Generally, the web application publishes metrics to Prometheus and the Indexer to StatsD.
510d7ace53SVladimir Kotal  */
52073595b0SAdam Hornacek public final class Metrics {
5361b71b09SAdam Hornacek 
540d7ace53SVladimir Kotal     private static final Logger LOGGER = LoggerFactory.getLogger(Metrics.class);
550d7ace53SVladimir Kotal 
560d7ace53SVladimir Kotal     private static final StatsdConfig statsdConfig = new StatsdConfig() {
570d7ace53SVladimir Kotal         @Override
580d7ace53SVladimir Kotal         public String get(String k) {
590d7ace53SVladimir Kotal             return null;
600d7ace53SVladimir Kotal         }
610d7ace53SVladimir Kotal 
620d7ace53SVladimir Kotal         @Override
630d7ace53SVladimir Kotal         public StatsdFlavor flavor() {
640d7ace53SVladimir Kotal             return RuntimeEnvironment.getInstance().getStatsdConfig().getFlavor();
650d7ace53SVladimir Kotal         }
660d7ace53SVladimir Kotal 
670d7ace53SVladimir Kotal         @Override
680d7ace53SVladimir Kotal         public int port() {
690d7ace53SVladimir Kotal             return RuntimeEnvironment.getInstance().getStatsdConfig().getPort();
700d7ace53SVladimir Kotal         }
710d7ace53SVladimir Kotal 
720d7ace53SVladimir Kotal         @Override
730d7ace53SVladimir Kotal         public String host() {
740d7ace53SVladimir Kotal             return RuntimeEnvironment.getInstance().getStatsdConfig().getHost();
750d7ace53SVladimir Kotal         }
760d7ace53SVladimir Kotal 
770d7ace53SVladimir Kotal         @Override
780d7ace53SVladimir Kotal         public boolean buffered() {
790d7ace53SVladimir Kotal             return true;
800d7ace53SVladimir Kotal         }
810d7ace53SVladimir Kotal     };
820d7ace53SVladimir Kotal 
830d7ace53SVladimir Kotal     private static PrometheusMeterRegistry prometheusRegistry;
840d7ace53SVladimir Kotal     private static StatsdMeterRegistry statsdRegistry;
859808407dSAdam Hornacek 
869808407dSAdam Hornacek     static {
870d7ace53SVladimir Kotal         MeterRegistry registry = null;
880d7ace53SVladimir Kotal 
890d7ace53SVladimir Kotal         if (RuntimeEnvironment.getInstance().getStatsdConfig().isEnabled()) {
LOGGER.log(Level.INFO, "configuring StatsdRegistry")900d7ace53SVladimir Kotal             LOGGER.log(Level.INFO, "configuring StatsdRegistry");
910d7ace53SVladimir Kotal             statsdRegistry = new StatsdMeterRegistry(statsdConfig, Clock.SYSTEM);
920d7ace53SVladimir Kotal             registry = statsdRegistry;
930d7ace53SVladimir Kotal         } else if (!RuntimeEnvironment.getInstance().isIndexer()) {
LOGGER.log(Level.INFO, "configuring PrometheusRegistry")940d7ace53SVladimir Kotal             LOGGER.log(Level.INFO, "configuring PrometheusRegistry");
950d7ace53SVladimir Kotal             prometheusRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
960d7ace53SVladimir Kotal             registry = prometheusRegistry;
970d7ace53SVladimir Kotal         }
980d7ace53SVladimir Kotal 
990d7ace53SVladimir Kotal         if (registry != null) {
1009808407dSAdam Hornacek             new ClassLoaderMetrics().bindTo(registry);
1019808407dSAdam Hornacek             new JvmMemoryMetrics().bindTo(registry);
1029808407dSAdam Hornacek             new JvmGcMetrics().bindTo(registry);
1039808407dSAdam Hornacek             new ProcessorMetrics().bindTo(registry);
1049808407dSAdam Hornacek             new JvmThreadMetrics().bindTo(registry);
1059808407dSAdam Hornacek         }
1060d7ace53SVladimir Kotal     }
10761b71b09SAdam Hornacek 
Metrics()10861b71b09SAdam Hornacek     private Metrics() {
10961b71b09SAdam Hornacek     }
11061b71b09SAdam Hornacek 
updateSubFiles(List<String> subFiles)1110d7ace53SVladimir Kotal     public static void updateSubFiles(List<String> subFiles) {
1120d7ace53SVladimir Kotal         // Add tag for per-project reindex.
1130d7ace53SVladimir Kotal         if (statsdRegistry != null && !subFiles.isEmpty()) {
1140d7ace53SVladimir Kotal             String projects = subFiles.stream().
1150d7ace53SVladimir Kotal                     map(s -> s.startsWith(Indexer.PATH_SEPARATOR_STRING) ? s.substring(1) : s).
1160d7ace53SVladimir Kotal                     collect(Collectors.joining(","));
1170d7ace53SVladimir Kotal             Tag commonTag = Tag.of("projects", projects);
1180d7ace53SVladimir Kotal             LOGGER.log(Level.FINE, "updating statsdRegistry with common tag: {}", commonTag);
1190d7ace53SVladimir Kotal             statsdRegistry.config().commonTags(Collections.singleton(commonTag));
1200d7ace53SVladimir Kotal         }
12161b71b09SAdam Hornacek     }
12261b71b09SAdam Hornacek 
getPrometheusRegistry()1230d7ace53SVladimir Kotal     public static PrometheusMeterRegistry getPrometheusRegistry() {
1240d7ace53SVladimir Kotal         return prometheusRegistry;
1250d7ace53SVladimir Kotal     }
1260d7ace53SVladimir Kotal 
getStatsdRegistry()1270d7ace53SVladimir Kotal     private static StatsdMeterRegistry getStatsdRegistry() {
1280d7ace53SVladimir Kotal         return statsdRegistry;
1290d7ace53SVladimir Kotal     }
1300d7ace53SVladimir Kotal 
1310d7ace53SVladimir Kotal     /**
1320d7ace53SVladimir Kotal      * Get registry based on running context.
1330d7ace53SVladimir Kotal      * @return MeterRegistry instance
1340d7ace53SVladimir Kotal      */
getRegistry()1350d7ace53SVladimir Kotal     public static MeterRegistry getRegistry() {
1360d7ace53SVladimir Kotal         if (RuntimeEnvironment.getInstance().isIndexer()) {
1370d7ace53SVladimir Kotal             return getStatsdRegistry();
1380d7ace53SVladimir Kotal         } else {
1390d7ace53SVladimir Kotal             return getPrometheusRegistry();
1400d7ace53SVladimir Kotal         }
1410d7ace53SVladimir Kotal     }
14261b71b09SAdam Hornacek }
143