Skip to content

Commit f30888c

Browse files
committed
introduce JmxTelemetry + builder
1 parent 90fd359 commit f30888c

File tree

4 files changed

+127
-69
lines changed

4 files changed

+127
-69
lines changed

instrumentation/jmx-metrics/javaagent/src/main/java/io/opentelemetry/instrumentation/javaagent/jmx/JmxMetricInsightInstaller.java

Lines changed: 12 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,15 @@
55

66
package io.opentelemetry.instrumentation.javaagent.jmx;
77

8-
import static java.util.logging.Level.FINE;
9-
import static java.util.logging.Level.INFO;
10-
118
import com.google.auto.service.AutoService;
129
import io.opentelemetry.api.GlobalOpenTelemetry;
13-
import io.opentelemetry.instrumentation.jmx.engine.JmxMetricInsight;
14-
import io.opentelemetry.instrumentation.jmx.engine.MetricConfiguration;
15-
import io.opentelemetry.instrumentation.jmx.yaml.RuleParser;
10+
import io.opentelemetry.instrumentation.jmx.JmxTelemetry;
11+
import io.opentelemetry.instrumentation.jmx.JmxTelemetryBuilder;
1612
import io.opentelemetry.javaagent.extension.AgentListener;
1713
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
1814
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
1915
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
20-
import java.io.InputStream;
21-
import java.nio.file.Files;
22-
import java.nio.file.Paths;
2316
import java.time.Duration;
24-
import java.util.List;
2517

2618
/** An {@link AgentListener} that enables JMX metrics during agent startup. */
2719
@AutoService(AgentListener.class)
@@ -32,11 +24,16 @@ public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
3224
ConfigProperties config = AutoConfigureUtil.getConfig(autoConfiguredSdk);
3325

3426
if (config.getBoolean("otel.jmx.enabled", true)) {
35-
JmxMetricInsight service =
36-
JmxMetricInsight.createService(
37-
GlobalOpenTelemetry.get(), beanDiscoveryDelay(config).toMillis());
38-
MetricConfiguration conf = buildMetricConfiguration(config);
39-
service.startLocal(conf);
27+
JmxTelemetryBuilder jmx =
28+
JmxTelemetry.builder(GlobalOpenTelemetry.get())
29+
.beanDiscoveryDelay(beanDiscoveryDelay(config).toMillis());
30+
31+
config.getList("otel.jmx.config").forEach(jmx::addCustomRules);
32+
config
33+
.getList("otel.jmx.target.system")
34+
.forEach(system -> jmx.addClasspathRules(JmxMetricInsightInstaller.class, system));
35+
36+
jmx.build().startLocal();
4037
}
4138
}
4239

