Skip to content

Commit 69b51e1

Browse files
authored
Adds Solr metrics gathering to jmx-metrics (#204)
* Adds Solr metrics gathering to jmx-metrics * Adds brackets to non standard Solr units * Shortens description of a JMX Solr metric * Adds minor tweaks to Solr JMX documentation
1 parent a1b43d9 commit 69b51e1

File tree

7 files changed

+445
-6
lines changed

7 files changed

+445
-6
lines changed

jmx-metrics/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,14 @@ capable of being specified via the `otel.jmx.target.system` property as a comma-
6767
mutually exclusive with `otel.jmx.groovy.script`. The currently supported target systems are:
6868

6969
| `otel.jmx.target.system` |
70-
| ------------------------ |
70+
|--------------------------|
7171
| [`jvm`](./docs/target-systems/jvm.md) |
72-
| [`activemq`](./docs/target-systems/activemq.md)|
72+
| [`activemq`](./docs/target-systems/activemq.md) |
7373
| [`cassandra`](./docs/target-systems/cassandra.md) |
7474
| [`kafka`](./docs/target-systems/kafka.md) |
7575
| [`kafka-consumer`](./docs/target-systems/kafka-consumer.md) |
7676
| [`kafka-producer`](./docs/target-systems/kafka-producer.md) |
77+
| [`solr`](./docs/target-systems/solr.md) |
7778
| [`tomcat`](./docs/target-systems/tomcat.md) |
7879

7980
### JMX Query Helpers
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Solr Metrics
2+
3+
The JMX Metric Gatherer provides built in Solr metric gathering capabilities.
4+
Details about using JMX with Solr can be found here: https://solr.apache.org/guide/6_6/using-jmx-with-solr.html
5+
6+
## Metrics
7+
8+
### Core Metrics
9+
10+
* Name: `solr.document.count`
11+
* Description: The total number of indexed documents.
12+
* Unit: `{documents}`
13+
* Labels: `core`
14+
* Instrument Type: ObservableLongUpDownCounter
15+
16+
17+
* Name: `solr.index.size`
18+
* Description: The total index size.
19+
* Unit: `by`
20+
* Labels: `core`
21+
* Instrument Type: ObservableLongUpDownCounter
22+
23+
24+
* Name: `solr.request.count`
25+
* Description: The number of queries made.
26+
* Unit: `{queries}`
27+
* Labels: `core`, `type`, `handler`
28+
* Instrument Type: ObservableLongCounter
29+
30+
31+
* Name: `solr.request.time.average`
32+
* Description: The average time of a query, based on Solr's histogram configuration.
33+
* Unit: `ms`
34+
* Labels: `core`, `type`, `handler`
35+
* Instrument Type: ObservableDoubleValue
36+
37+
38+
* Name: `solr.request.error.count`
39+
* Description: The number of queries resulting in an error.
40+
* Unit: `{queries}`
41+
* Labels: `core`, `type`, `handler`
42+
* Instrument Type: ObservableLongCounter
43+
44+
45+
* Name: `solr.request.timeout.count`
46+
* Description: The number of queries resulting in a timeout.
47+
* Unit: `{queries}`
48+
* Labels: `core`, `type`, `handler`
49+
* Instrument Type: ObservableLongCounter
50+
51+
52+
* Name: `solr.cache.eviction.count`
53+
* Description: The number of evictions from a cache.
54+
* Unit: `{evictions}`
55+
* Labels: `core`, `cache`
56+
* Instrument Type: ObservableLongCounter
57+
58+
59+
* Name: `solr.cache.hit.count`
60+
* Description: The number of hits from a cache.
61+
* Unit: `{hits}`
62+
* Labels: `core`, `cache`
63+
* Instrument Type: ObservableLongCounter
64+
65+
66+
* Name: `solr.cache.insert.count`
67+
* Description: The number of inserts from a cache.
68+
* Unit: `{inserts}`
69+
* Labels: `core`, `cache`
70+
* Instrument Type: ObservableLongCounter
71+
72+
73+
* Name: `solr.cache.lookup.count`
74+
* Description: The number of lookups from a cache.
75+
* Unit: `{lookups}`
76+
* Labels: `core`, `cache`
77+
* Instrument Type: ObservableLongCounter
78+
79+
80+
* Name: `solr.cache.size`
81+
* Description: The size of the cache occupied in memory.
82+
* Unit: `by`
83+
* Labels: `core`, `cache`
84+
* Instrument Type: ObservableLongUpDownCounter
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.contrib.jmxmetrics.target_systems;
7+
8+
import static org.assertj.core.api.Assertions.entry;
9+
10+
import io.opentelemetry.contrib.jmxmetrics.AbstractIntegrationTest;
11+
import io.opentelemetry.proto.metrics.v1.Metric;
12+
import java.time.Duration;
13+
import org.junit.jupiter.api.Test;
14+
import org.testcontainers.containers.GenericContainer;
15+
import org.testcontainers.containers.Network;
16+
import org.testcontainers.containers.wait.strategy.Wait;
17+
import org.testcontainers.junit.jupiter.Container;
18+
19+
class SolrIntegrationTest extends AbstractIntegrationTest {
20+
21+
SolrIntegrationTest() {
22+
super(/* configFromStdin= */ false, "target-systems/solr.properties");
23+
}
24+
25+
@Container
26+
GenericContainer<?> solr =
27+
new GenericContainer<>("solr:8.8.2")
28+
.withNetwork(Network.SHARED)
29+
.withEnv("LOCAL_JMX", "no")
30+
.withEnv("ENABLE_REMOTE_JMX_OPTS", "true")
31+
.withEnv("RMI_PORT", "9990")
32+
.withCommand("solr-precreate", "gettingstarted")
33+
.withNetworkAliases("solr")
34+
.withExposedPorts(9990)
35+
.withStartupTimeout(Duration.ofMinutes(2))
36+
.waitingFor(Wait.forListeningPort());
37+
38+
@Test
39+
void endToEnd() {
40+
waitAndAssertMetrics(
41+
metric ->
42+
assertSumWithAttributes(
43+
metric,
44+
"solr.document.count",
45+
"The total number of indexed documents.",
46+
"{documents}",
47+
attrs -> attrs.containsOnly(entry("core", "gettingstarted"))),
48+
metric ->
49+
assertSumWithAttributes(
50+
metric,
51+
"solr.index.size",
52+
"The total index size.",
53+
"by",
54+
attrs -> attrs.containsOnly(entry("core", "gettingstarted"))),
55+
metric ->
56+
assertSolrRequestSumMetric(
57+
metric, "solr.request.count", "The number of queries made.", "{queries}"),
58+
metric ->
59+
assertSolrRequestGaugeMetric(
60+
metric,
61+
"solr.request.time.average",
62+
"The average time of a query, based on Solr's histogram configuration.",
63+
"ms"),
64+
metric ->
65+
assertSolrRequestSumMetric(
66+
metric,
67+
"solr.request.error.count",
68+
"The number of queries resulting in an error.",
69+
"{queries}"),
70+
metric ->
71+
assertSolrRequestSumMetric(
72+
metric,
73+
"solr.request.timeout.count",
74+
"The number of queries resulting in a timeout.",
75+
"{queries}"),
76+
metric ->
77+
assertSolrCacheSumMetric(
78+
metric,
79+
"solr.cache.eviction.count",
80+
"The number of evictions from a cache.",
81+
"{evictions}"),
82+
metric ->
83+
assertSolrCacheSumMetric(
84+
metric, "solr.cache.hit.count", "The number of hits for a cache.", "{hits}"),
85+
metric ->
86+
assertSolrCacheSumMetric(
87+
metric,
88+
"solr.cache.insert.count",
89+
"The number of inserts to a cache.",
90+
"{inserts}"),
91+
metric ->
92+
assertSolrCacheSumMetric(
93+
metric,
94+
"solr.cache.lookup.count",
95+
"The number of lookups to a cache.",
96+
"{lookups}"),
97+
metric ->
98+
assertSolrCacheSumMetric(
99+
metric, "solr.cache.size", "The size of the cache occupied in memory.", "by"));
100+
}
101+
102+
private void assertSolrRequestSumMetric(
103+
Metric metric, String name, String description, String unit) {
104+
assertSumWithAttributes(
105+
metric,
106+
name,
107+
description,
108+
unit,
109+
attrs ->
110+
attrs.containsExactly(
111+
entry("core", "gettingstarted"), entry("handler", "/get"), entry("type", "QUERY")),
112+
attrs ->
113+
attrs.containsExactly(
114+
entry("core", "gettingstarted"),
115+
entry("handler", "/update/csv"),
116+
entry("type", "UPDATE")),
117+
attrs ->
118+
attrs.containsExactly(
119+
entry("core", "gettingstarted"),
120+
entry("handler", "/query"),
121+
entry("type", "QUERY")),
122+
attrs ->
123+
attrs.containsExactly(
124+
entry("core", "gettingstarted"),
125+
entry("handler", "/graph"),
126+
entry("type", "QUERY")),
127+
attrs ->
128+
attrs.containsExactly(
129+
entry("core", "gettingstarted"),
130+
entry("handler", "update"),
131+
entry("type", "UPDATE")),
132+
attrs ->
133+
attrs.containsExactly(
134+
entry("core", "gettingstarted"),
135+
entry("handler", "/update"),
136+
entry("type", "UPDATE")),
137+
attrs ->
138+
attrs.containsExactly(
139+
entry("core", "gettingstarted"),
140+
entry("handler", "/debug/dump"),
141+
entry("type", "QUERY")),
142+
attrs ->
143+
attrs.containsExactly(
144+
entry("core", "gettingstarted"),
145+
entry("handler", "/update/json"),
146+
entry("type", "UPDATE")),
147+
attrs ->
148+
attrs.containsExactly(
149+
entry("core", "gettingstarted"),
150+
entry("handler", "/stream"),
151+
entry("type", "QUERY")),
152+
attrs ->
153+
attrs.containsExactly(
154+
entry("core", "gettingstarted"),
155+
entry("handler", "/export"),
156+
entry("type", "QUERY")),
157+
attrs ->
158+
attrs.containsExactly(
159+
entry("core", "gettingstarted"),
160+
entry("handler", "/update/json/docs"),
161+
entry("type", "UPDATE")),
162+
attrs ->
163+
attrs.containsExactly(
164+
entry("core", "gettingstarted"), entry("handler", "/sql"), entry("type", "QUERY")),
165+
attrs ->
166+
attrs.containsExactly(
167+
entry("core", "gettingstarted"),
168+
entry("handler", "/select"),
169+
entry("type", "QUERY")));
170+
}
171+
172+
private void assertSolrRequestGaugeMetric(
173+
Metric metric, String name, String description, String unit) {
174+
assertGaugeWithAttributes(
175+
metric,
176+
name,
177+
description,
178+
unit,
179+
attrs ->
180+
attrs.containsExactly(
181+
entry("core", "gettingstarted"), entry("handler", "/get"), entry("type", "QUERY")),
182+
attrs ->
183+
attrs.containsExactly(
184+
entry("core", "gettingstarted"),
185+
entry("handler", "/update/csv"),
186+
entry("type", "UPDATE")),
187+
attrs ->
188+
attrs.containsExactly(
189+
entry("core", "gettingstarted"),
190+
entry("handler", "/query"),
191+
entry("type", "QUERY")),
192+
attrs ->
193+
attrs.containsExactly(
194+
entry("core", "gettingstarted"),
195+
entry("handler", "/graph"),
196+
entry("type", "QUERY")),
197+
attrs ->
198+
attrs.containsExactly(
199+
entry("core", "gettingstarted"),
200+
entry("handler", "update"),
201+
entry("type", "UPDATE")),
202+
attrs ->
203+
attrs.containsExactly(
204+
entry("core", "gettingstarted"),
205+
entry("handler", "/update"),
206+
entry("type", "UPDATE")),
207+
attrs ->
208+
attrs.containsExactly(
209+
entry("core", "gettingstarted"),
210+
entry("handler", "/debug/dump"),
211+
entry("type", "QUERY")),
212+
attrs ->
213+
attrs.containsExactly(
214+
entry("core", "gettingstarted"),
215+
entry("handler", "/update/json"),
216+
entry("type", "UPDATE")),
217+
attrs ->
218+
attrs.containsExactly(
219+
entry("core", "gettingstarted"),
220+
entry("handler", "/stream"),
221+
entry("type", "QUERY")),
222+
attrs ->
223+
attrs.containsExactly(
224+
entry("core", "gettingstarted"),
225+
entry("handler", "/export"),
226+
entry("type", "QUERY")),
227+
attrs ->
228+
attrs.containsExactly(
229+
entry("core", "gettingstarted"),
230+
entry("handler", "/update/json/docs"),
231+
entry("type", "UPDATE")),
232+
attrs ->
233+
attrs.containsExactly(
234+
entry("core", "gettingstarted"), entry("handler", "/sql"), entry("type", "QUERY")),
235+
attrs ->
236+
attrs.containsExactly(
237+
entry("core", "gettingstarted"),
238+
entry("handler", "/select"),
239+
entry("type", "QUERY")));
240+
}
241+
242+
private void assertSolrCacheSumMetric(
243+
Metric metric, String name, String description, String unit) {
244+
assertSumWithAttributes(
245+
metric,
246+
name,
247+
description,
248+
unit,
249+
attrs ->
250+
attrs.containsExactly(entry("core", "gettingstarted"), entry("cache", "searcher")));
251+
}
252+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
otel.jmx.interval.milliseconds = 3000
2+
otel.metrics.exporter = otlp
3+
otel.jmx.service.url = service:jmx:rmi:///jndi/rmi://solr:9990/jmxrmi
4+
otel.jmx.target.system = solr
5+
6+
# these will be overridden by cmd line
7+
otel.exporter.otlp.endpoint = http://host.testcontainers.internal

jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/JmxConfig.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,14 @@ class JmxConfig {
3434

3535
static final List<String> AVAILABLE_TARGET_SYSTEMS =
3636
Arrays.asList(
37-
"activemq", "cassandra", "jvm", "kafka", "kafka-consumer", "kafka-producer", "tomcat");
37+
"activemq",
38+
"cassandra",
39+
"jvm",
40+
"kafka",
41+
"kafka-consumer",
42+
"kafka-producer",
43+
"solr",
44+
"tomcat");
3845

3946
final String serviceUrl;
4047
final String groovyScript;

0 commit comments

Comments
 (0)