Skip to content

Commit e5ff7c5

Browse files
committed
implement new syntax
1 parent 679c460 commit e5ff7c5

File tree

6 files changed

+91
-45
lines changed

6 files changed

+91
-45
lines changed

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ public class MetricInfo {
1919
public enum Type {
2020
COUNTER,
2121
UPDOWNCOUNTER,
22-
GAUGE
22+
GAUGE,
23+
/** state metric captured as updowncounter */
24+
STATE
2325
}
2426

2527
// How to report the metric using OpenTelemetry API
@@ -44,21 +46,22 @@ public MetricInfo(
4446
this.type = type == null ? Type.GAUGE : type;
4547
}
4648

47-
String getMetricName() {
49+
public String getMetricName() {
4850
return metricName;
4951
}
5052

5153
@Nullable
52-
String getDescription() {
54+
public String getDescription() {
5355
return description;
5456
}
5557

5658
@Nullable
57-
String getUnit() {
59+
public String getUnit() {
5860
return unit;
5961
}
6062

61-
Type getType() {
63+
public Type getType() {
6264
return type;
6365
}
66+
6467
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,13 @@ void enrollExtractor(
120120
}
121121
logger.log(INFO, "Created Gauge for {0}", metricName);
122122
}
123+
break;
124+
// CHECKSTYLE:OFF
125+
case STATE:
126+
{
127+
// CHECKSTYLE:ON
128+
throw new IllegalStateException("state metrics should not be registered");
129+
}
123130
}
124131
}
125132

instrumentation/jmx-metrics/library/src/main/java/io/opentelemetry/instrumentation/jmx/yaml/JmxRule.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,14 @@ protected Number extractNumericalAttribute(
228228
}
229229
};
230230

231+
// state metric are always up/down counters
232+
MetricInfo stateMetricInfo = new MetricInfo(metricInfo.getMetricName(),
233+
metricInfo.getDescription(), metricInfo.getUnit(), MetricInfo.Type.UPDOWNCOUNTER);
234+
231235
extractors.add(
232236
new MetricExtractor(
233237
stateMetricExtractor,
234-
metricInfo,
238+
stateMetricInfo,
235239
stateMetricAttributes.toArray(new MetricAttribute[0])));
236240
}
237241
return extractors;

