Issue 7212 - Allow multiple YAML configuration files for JMX rules (#7284)

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
This commit is contained in:
Peter Findeisen 2022-11-24 02:20:08 -08:00 committed by GitHub
parent 16272753cc
commit c4ceaaa8d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 18 deletions

View File

@ -30,20 +30,20 @@ No targets are enabled by default. The supported target environments are listed
- [wildfly](wildfly.md)
- [hadoop](hadoop.md)
## Configuration File
## Configuration Files
To provide your own metric definitions, create a YAML configuration file, and specify its location using the `otel.jmx.config` property. For example
To provide your own metric definitions, create one or more YAML configuration files, and specify their location using the `otel.jmx.config` property. Absolute or relative pathnames can be specified. For example
```bash
$ java -javaagent:path/to/opentelemetry-javaagent.jar \
-Dotel.jmx.config=path/to/config_file.yaml \
-Dotel.jmx.config=path/to/config_file.yaml,more_rules.yaml \
... \
-jar myapp.jar
```
### Basic Syntax
The configuration file can contain multiple entries (which we call _rules_), defining a number of metrics. Each rule must identify a set of MBeans and the name of the MBean attribute to query, along with additional information on how to report the values. Let's look at a simple example.
Each configuration file can contain multiple entries (which we call _rules_), defining a number of metrics. Each rule must identify a set of MBeans and the name of the MBean attribute to query, along with additional information on how to report the values. Let's look at a simple example.
```yaml
---

View File

@ -16,9 +16,10 @@ import io.opentelemetry.instrumentation.jmx.yaml.RuleParser;
import io.opentelemetry.javaagent.extension.AgentListener;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
/** An {@link AgentListener} that enables JMX metrics during agent startup. */
@AutoService(AgentListener.class)
@ -59,7 +60,7 @@ public class JmxMetricInsightInstaller implements AgentListener {
if (inputStream != null) {
JmxMetricInsight.getLogger().log(FINE, "Opened input stream {0}", yamlResource);
RuleParser parserInstance = RuleParser.get();
parserInstance.addMetricDefsTo(conf, inputStream);
parserInstance.addMetricDefsTo(conf, inputStream, platform);
} else {
JmxMetricInsight.getLogger().log(INFO, "No support found for {0}", platform);
}
@ -70,9 +71,7 @@ public class JmxMetricInsightInstaller implements AgentListener {
private static void buildFromDefaultRules(
MetricConfiguration conf, ConfigProperties configProperties) {
String targetSystem = configProperties.getString("otel.jmx.target.system", "");
String[] platforms = targetSystem.isEmpty() ? new String[0] : targetSystem.split(",");
List<String> platforms = configProperties.getList("otel.jmx.target.system");
for (String platform : platforms) {
addRulesForPlatform(platform, conf);
}
@ -80,14 +79,16 @@ public class JmxMetricInsightInstaller implements AgentListener {
private static void buildFromUserRules(
MetricConfiguration conf, ConfigProperties configProperties) {
String jmxDir = configProperties.getString("otel.jmx.config");
if (jmxDir != null) {
JmxMetricInsight.getLogger().log(FINE, "JMX config file name: {0}", jmxDir);
List<String> configFiles = configProperties.getList("otel.jmx.config");
for (String configFile : configFiles) {
JmxMetricInsight.getLogger().log(FINE, "JMX config file name: {0}", configFile);
RuleParser parserInstance = RuleParser.get();
try (InputStream inputStream = Files.newInputStream(new File(jmxDir.trim()).toPath())) {
parserInstance.addMetricDefsTo(conf, inputStream);
try (InputStream inputStream = Files.newInputStream(Paths.get(configFile))) {
parserInstance.addMetricDefsTo(conf, inputStream, configFile);
} catch (Exception e) {
JmxMetricInsight.getLogger().warning(e.getMessage());
// yaml parsing errors are caught and logged inside of addMetricDefsTo
// only file access related exceptions are expected here
JmxMetricInsight.getLogger().warning(e.toString());
}
}
}

View File

@ -51,17 +51,22 @@ public class RuleParser {
*
* @param conf the metric configuration
* @param is the InputStream with the YAML rules
* @param id identifier of the YAML ruleset, such as a filename
*/
public void addMetricDefsTo(MetricConfiguration conf, InputStream is) {
public void addMetricDefsTo(MetricConfiguration conf, InputStream is, String id) {
try {
JmxConfig config = loadConfig(is);
if (config != null) {
logger.log(INFO, "Found {0} metric rules", config.getRules().size());
logger.log(
INFO, "{0}: found {1} metric rules", new Object[] {id, config.getRules().size()});
config.addMetricDefsTo(conf);
}
} catch (Exception exception) {
logger.log(WARNING, "Failed to parse YAML rules: " + rootCause(exception));
logger.log(
WARNING,
"Failed to parse YAML rules from {0}: {1}",
new Object[] {id, rootCause(exception)});
// It is essential that the parser exception is made visible to the user.
// It contains contextual information about any syntax issues found by the parser.
logger.log(WARNING, exception.toString());