
io.prometheus.jmx.JmxCollector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of collector Show documentation
Show all versions of collector Show documentation
See https://github.com/prometheus/jmx_exporter/blob/master/README.md
The newest version!
/*
* Copyright (C) 2015-2023 The Prometheus jmx_exporter Authors
*
* 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 io.prometheus.jmx;
import static java.lang.String.format;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.SEVERE;
import io.prometheus.jmx.logger.Logger;
import io.prometheus.jmx.logger.LoggerFactory;
import io.prometheus.metrics.core.metrics.Counter;
import io.prometheus.metrics.core.metrics.Gauge;
import io.prometheus.metrics.model.registry.MultiCollector;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
import io.prometheus.metrics.model.snapshots.Unit;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.yaml.snakeyaml.Yaml;
@SuppressWarnings("unchecked")
public class JmxCollector implements MultiCollector {
private static final Logger LOGGER = LoggerFactory.getLogger(JmxCollector.class);
public enum Mode {
AGENT,
STANDALONE
}
private final Mode mode;
static class Rule {
Pattern pattern;
String name;
String value;
Double valueFactor = 1.0;
String help;
boolean attrNameSnakeCase;
boolean cache = false;
String type = "UNKNOWN";
ArrayList labelNames;
ArrayList labelValues;
}
private static class Config {
Integer startDelaySeconds = 0;
String jmxUrl = "";
String username = "";
String password = "";
boolean ssl = false;
boolean lowercaseOutputName;
boolean lowercaseOutputLabelNames;
List includeObjectNames = new ArrayList<>();
List excludeObjectNames = new ArrayList<>();
ObjectNameAttributeFilter objectNameAttributeFilter;
List rules = new ArrayList<>();
long lastUpdate = 0L;
MatchedRulesCache rulesCache;
}
private PrometheusRegistry prometheusRegistry;
private Config config;
private File configFile;
private long createTimeNanoSecs = System.nanoTime();
private Counter configReloadSuccess;
private Counter configReloadFailure;
private Gauge jmxScrapeDurationSeconds;
private Gauge jmxScrapeError;
private Gauge jmxScrapeCachedBeans;
private final JmxMBeanPropertyCache jmxMBeanPropertyCache = new JmxMBeanPropertyCache();
public JmxCollector(File in) throws IOException, MalformedObjectNameException {
this(in, null);
}
public JmxCollector(File in, Mode mode) throws IOException, MalformedObjectNameException {
configFile = in;
this.mode = mode;
config = loadConfig(new Yaml().load(new FileReader(in)));
config.lastUpdate = configFile.lastModified();
exitOnConfigError();
}
public JmxCollector(String yamlConfig) throws MalformedObjectNameException {
config = loadConfig(new Yaml().load(yamlConfig));
mode = null;
}
public JmxCollector(InputStream inputStream) throws MalformedObjectNameException {
config = loadConfig(new Yaml().load(inputStream));
mode = null;
}
public JmxCollector register() {
return register(PrometheusRegistry.defaultRegistry);
}
public JmxCollector register(PrometheusRegistry prometheusRegistry) {
this.prometheusRegistry = prometheusRegistry;
configReloadSuccess =
Counter.builder()
.name("jmx_config_reload_success_total")
.help("Number of times configuration have successfully been reloaded.")
.register(prometheusRegistry);
configReloadFailure =
Counter.builder()
.name("jmx_config_reload_failure_total")
.help("Number of times configuration have failed to be reloaded.")
.register(prometheusRegistry);
jmxScrapeDurationSeconds =
Gauge.builder()
.name("jmx_scrape_duration_seconds")
.help("Time this JMX scrape took, in seconds.")
.unit(Unit.SECONDS)
.register(prometheusRegistry);
jmxScrapeError =
Gauge.builder()
.name("jmx_scrape_error")
.help("Non-zero if this scrape failed.")
.register(prometheusRegistry);
jmxScrapeCachedBeans =
Gauge.builder()
.name("jmx_scrape_cached_beans")
.help("Number of beans with their matching rule cached")
.register(prometheusRegistry);
prometheusRegistry.register(this);
return this;
}
private void exitOnConfigError() {
if (mode == Mode.AGENT && !config.jmxUrl.isEmpty()) {
LOGGER.log(
SEVERE,
"Configuration error: When running jmx_exporter as a Java agent, you must not"
+ " configure 'jmxUrl' or 'hostPort' because you don't want to monitor a"
+ " remote JVM.");
System.exit(-1);
}
if (mode == Mode.STANDALONE && config.jmxUrl.isEmpty()) {
LOGGER.log(
SEVERE,
"Configuration error: When running jmx_exporter in standalone mode (using"
+ " jmx_prometheus_httpserver-*.jar) you must configure 'jmxUrl' or"
+ " 'hostPort'.");
System.exit(-1);
}
}
private void reloadConfig() {
try {
FileReader fr = new FileReader(configFile);
try {
Map newYamlConfig = new Yaml().load(fr);
config = loadConfig(newYamlConfig);
config.lastUpdate = configFile.lastModified();
configReloadSuccess.inc();
} catch (Exception e) {
LOGGER.log(SEVERE, "Configuration reload failed: %s: ", e);
configReloadFailure.inc();
} finally {
fr.close();
}
} catch (IOException e) {
LOGGER.log(SEVERE, "Configuration reload failed: %s", e);
configReloadFailure.inc();
}
}
private synchronized Config getLatestConfig() {
if (configFile != null) {
long mtime = configFile.lastModified();
if (mtime > config.lastUpdate) {
LOGGER.log(FINE, "Configuration file changed, reloading...");
reloadConfig();
}
}
exitOnConfigError();
return config;
}
private Config loadConfig(Map yamlConfig) throws MalformedObjectNameException {
Config cfg = new Config();
if (yamlConfig == null) { // Yaml config empty, set config to empty map.
yamlConfig = new HashMap<>();
}
if (yamlConfig.containsKey("startDelaySeconds")) {
try {
cfg.startDelaySeconds = (Integer) yamlConfig.get("startDelaySeconds");
} catch (NumberFormatException e) {
throw new IllegalArgumentException(
"Invalid number provided for startDelaySeconds", e);
}
}
if (yamlConfig.containsKey("hostPort")) {
if (yamlConfig.containsKey("jmxUrl")) {
throw new IllegalArgumentException(
"At most one of hostPort and jmxUrl must be provided");
}
cfg.jmxUrl = "service:jmx:rmi:///jndi/rmi://" + yamlConfig.get("hostPort") + "/jmxrmi";
} else if (yamlConfig.containsKey("jmxUrl")) {
cfg.jmxUrl = (String) yamlConfig.get("jmxUrl");
}
if (yamlConfig.containsKey("username")) {
cfg.username = (String) yamlConfig.get("username");
}
if (yamlConfig.containsKey("password")) {
cfg.password = (String) yamlConfig.get("password");
}
if (yamlConfig.containsKey("ssl")) {
cfg.ssl = (Boolean) yamlConfig.get("ssl");
}
if (yamlConfig.containsKey("lowercaseOutputName")) {
cfg.lowercaseOutputName = (Boolean) yamlConfig.get("lowercaseOutputName");
}
if (yamlConfig.containsKey("lowercaseOutputLabelNames")) {
cfg.lowercaseOutputLabelNames = (Boolean) yamlConfig.get("lowercaseOutputLabelNames");
}
// Default to includeObjectNames, but fall back to whitelistObjectNames for backward
// compatibility
if (yamlConfig.containsKey("includeObjectNames")) {
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy