Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored outdated terms #852

Merged
merged 1 commit into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ jmxUrl: service:jmx:rmi:///jndi/rmi://127.0.0.1:1234/jmxrmi
ssl: false
lowercaseOutputName: false
lowercaseOutputLabelNames: false
whitelistObjectNames: ["org.apache.cassandra.metrics:*"]
blacklistObjectNames: ["org.apache.cassandra.metrics:type=ColumnFamily,*"]
includeObjectNames: ["org.apache.cassandra.metrics:*"]
excludeObjectNames: ["org.apache.cassandra.metrics:type=ColumnFamily,*"]
rules:
- pattern: 'org.apache.cassandra.metrics<type=(\w+), name=(\w+)><>Value: (\d+)'
name: cassandra_$1_$2
Expand All @@ -104,8 +104,8 @@ jmxUrl | A full JMX URL to connect to. Should not be specified if hostPort i
ssl | Whether JMX connection should be done over SSL. To configure certificates you have to set following system properties:<br/>`-Djavax.net.ssl.keyStore=/home/user/.keystore`<br/>`-Djavax.net.ssl.keyStorePassword=changeit`<br/>`-Djavax.net.ssl.trustStore=/home/user/.truststore`<br/>`-Djavax.net.ssl.trustStorePassword=changeit`
lowercaseOutputName | Lowercase the output metric name. Applies to default format and `name`. Defaults to false.
lowercaseOutputLabelNames | Lowercase the output metric label names. Applies to default format and `labels`. Defaults to false.
whitelistObjectNames | A list of [ObjectNames](http://docs.oracle.com/javase/6/docs/api/javax/management/ObjectName.html) to query. Defaults to all mBeans.
blacklistObjectNames | A list of [ObjectNames](http://docs.oracle.com/javase/6/docs/api/javax/management/ObjectName.html) to not query. Takes precedence over `whitelistObjectNames`. Defaults to none.
includeObjectNames | A list of [ObjectNames](http://docs.oracle.com/javase/6/docs/api/javax/management/ObjectName.html) to query. Defaults to all mBeans.
excludeObjectNames | A list of [ObjectNames](http://docs.oracle.com/javase/6/docs/api/javax/management/ObjectName.html) to not query. Takes precedence over `includeObjectNames`. Defaults to none.
rules | A list of rules to apply in order, processing stops at the first matching rule. Attributes that aren't matched aren't collected. If not specified, defaults to collecting everything in the default format.
pattern | Regex pattern to match against each bean attribute. The pattern is not anchored. Capture groups can be used in other options. Defaults to matching everything.
attrNameSnakeCase | Converts the attribute name to snake case. This is seen in the names matched by the pattern and the default format. For example, anAttrName to an\_attr\_name. Defaults to false.
Expand All @@ -125,6 +125,10 @@ Note that the scraper always processes all mBeans, even if they're not exported.

Example configurations for javaagents can be found at https://github.com/prometheus/jmx_exporter/tree/master/example_configs

**NOTE**

Both `whitelistObjectNames` and `blacklistObjectNames` are still supported for backward compatibility, but should be considered deprecated.

### Pattern input
The format of the input matches against the pattern is
```
Expand Down
30 changes: 21 additions & 9 deletions collector/src/main/java/io/prometheus/jmx/JmxCollector.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ private static class Config {
boolean ssl = false;
boolean lowercaseOutputName;
boolean lowercaseOutputLabelNames;
List<ObjectName> whitelistObjectNames = new ArrayList<ObjectName>();
List<ObjectName> blacklistObjectNames = new ArrayList<ObjectName>();
List<ObjectName> includeObjectNames = new ArrayList<>();
List<ObjectName> excludeObjectNames = new ArrayList<>();
List<Rule> rules = new ArrayList<Rule>();
long lastUpdate = 0L;

Expand Down Expand Up @@ -210,19 +210,31 @@ private Config loadConfig(Map<String, Object> yamlConfig) throws MalformedObject
cfg.lowercaseOutputLabelNames = (Boolean)yamlConfig.get("lowercaseOutputLabelNames");
}

if (yamlConfig.containsKey("whitelistObjectNames")) {
// Default to includeObjectNames, but fall back to whitelistObjectNames for backward compatibility
if (yamlConfig.containsKey("includeObjectNames")) {
List<Object> names = (List<Object>) yamlConfig.get("includeObjectNames");
for (Object name : names) {
cfg.includeObjectNames.add(new ObjectName((String) name));
}
} else if (yamlConfig.containsKey("whitelistObjectNames")) {
List<Object> names = (List<Object>) yamlConfig.get("whitelistObjectNames");
for(Object name : names) {
cfg.whitelistObjectNames.add(new ObjectName((String)name));
for (Object name : names) {
cfg.includeObjectNames.add(new ObjectName((String) name));
}
} else {
cfg.whitelistObjectNames.add(null);
cfg.includeObjectNames.add(null);
}

if (yamlConfig.containsKey("blacklistObjectNames")) {
// Default to excludeObjectNames, but fall back to blacklistObjectNames for backward compatibility
if (yamlConfig.containsKey("excludeObjectNames")) {
List<Object> names = (List<Object>) yamlConfig.get("excludeObjectNames");
for (Object name : names) {
cfg.excludeObjectNames.add(new ObjectName((String)name));
}
} else if (yamlConfig.containsKey("blacklistObjectNames")) {
List<Object> names = (List<Object>) yamlConfig.get("blacklistObjectNames");
for (Object name : names) {
cfg.blacklistObjectNames.add(new ObjectName((String)name));
cfg.excludeObjectNames.add(new ObjectName((String)name));
}
}

Expand Down Expand Up @@ -648,7 +660,7 @@ public List<MetricFamilySamples> collect() {
MatchedRulesCache.StalenessTracker stalenessTracker = new MatchedRulesCache.StalenessTracker();
Receiver receiver = new Receiver(config, stalenessTracker);
JmxScraper scraper = new JmxScraper(config.jmxUrl, config.username, config.password, config.ssl,
config.whitelistObjectNames, config.blacklistObjectNames, receiver, jmxMBeanPropertyCache);
config.includeObjectNames, config.excludeObjectNames, receiver, jmxMBeanPropertyCache);
long start = System.nanoTime();
double error = 0;
if ((config.startDelaySeconds > 0) &&
Expand Down
12 changes: 6 additions & 6 deletions collector/src/main/java/io/prometheus/jmx/JmxScraper.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,20 @@ void recordBean(
private final String username;
private final String password;
private final boolean ssl;
private final List<ObjectName> whitelistObjectNames, blacklistObjectNames;
private final List<ObjectName> includeObjectNames, excludeObjectNames;
private final JmxMBeanPropertyCache jmxMBeanPropertyCache;
private final OptionalValueExtractor optionalValueExtractor = new OptionalValueExtractor();

public JmxScraper(String jmxUrl, String username, String password, boolean ssl,
List<ObjectName> whitelistObjectNames, List<ObjectName> blacklistObjectNames,
List<ObjectName> includeObjectNames, List<ObjectName> excludeObjectNames,
MBeanReceiver receiver, JmxMBeanPropertyCache jmxMBeanPropertyCache) {
this.jmxUrl = jmxUrl;
this.receiver = receiver;
this.username = username;
this.password = password;
this.ssl = ssl;
this.whitelistObjectNames = whitelistObjectNames;
this.blacklistObjectNames = blacklistObjectNames;
this.includeObjectNames = includeObjectNames;
this.excludeObjectNames = excludeObjectNames;
this.jmxMBeanPropertyCache = jmxMBeanPropertyCache;
}

Expand Down Expand Up @@ -114,13 +114,13 @@ public void doScrape() throws Exception {
try {
// Query MBean names, see #89 for reasons queryMBeans() is used instead of queryNames()
Set<ObjectName> mBeanNames = new HashSet<ObjectName>();
for (ObjectName name : whitelistObjectNames) {
for (ObjectName name : includeObjectNames) {
for (ObjectInstance instance : beanConn.queryMBeans(name, null)) {
mBeanNames.add(instance.getObjectName());
}
}

for (ObjectName name : blacklistObjectNames) {
for (ObjectName name : excludeObjectNames) {
for (ObjectInstance instance : beanConn.queryMBeans(name, null)) {
mBeanNames.remove(instance.getObjectName());
}
Expand Down
24 changes: 24 additions & 0 deletions collector/src/test/java/io/prometheus/jmx/JmxCollectorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,18 @@ public void tabularDataCompositeKeyTest() throws Exception {
assertEquals(2, registry.getSampleValue("org_exist_management_exist_ProcessReport_RunningQueries_id", new String[]{"key_id", "key_path"}, new String[]{"2", "/db/query2.xq"}), .001);
}

@Test
public void testIncludeObjectNames() throws Exception {
JmxCollector jc = new JmxCollector("\n---\nincludeObjectNames:\n- java.lang:*\n- java.lang:*\n- org.apache.cassandra.concurrent:*".replace('`','"')).register(registry);

// Test what should and shouldn't be present.
assertNotNull(registry.getSampleValue("java_lang_OperatingSystem_ProcessCpuTime", new String[]{}, new String[]{}));
assertNotNull(registry.getSampleValue("org_apache_cassandra_concurrent_CONSISTENCY_MANAGER_ActiveCount", new String[]{}, new String[]{}));

assertNull(registry.getSampleValue("org_apache_cassandra_metrics_Compaction_Value", new String[]{"name"}, new String[]{"CompletedTasks"}));
assertNull(registry.getSampleValue("hadoop_DataNode_replaceBlockOpMinTime", new String[]{"name"}, new String[]{"DataNodeActivity-ams-hdd001-50010"}));
}

@Test
public void testWhitelist() throws Exception {
JmxCollector jc = new JmxCollector("\n---\nwhitelistObjectNames:\n- java.lang:*\n- java.lang:*\n- org.apache.cassandra.concurrent:*".replace('`','"')).register(registry);
Expand All @@ -188,6 +200,18 @@ public void testWhitelist() throws Exception {
assertNull(registry.getSampleValue("hadoop_DataNode_replaceBlockOpMinTime", new String[]{"name"}, new String[]{"DataNodeActivity-ams-hdd001-50010"}));
}

@Test
public void testExcludeObjectNames() throws Exception {
JmxCollector jc = new JmxCollector("\n---\nincludeObjectNames:\n- java.lang:*\n- org.apache.cassandra.concurrent:*\nexcludeObjectNames:\n- org.apache.cassandra.concurrent:*".replace('`','"')).register(registry);

// Test what should and shouldn't be present.
assertNotNull(registry.getSampleValue("java_lang_OperatingSystem_ProcessCpuTime", new String[]{}, new String[]{}));

assertNull(registry.getSampleValue("org_apache_cassandra_concurrent_CONSISTENCY_MANAGER_ActiveCount", new String[]{}, new String[]{}));
assertNull(registry.getSampleValue("org_apache_cassandra_metrics_Compaction_Value", new String[]{"name"}, new String[]{"CompletedTasks"}));
assertNull(registry.getSampleValue("hadoop_DataNode_replaceBlockOpMinTime", new String[]{"name"}, new String[]{"DataNodeActivity-ams-hdd001-50010"}));
}

@Test
public void testBlacklist() throws Exception {
JmxCollector jc = new JmxCollector("\n---\nwhitelistObjectNames:\n- java.lang:*\n- org.apache.cassandra.concurrent:*\nblacklistObjectNames:\n- org.apache.cassandra.concurrent:*".replace('`','"')).register(registry);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (C) 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.test;

import io.prometheus.jmx.test.support.ContentConsumer;
import io.prometheus.jmx.test.support.HealthyRequest;
import io.prometheus.jmx.test.support.HealthyResponse;
import io.prometheus.jmx.test.support.MetricsRequest;
import io.prometheus.jmx.test.support.MetricsResponse;
import io.prometheus.jmx.test.support.OpenMetricsRequest;
import io.prometheus.jmx.test.support.OpenMetricsResponse;
import io.prometheus.jmx.test.support.PrometheusMetricsRequest;
import io.prometheus.jmx.test.support.PrometheusMetricsResponse;
import io.prometheus.jmx.test.support.RequestResponseAssertions;
import org.antublue.test.engine.api.TestEngine;

import java.util.Collection;

import static org.assertj.core.api.Assertions.assertThat;

public class ExcludeObjectNamesTest extends BaseTest implements ContentConsumer {

@TestEngine.Test
public void testHealthy() {
RequestResponseAssertions
.assertThatResponseForRequest(new HealthyRequest(testState.httpClient()))
.isSuperset(HealthyResponse.RESULT_200);
}

@TestEngine.Test
public void testMetrics() {
RequestResponseAssertions
.assertThatResponseForRequest(new MetricsRequest(testState.httpClient()))
.isSuperset(MetricsResponse.RESULT_200)
.dispatch(this);
}

@TestEngine.Test
public void testMetricsOpenMetricsFormat() {
RequestResponseAssertions
.assertThatResponseForRequest(new OpenMetricsRequest(testState.httpClient()))
.isSuperset(OpenMetricsResponse.RESULT_200)
.dispatch(this);
}

@TestEngine.Test
public void testMetricsPrometheusFormat() {
RequestResponseAssertions
.assertThatResponseForRequest(new PrometheusMetricsRequest(testState.httpClient()))
.isSuperset(PrometheusMetricsResponse.RESULT_200)
.dispatch(this);
}

@Override
public void accept(String content) {
Collection<Metric> metricCollection = MetricsParser.parse(content);

/*
* Assert that we don't have any metrics that start with ...
*
* name = java_lang*
*/
metricCollection
.forEach(metric -> assertThat(metric.getName().toLowerCase()).doesNotStartWith("java_lang"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright (C) 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.test;

import io.prometheus.jmx.test.support.ContentConsumer;
import io.prometheus.jmx.test.support.HealthyRequest;
import io.prometheus.jmx.test.support.HealthyResponse;
import io.prometheus.jmx.test.support.MetricsRequest;
import io.prometheus.jmx.test.support.MetricsResponse;
import io.prometheus.jmx.test.support.OpenMetricsRequest;
import io.prometheus.jmx.test.support.OpenMetricsResponse;
import io.prometheus.jmx.test.support.PrometheusMetricsRequest;
import io.prometheus.jmx.test.support.PrometheusMetricsResponse;
import org.antublue.test.engine.api.TestEngine;

import java.util.Collection;

import static io.prometheus.jmx.test.support.RequestResponseAssertions.assertThatResponseForRequest;
import static org.assertj.core.api.Assertions.assertThat;

public class IncludeAndExcludeObjectNamesTest extends BaseTest implements ContentConsumer {

@TestEngine.Test
public void testHealthy() {
assertThatResponseForRequest(new HealthyRequest(testState.httpClient()))
.isSuperset(HealthyResponse.RESULT_200);
}

@TestEngine.Test
public void testMetrics() {
assertThatResponseForRequest(new MetricsRequest(testState.httpClient()))
.isSuperset(MetricsResponse.RESULT_200)
.dispatch(this);
}

@TestEngine.Test
public void testMetricsOpenMetricsFormat() {
assertThatResponseForRequest(new OpenMetricsRequest(testState.httpClient()))
.isSuperset(OpenMetricsResponse.RESULT_200)
.dispatch(this);
}

@TestEngine.Test
public void testMetricsPrometheusFormat() {
assertThatResponseForRequest(new PrometheusMetricsRequest(testState.httpClient()))
.isSuperset(PrometheusMetricsResponse.RESULT_200)
.dispatch(this);
}

@Override
public void accept(String content) {
Collection<Metric> metricCollection = MetricsParser.parse(content);

/*
* Assert that we don't have any metrics that start with ...
*
* name = java_lang*
*/
metricCollection
.forEach(metric -> assertThat(metric.getName().toLowerCase()).doesNotStartWith("java_lang"));
}
}
Loading