@@ -50,58 +47,4 @@ private static Duration beanDiscoveryDelay(ConfigProperties configProperties) {
5047
// It makes sense for both of these values to be similar.
5148
return configProperties.getDuration("otel.metric.export.interval", Duration.ofMinutes(1));
5249
}
53-
54-
private static String resourceFor(String platform) {
55-
return "/jmx/rules/" + platform + ".yaml";
56-
}
57-
58-
private static void addRulesForPlatform(String platform, MetricConfiguration conf) {
59-
String yamlResource = resourceFor(platform);
60-
try (InputStream inputStream =
61-
JmxMetricInsightInstaller.class.getResourceAsStream(yamlResource)) {
62-
if (inputStream != null) {
63-
JmxMetricInsight.getLogger().log(FINE, "Opened input stream {0}", yamlResource);
64-
RuleParser parserInstance = RuleParser.get();
65-
parserInstance.addMetricDefsTo(conf, inputStream, platform);
66-
} else {
67-
JmxMetricInsight.getLogger().log(INFO, "No support found for {0}", platform);
68-
}
69-
} catch (Exception e) {
70-
JmxMetricInsight.getLogger().warning(e.getMessage());
71-
}
72-
}
73-
74-
private static void buildFromDefaultRules(
75-
MetricConfiguration conf, ConfigProperties configProperties) {
76-
List<String> platforms = configProperties.getList("otel.jmx.target.system");
77-
for (String platform : platforms) {
78-
addRulesForPlatform(platform, conf);
79-
}
80-
}
81-
82-
private static void buildFromUserRules(
83-
MetricConfiguration conf, ConfigProperties configProperties) {
84-
List<String> configFiles = configProperties.getList("otel.jmx.config");
85-
for (String configFile : configFiles) {
86-
JmxMetricInsight.getLogger().log(FINE, "JMX config file name: {0}", configFile);
87-
RuleParser parserInstance = RuleParser.get();
88-
try (InputStream inputStream = Files.newInputStream(Paths.get(configFile))) {
89-
parserInstance.addMetricDefsTo(conf, inputStream, configFile);
90-
} catch (Exception e) {
91-
// yaml parsing errors are caught and logged inside of addMetricDefsTo
92-
// only file access related exceptions are expected here
93-
JmxMetricInsight.getLogger().warning(e.toString());
94-
}
95-
}
96-
}
97-
98-
private static MetricConfiguration buildMetricConfiguration(ConfigProperties configProperties) {
99-
MetricConfiguration metricConfiguration = new MetricConfiguration();
100-
101-
buildFromDefaultRules(metricConfiguration, configProperties);
102-
103-
buildFromUserRules(metricConfiguration, configProperties);
104-
105-
return metricConfiguration;
106-
}
10750
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.jmx;
7+
8+
import io.opentelemetry.api.OpenTelemetry;
9+
import io.opentelemetry.instrumentation.jmx.engine.JmxMetricInsight;
10+
import io.opentelemetry.instrumentation.jmx.engine.MetricConfiguration;
11+
import java.util.List;
12+
import java.util.function.Supplier;
13+
import javax.management.MBeanServerConnection;
14+
15+
public class JmxTelemetry {
16+
17+
private final JmxMetricInsight service;
18+
private final MetricConfiguration metricConfiguration;
19+
20+
public static JmxTelemetryBuilder builder(OpenTelemetry openTelemetry) {
21+
return new JmxTelemetryBuilder(openTelemetry);
22+
}
23+
24+
JmxTelemetry(
25+
OpenTelemetry openTelemetry, long discoveryDelayMs, MetricConfiguration metricConfiguration) {
26+
this.service = JmxMetricInsight.createService(openTelemetry, discoveryDelayMs);
27+
this.metricConfiguration = metricConfiguration;
28+
}
29+
30+
@SuppressWarnings("unused") // used by jmx-scraper with remote connection
31+
public void startRemote(Supplier<List<? extends MBeanServerConnection>> connections) {
32+
service.startRemote(metricConfiguration, connections);
33+
}
34+
35+
public void startLocal() {
36+
service.startLocal(metricConfiguration);
37+
}
38+
39+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.jmx;
7+
8+
import static java.util.logging.Level.FINE;
9+
import static java.util.logging.Level.INFO;
10+
11+
import com.google.errorprone.annotations.CanIgnoreReturnValue;
12+
import io.opentelemetry.api.OpenTelemetry;
13+
import io.opentelemetry.instrumentation.jmx.engine.MetricConfiguration;
14+
import io.opentelemetry.instrumentation.jmx.yaml.RuleParser;
15+
import java.io.InputStream;
16+
import java.nio.file.Files;
17+
import java.nio.file.Paths;
18+
import java.util.logging.Logger;
19+
20+
public class JmxTelemetryBuilder {
21+
22+
private static final Logger logger = Logger.getLogger(JmxTelemetryBuilder.class.getName());
23+
24+
private final OpenTelemetry openTelemetry;
25+
private final MetricConfiguration metricConfiguration;
26+
private long discoveryDelayMs;
27+
28+
JmxTelemetryBuilder(OpenTelemetry openTelemetry) {
29+
this.openTelemetry = openTelemetry;
30+
this.discoveryDelayMs = 0;
31+
this.metricConfiguration = new MetricConfiguration();
32+
}
33+
34+
@CanIgnoreReturnValue
35+
public JmxTelemetryBuilder beanDiscoveryDelay(long delayMs) {
36+
this.discoveryDelayMs = delayMs;
37+
return this;
38+
}
39+
40+
// TODO: can we use classloader as argument instead of baseClass?
41+
@CanIgnoreReturnValue
42+
public JmxTelemetryBuilder addClasspathRules(Class<?> baseClass, String targetId) {
43+
String yamlResource = String.format("/jmx/rules/%s.yaml", targetId);
44+
try (InputStream inputStream = baseClass.getResourceAsStream(yamlResource)) {
45+
if (inputStream != null) {
46+
logger.log(FINE, "Adding JMX config from classpath for {0}", yamlResource);
47+
RuleParser parserInstance = RuleParser.get();
48+
parserInstance.addMetricDefsTo(metricConfiguration, inputStream, targetId);
49+
} else {
50+
logger.log(INFO, "No support found for {0}", targetId);
51+
}
52+
} catch (Exception e) {
53+
logger.warning(e.getMessage());
54+
}
55+
return this;
56+
}
57+
58+
@CanIgnoreReturnValue
59+
public JmxTelemetryBuilder addCustomRules(String path) {
60+
logger.log(FINE, "Adding JMX config from file: {0}", path);
61+
RuleParser parserInstance = RuleParser.get();
62+
try (InputStream inputStream = Files.newInputStream(Paths.get(path))) {
63+
parserInstance.addMetricDefsTo(metricConfiguration, inputStream, path);
64+
} catch (Exception e) {
65+
// yaml parsing errors are caught and logged inside of addMetricDefsTo
66+
// only file access related exceptions are expected here
67+
logger.warning(e.toString());
68+
}
69+
return this;
70+
}
71+
72+
public JmxTelemetry build() {
73+
return new JmxTelemetry(openTelemetry, discoveryDelayMs, metricConfiguration);
74+
}
75+
}

instrumentation/jmx-metrics/library/src/main/java/io/opentelemetry/instrumentation/jmx/engine/JmxMetricInsight.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public void startLocal(MetricConfiguration conf) {
5252
* @param conf metric configuration
5353
* @param connections supplier for list of remote connections
5454
*/
55+
@SuppressWarnings("unused") // used by jmx-scraper with remote connection
5556
public void startRemote(
5657
MetricConfiguration conf, Supplier<List<? extends MBeanServerConnection>> connections) {
5758
start(conf, connections);

0 commit comments

Comments
 (0)