Skip to content

Commit 3f2f151

Browse files
committed
add state mapping + tests
1 parent d1a195b commit 3f2f151

File tree

2 files changed

+224
-0
lines changed

2 files changed

+224
-0
lines changed
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.jmx.yaml;
7+
8+
import com.google.errorprone.annotations.CanIgnoreReturnValue;
9+
import java.util.Collections;
10+
import java.util.HashMap;
11+
import java.util.HashSet;
12+
import java.util.Map;
13+
import java.util.Set;
14+
import javax.annotation.Nullable;
15+
16+
/** State mapping for "state metrics", contains: */
17+
public class StateMapping {
18+
19+
private static final StateMapping EMPTY =
20+
new StateMapping(null, Collections.emptyMap(), Collections.emptySet());
21+
22+
/** default state to map entries that are not part of {@link #stateMapping} */
23+
private final String defaultStateKey;
24+
25+
/** maps values (keys) to their respective state (value) */
26+
private final Map<String, String> stateMapping;
27+
28+
/** set of all states, including {@link #defaultStateKey} */
29+
private final Set<String> stateKeys;
30+
31+
private StateMapping(
32+
String defaultState, Map<String, String> stateMapping, Set<String> stateKeys) {
33+
this.defaultStateKey = defaultState;
34+
this.stateMapping = stateMapping;
35+
this.stateKeys = stateKeys;
36+
}
37+
38+
/**
39+
* @return {@literal true} when state mapping is empty, {@literal false} otherwise
40+
*/
41+
public boolean isEmpty() {
42+
return stateKeys.isEmpty();
43+
}
44+
45+
/**
46+
* get state keys
47+
*
48+
* @return set of state keys, including the default one
49+
*/
50+
public Set<String> getStateKeys() {
51+
return stateKeys;
52+
}
53+
54+
/**
55+
* get default state key
56+
*
57+
* @return default state key, {@literal null} when empty
58+
*/
59+
@Nullable
60+
public String getDefaultStateKey() {
61+
return defaultStateKey;
62+
}
63+
64+
/**
65+
* Get mapped state value
66+
*
67+
* @param rawValue raw state value from JMX attribute
68+
* @return mapped state value from raw value, default value or {@literal null} when empty
69+
*/
70+
@Nullable
71+
public String getStateValue(String rawValue) {
72+
String value = stateMapping.get(rawValue);
73+
if (value == null) {
74+
value = defaultStateKey;
75+
}
76+
return value;
77+
}
78+
79+
public static Builder builder() {
80+
return new Builder();
81+
}
82+
83+
/**
84+
* Empty instance
85+
*
86+
* @return an empty {@link StateMapping} instance
87+
*/
88+
public static StateMapping empty() {
89+
return EMPTY;
90+
}
91+
92+
public static class Builder {
93+
94+
private String defaultState;
95+
private final Map<String, String> valueMapping;
96+
private final Set<String> stateKeys;
97+
98+
private Builder() {
99+
this.valueMapping = new HashMap<>();
100+
this.stateKeys = new HashSet<>();
101+
}
102+
103+
/**
104+
* Adds default state key
105+
*
106+
* @param state state key
107+
* @return this
108+
*/
109+
@CanIgnoreReturnValue
110+
public Builder withDefaultState(String state) {
111+
if (defaultState != null) {
112+
throw new IllegalStateException("default state already set");
113+
}
114+
defaultState = state;
115+
stateKeys.add(defaultState);
116+
return this;
117+
}
118+
119+
/**
120+
* Adds a mapped state value
121+
*
122+
* @param value raw value to be mapped
123+
* @param state state value to map raw value to
124+
* @return this
125+
*/
126+
@CanIgnoreReturnValue
127+
public Builder withMappedValue(String value, String state) {
128+
String currentMapping = valueMapping.putIfAbsent(value, state);
129+
if (currentMapping != null) {
130+
throw new IllegalStateException(value + " already mapped to " + currentMapping);
131+
}
132+
stateKeys.add(state);
133+
return this;
134+
}
135+
136+
StateMapping build() {
137+
if (stateKeys.isEmpty()) {
138+
return EMPTY;
139+
}
140+
141+
if (defaultState == null) {
142+
throw new IllegalStateException("missing default state");
143+
}
144+
145+
return new StateMapping(defaultState, valueMapping, stateKeys);
146+
}
147+
}
148+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.jmx.yaml;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
10+
11+
import org.junit.jupiter.api.Test;
12+
13+
class StateMappingTest {
14+
15+
@Test
16+
void empty() {
17+
StateMapping empty = StateMapping.builder().build();
18+
assertThat(empty).isSameAs(StateMapping.empty());
19+
20+
assertThat(empty.isEmpty()).isTrue();
21+
assertThat(empty.getDefaultStateKey()).isNull();
22+
assertThat(empty.getStateKeys()).isEmpty();
23+
assertThat(empty.getStateValue("any")).isNull();
24+
}
25+
26+
@Test
27+
void onlyDefault() {
28+
StateMapping mapping = StateMapping.builder().withDefaultState("default").build();
29+
30+
assertThat(mapping.getDefaultStateKey()).isEqualTo("default");
31+
assertThat(mapping.getStateKeys()).containsExactly("default");
32+
assertThat(mapping.getStateValue("other")).isEqualTo("default");
33+
}
34+
35+
@Test
36+
void tryDuplicateDefault() {
37+
assertThatThrownBy(
38+
() ->
39+
StateMapping.builder().withDefaultState("default").withDefaultState("default").build());
40+
}
41+
42+
@Test
43+
void tryMissingDefault() {
44+
assertThatThrownBy(() -> StateMapping.builder().withMappedValue("value", "state").build());
45+
}
46+
47+
@Test
48+
void mapValues() {
49+
StateMapping mapping =
50+
StateMapping.builder()
51+
.withDefaultState("unknown")
52+
.withMappedValue("value1", "ok")
53+
.withMappedValue("value1bis", "ok")
54+
.withMappedValue("value2", "ko")
55+
.build();
56+
57+
assertThat(mapping.getStateKeys()).hasSize(3).contains("ok", "ko", "unknown");
58+
assertThat(mapping.getDefaultStateKey()).isEqualTo("unknown");
59+
60+
assertThat(mapping.getStateValue("value1")).isEqualTo("ok");
61+
assertThat(mapping.getStateValue("value1bis")).isEqualTo("ok");
62+
assertThat(mapping.getStateValue("value2")).isEqualTo("ko");
63+
assertThat(mapping.getStateValue("other")).isEqualTo("unknown");
64+
}
65+
66+
@Test
67+
void tryDuplicateMappings() {
68+
assertThatThrownBy(
69+
() ->
70+
StateMapping.builder()
71+
.withDefaultState("default")
72+
.withMappedValue("value", "state1")
73+
.withMappedValue("value", "state2")
74+
.build());
75+
}
76+
}

0 commit comments

Comments
 (0)