instrumentation/jmx-metrics/library/src/main/java/io/opentelemetry/instrumentation/jmx/yaml/MetricStructure.java

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,29 @@
2020
* <li>the metric attributes
2121
* <li>the unit
2222
*
23-
* <p>Known subclasses are {@link JmxRule} and {@link Metric}.
23+
* <p>Known subclasses are {@link JmxRule} and {@link Metric}.
2424
*/
2525
abstract class MetricStructure {
2626

2727
// Used by the YAML parser
28+
//
2829
// type: TYPE
2930
// metricAttribute:
3031
// KEY1: SPECIFICATION1
3132
// KEY2: SPECIFICATION2
3233
// unit: UNIT
33-
// stateMapping:
34-
// state1: [a,b]
35-
// state2: c
36-
// state3: '*'
34+
//
35+
// For state metrics
36+
//
37+
// type: state
38+
// metricAttribute:
39+
// KEY1: SPECIFICATION1
40+
// state:
41+
// state1: [a,b]
42+
// state2: c
43+
// state3: '*'
3744

38-
private Map<String, String> metricAttribute;
45+
private Map<String, Object> metricAttribute;
3946
private StateMapping stateMapping = StateMapping.empty();
4047
private static final String STATE_MAPPING_WILDCARD = "*";
4148
private String unit;
@@ -96,20 +103,20 @@ private String validateUnit(String unit) {
96103
}
97104

98105
/**
99-
* When the YAML parser sets the metric attributes (as Strings), convert them immediately to
106+
* When the YAML parser sets the metric attributes, convert them immediately to
100107
* MetricAttribute objects. Any errors during conversion will show in the context of the parsed
101108
* YAML file.
102109
*
103110
* @param map the mapping of metric attribute keys to evaluating snippets
104111
*/
105-
public void setMetricAttribute(Map<String, String> map) {
112+
public void setMetricAttribute(Map<String, Object> map) {
106113
this.metricAttribute = map;
107114
// pre-build the MetricAttributes
108115
this.metricAttributes = addMetricAttributes(map);
109116
}
110117

111118
// Used only for testing
112-
public Map<String, String> getMetricAttribute() {
119+
public Map<String, Object> getMetricAttribute() {
113120
return metricAttribute;
114121
}
115122

@@ -127,27 +134,26 @@ protected void requireNonEmpty(String s, String msg) {
127134
}
128135
}
129136

130-
private List<MetricAttribute> addMetricAttributes(Map<String, String> metricAttributeMap) {
137+
private List<MetricAttribute> addMetricAttributes(Map<String, Object> metricAttributeMap) {
131138

132139
List<MetricAttribute> list = new ArrayList<>();
133-
boolean hasStateAttribute = false;
134140
for (String key : metricAttributeMap.keySet()) {
135-
String target = metricAttributeMap.get(key);
136-
if (target == null) {
141+
Object value = metricAttributeMap.get(key);
142+
if (value == null) {
137143
throw new IllegalStateException("nothing specified for metric attribute key '" + key + "'");
138144
}
139-
MetricAttribute attribute = buildMetricAttribute(key, target.trim());
140-
if (attribute.isStateAttribute()) {
141-
if (hasStateAttribute) {
142-
throw new IllegalArgumentException("only one state attribute is allowed");
143-
}
144-
hasStateAttribute = true;
145+
146+
MetricAttribute attribute;
147+
if (value instanceof String) {
148+
attribute = buildMetricAttribute(key, ((String) value).trim());
149+
} else if (value instanceof Map) {
150+
attribute = buildStateMetricAttribute(key, (Map<?, ?>) value);
151+
} else {
152+
throw new IllegalArgumentException("unexpected metric attribute: " + value);
145153
}
154+
146155
list.add(attribute);
147156
}
148-
if (hasStateAttribute && stateMapping.isEmpty()) {
149-
throw new IllegalArgumentException("statekey() usage without stateMapping");
150-
}
151157
return list;
152158
}
153159

@@ -156,7 +162,6 @@ private static MetricAttribute buildMetricAttribute(String key, String target) {
156162
// - param(STRING)
157163
// - beanattr(STRING)
158164
// - const(STRING)
159-
// - statekey()
160165
// where STRING is the name of the corresponding parameter key, attribute name,
161166
// or the direct value to use
162167
int k = target.indexOf(')');
@@ -178,14 +183,43 @@ private static MetricAttribute buildMetricAttribute(String key, String target) {
178183
String constantValue = target.substring(6, k).trim();
179184
return new MetricAttribute(key, MetricAttributeExtractor.fromConstant(constantValue));
180185
}
181-
} else if (target.equals("statekey()")) {
182-
return new MetricAttribute(key, null);
183186
}
184187

185188
String msg = "Invalid metric attribute specification for '" + key + "': " + target;
186189
throw new IllegalArgumentException(msg);
187190
}
188191

192+
private MetricAttribute buildStateMetricAttribute(String key, Map<?, ?> stateMap) {
193+
if (stateMap.isEmpty()) {
194+
throw new IllegalArgumentException("state map is empty for key " + key);
195+
}
196+
if (!stateMapping.isEmpty()) {
197+
throw new IllegalStateException("state map already set for " + key);
198+
}
199+
200+
StateMapping.Builder builder = StateMapping.builder();
201+
202+
for (Map.Entry<?, ?> entry : stateMap.entrySet()) {
203+
if (!(entry.getKey() instanceof String)) {
204+
throw new IllegalArgumentException("unexpected state map key: " + entry.getKey());
205+
}
206+
String stateKey = (String) entry.getKey();
207+
Object objValue = entry.getValue();
208+
if (objValue instanceof String) {
209+
addMappedValue(builder, (String) objValue, stateKey);
210+
} else if (objValue instanceof List) {
211+
for (Object listEntry : (List<?>) objValue) {
212+
if (!(listEntry instanceof String)) {
213+
throw new IllegalArgumentException("unexpected state list value: " + stateKey);
214+
}
215+
addMappedValue(builder, (String) listEntry, stateKey);
216+
}
217+
}
218+
}
219+
stateMapping = builder.build();
220+
return new MetricAttribute(key, null);
221+
}
222+
189223
public StateMapping getStateMapping() {
190224
return stateMapping;
191225
}

instrumentation/jmx-metrics/library/src/main/java/io/opentelemetry/instrumentation/jmx/yaml/RuleParser.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,6 @@ private static void parseMetricStructure(
140140
out.setStateMapping(stateMapping);
141141
}
142142

143-
Map<String, String> metricAttribute =
144-
(Map<String, String>) metricStructureYaml.remove("metricAttribute");
145-
if (metricAttribute != null) {
146-
out.setMetricAttribute(metricAttribute);
147-
}
148143
String unit = (String) metricStructureYaml.remove("unit");
149144
if (unit != null) {
150145
out.setUnit(unit);

instrumentation/jmx-metrics/library/src/test/java/io/opentelemetry/instrumentation/jmx/engine/RuleParserTest.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -367,16 +367,16 @@ void testConf8() throws Exception {
367367
+ " - bean: my-test:type=9\n"
368368
+ " mapping:\n"
369369
+ " jmxStateAttribute:\n"
370-
+ " type: updowncounter\n"
370+
+ " type: state\n"
371371
+ " metric: state_metric\n"
372-
+ " stateMapping:\n" // --> implies it's a state metric, value is either 0 or 1
373-
+ " ok: STARTED\n" // as simple string
374-
+ " failed: [STOPPED,FAILED]\n" // as array of strings
375-
+ " degraded: '*'\n" // wildcard value for default
376372
+ " metricAttribute:\n"
377-
+ " state: statekey()\n" // --> only one state attribute allowed
373+
+ " state_attribute: \n" // --> only one state attribute allowed
374+
+ " ok: STARTED\n" // as simple string
375+
+ " failed: [STOPPED,FAILED]\n" // as array of strings
376+
+ " degraded: '*'\n" // wildcard value for default
378377
+ "";
379378

379+
380380
@Test
381381
void testStateMetricConf() throws Exception {
382382
JmxConfig config = parseConf(CONF9);
@@ -388,7 +388,7 @@ void testStateMetricConf() throws Exception {
388388
JmxRule jmxRule = rules.get(0);
389389
assertThat(jmxRule.getBean()).isEqualTo("my-test:type=9");
390390
Metric metric = jmxRule.getMapping().get("jmxStateAttribute");
391-
assertThat(metric.getMetricType()).isEqualTo(MetricInfo.Type.UPDOWNCOUNTER);
391+
assertThat(metric.getMetricType()).isEqualTo(MetricInfo.Type.STATE);
392392

393393
assertThat(metric.getStateMapping().isEmpty()).isFalse();
394394
assertThat(metric.getStateMapping().getStateKeys()).contains("ok", "failed", "degraded");
@@ -398,7 +398,10 @@ void testStateMetricConf() throws Exception {
398398
assertThat(metric.getStateMapping().getStateValue("FAILED")).isEqualTo("failed");
399399
assertThat(metric.getStateMapping().getStateValue("OTHER")).isEqualTo("degraded");
400400

401-
assertThat(metric.getMetricAttribute()).containsEntry("state", "statekey()");
401+
Map<String, Object> metricAttributeMap = metric.getMetricAttribute();
402+
assertThat(metricAttributeMap).containsKey("state_attribute").hasSize(1);
403+
assertThat(metricAttributeMap.get("state_attribute")).isInstanceOf(Map.class);
404+
402405

403406
ObjectName objectName = new ObjectName(jmxRule.getBean());
404407
MBeanServerConnection mockConnection = mock(MBeanServerConnection.class);
@@ -426,7 +429,7 @@ void testStateMetricConf() throws Exception {
426429

427430
assertThat(me.getAttributes()).hasSize(1);
428431
MetricAttribute stateAttribute = me.getAttributes()[0];
429-
assertThat(stateAttribute.getAttributeName()).isEqualTo("state");
432+
assertThat(stateAttribute.getAttributeName()).isEqualTo("state_attribute");
430433
String stateAttributeValue =
431434
stateAttribute.acquireAttributeValue(mockConnection, objectName);
432435

0 commit comments

Comments
 (0)