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