Skip to content

Commit 6377352

Browse files
GaganjunejaGagan Juneja
andcommitted
Adds support to provide tags with value in Gauge metric (opensearch-project#13994)
* Adds support to provide tags with value in Gauge metric Signed-off-by: Gagan Juneja <[email protected]> * Adds support to provide tags with value in Gauge metric Signed-off-by: Gagan Juneja <[email protected]> * Adds support to provide tags with value in Gauge metric Signed-off-by: Gagan Juneja <[email protected]> * Adds build issue Signed-off-by: Gagan Juneja <[email protected]> * Fix compilation issue Signed-off-by: Gagan Juneja <[email protected]> * Empty-Commit Signed-off-by: Gagan Juneja <[email protected]> * Empty-Commit Signed-off-by: Gagan Juneja <[email protected]> --------- Signed-off-by: Gagan Juneja <[email protected]> Signed-off-by: Gagan Juneja <[email protected]> Co-authored-by: Gagan Juneja <[email protected]>
1 parent 2a8ffba commit 6377352

File tree

11 files changed

+187
-0
lines changed

11 files changed

+187
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
4444
- Add ability for Boolean and date field queries to run when only doc_values are enabled ([#11650](https://github.com/opensearch-project/OpenSearch/pull/11650))
4545
- Refactor implementations of query phase searcher, allow QueryCollectorContext to have zero collectors ([#13481](https://github.com/opensearch-project/OpenSearch/pull/13481))
4646
- Adds support to inject telemetry instances to plugins ([#13636](https://github.com/opensearch-project/OpenSearch/pull/13636))
47+
- Adds support to provide tags with value in Gauge metric. ([#13994](https://github.com/opensearch-project/OpenSearch/pull/13994))
4748
- Move cache removal notifications outside lru lock ([#14017](https://github.com/opensearch-project/OpenSearch/pull/14017))
4849

4950
### Deprecated

libs/telemetry/src/main/java/org/opensearch/telemetry/metrics/DefaultMetricsRegistry.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ public Closeable createGauge(String name, String description, String unit, Suppl
4848
return metricsTelemetry.createGauge(name, description, unit, valueProvider, tags);
4949
}
5050

51+
@Override
52+
public Closeable createGauge(String name, String description, String unit, Supplier<TaggedMeasurement> value) {
53+
return metricsTelemetry.createGauge(name, description, unit, value);
54+
}
55+
5156
@Override
5257
public void close() throws IOException {
5358
metricsTelemetry.close();

libs/telemetry/src/main/java/org/opensearch/telemetry/metrics/MetricsRegistry.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,16 @@ public interface MetricsRegistry extends Closeable {
6363
*/
6464
Closeable createGauge(String name, String description, String unit, Supplier<Double> valueProvider, Tags tags);
6565

66+
/**
67+
* Creates the Observable Gauge type of Metric. Where the value provider will be called at a certain frequency
68+
* to capture the value.
69+
*
70+
* @param name name of the observable gauge.
71+
* @param description any description about the metric.
72+
* @param unit unit of the metric.
73+
* @param value value provider.
74+
* @return closeable to dispose/close the Gauge metric.
75+
*/
76+
Closeable createGauge(String name, String description, String unit, Supplier<TaggedMeasurement> value);
77+
6678
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.telemetry.metrics;
10+
11+
import org.opensearch.common.annotation.ExperimentalApi;
12+
import org.opensearch.telemetry.metrics.tags.Tags;
13+
14+
/**
15+
* Observable Measurement for the Asynchronous instruments.
16+
* @opensearch.experimental
17+
*/
18+
@ExperimentalApi
19+
public final class TaggedMeasurement {
20+
private final Double value;
21+
private final Tags tags;
22+
23+
/**
24+
* Factory method to create the {@link TaggedMeasurement} object.
25+
* @param value value.
26+
* @param tags tags to be added per value.
27+
* @return tagged measurement TaggedMeasurement
28+
*/
29+
public static TaggedMeasurement create(double value, Tags tags) {
30+
return new TaggedMeasurement(value, tags);
31+
}
32+
33+
private TaggedMeasurement(double value, Tags tags) {
34+
this.value = value;
35+
this.tags = tags;
36+
}
37+
38+
/**
39+
* Returns the value.
40+
* @return value
41+
*/
42+
public Double getValue() {
43+
return value;
44+
}
45+
46+
/**
47+
* Returns the tags.
48+
* @return tags
49+
*/
50+
public Tags getTags() {
51+
return tags;
52+
}
53+
}

libs/telemetry/src/main/java/org/opensearch/telemetry/metrics/noop/NoopMetricsRegistry.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.opensearch.telemetry.metrics.Counter;
1313
import org.opensearch.telemetry.metrics.Histogram;
1414
import org.opensearch.telemetry.metrics.MetricsRegistry;
15+
import org.opensearch.telemetry.metrics.TaggedMeasurement;
1516
import org.opensearch.telemetry.metrics.tags.Tags;
1617

1718
import java.io.Closeable;
@@ -52,6 +53,11 @@ public Closeable createGauge(String name, String description, String unit, Suppl
5253
return () -> {};
5354
}
5455

56+
@Override
57+
public Closeable createGauge(String name, String description, String unit, Supplier<TaggedMeasurement> value) {
58+
return () -> {};
59+
}
60+
5561
@Override
5662
public void close() throws IOException {
5763

libs/telemetry/src/test/java/org/opensearch/telemetry/metrics/DefaultMetricsRegistryTests.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,19 @@ public void testGauge() {
7979
assertSame(mockCloseable, closeable);
8080
}
8181

82+
@SuppressWarnings("unchecked")
83+
public void testGaugeWithValueAndTagSupplier() {
84+
Closeable mockCloseable = mock(Closeable.class);
85+
when(defaultMeterRegistry.createGauge(any(String.class), any(String.class), any(String.class), any(Supplier.class))).thenReturn(
86+
mockCloseable
87+
);
88+
Closeable closeable = defaultMeterRegistry.createGauge(
89+
"org.opensearch.telemetry.metrics.DefaultMeterRegistryTests.testObservableGauge",
90+
"test observable gauge",
91+
"ms",
92+
() -> TaggedMeasurement.create(1.0, Tags.EMPTY)
93+
);
94+
assertSame(mockCloseable, closeable);
95+
}
96+
8297
}

plugins/telemetry-otel/src/internalClusterTest/java/org/opensearch/telemetry/metrics/TelemetryMetricsEnabledSanityIT.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@
2323
import java.util.Arrays;
2424
import java.util.Collection;
2525
import java.util.List;
26+
import java.util.Map;
2627
import java.util.concurrent.atomic.AtomicInteger;
2728
import java.util.function.Supplier;
2829
import java.util.stream.Collectors;
2930

31+
import io.opentelemetry.api.common.AttributeKey;
32+
import io.opentelemetry.api.common.Attributes;
3033
import io.opentelemetry.sdk.metrics.data.DoublePointData;
3134
import io.opentelemetry.sdk.metrics.data.MetricData;
3235
import io.opentelemetry.sdk.metrics.internal.data.ImmutableExponentialHistogramPointData;
@@ -147,6 +150,36 @@ public void testGauge() throws Exception {
147150

148151
}
149152

153+
public void testGaugeWithValueAndTagSupplier() throws Exception {
154+
String metricName = "test-gauge";
155+
MetricsRegistry metricsRegistry = internalCluster().getInstance(MetricsRegistry.class);
156+
InMemorySingletonMetricsExporter.INSTANCE.reset();
157+
Tags tags = Tags.create().addTag("test", "integ-test");
158+
final AtomicInteger testValue = new AtomicInteger(0);
159+
Supplier<TaggedMeasurement> valueProvider = () -> {
160+
return TaggedMeasurement.create(Double.valueOf(testValue.incrementAndGet()), tags);
161+
};
162+
Closeable gaugeCloseable = metricsRegistry.createGauge(metricName, "test", "ms", valueProvider);
163+
// Sleep for about 2.2s to wait for metrics to be published.
164+
Thread.sleep(2200);
165+
166+
InMemorySingletonMetricsExporter exporter = InMemorySingletonMetricsExporter.INSTANCE;
167+
168+
assertTrue(getMaxObservableGaugeValue(exporter, metricName) >= 2.0);
169+
170+
gaugeCloseable.close();
171+
double observableGaugeValueAfterStop = getMaxObservableGaugeValue(exporter, metricName);
172+
173+
Map<AttributeKey<?>, Object> attributes = getMetricAttributes(exporter, metricName);
174+
175+
assertEquals("integ-test", attributes.get(AttributeKey.stringKey("test")));
176+
177+
// Sleep for about 1.2s to wait for metrics to see that closed observableGauge shouldn't execute the callable.
178+
Thread.sleep(1200);
179+
assertEquals(observableGaugeValueAfterStop, getMaxObservableGaugeValue(exporter, metricName), 0.0);
180+
181+
}
182+
150183
private static double getMaxObservableGaugeValue(InMemorySingletonMetricsExporter exporter, String metricName) {
151184
List<MetricData> dataPoints = exporter.getFinishedMetricItems()
152185
.stream()
@@ -159,6 +192,15 @@ private static double getMaxObservableGaugeValue(InMemorySingletonMetricsExporte
159192
return totalValue;
160193
}
161194

195+
private static Map<AttributeKey<?>, Object> getMetricAttributes(InMemorySingletonMetricsExporter exporter, String metricName) {
196+
List<MetricData> dataPoints = exporter.getFinishedMetricItems()
197+
.stream()
198+
.filter(a -> a.getName().contains(metricName))
199+
.collect(Collectors.toList());
200+
Attributes attributes = dataPoints.get(0).getDoubleGaugeData().getPoints().stream().findAny().get().getAttributes();
201+
return attributes.asMap();
202+
}
203+
162204
@After
163205
public void reset() {
164206
InMemorySingletonMetricsExporter.INSTANCE.reset();

plugins/telemetry-otel/src/main/java/org/opensearch/telemetry/metrics/OTelMetricsTelemetry.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,17 @@ public Closeable createGauge(String name, String description, String unit, Suppl
101101
return () -> doubleObservableGauge.close();
102102
}
103103

104+
@Override
105+
public Closeable createGauge(String name, String description, String unit, Supplier<TaggedMeasurement> value) {
106+
ObservableDoubleGauge doubleObservableGauge = AccessController.doPrivileged(
107+
(PrivilegedAction<ObservableDoubleGauge>) () -> otelMeter.gaugeBuilder(name)
108+
.setUnit(unit)
109+
.setDescription(description)
110+
.buildWithCallback(record -> record.record(value.get().getValue(), OTelAttributesConverter.convert(value.get().getTags())))
111+
);
112+
return () -> doubleObservableGauge.close();
113+
}
114+
104115
@Override
105116
public void close() throws IOException {
106117
meterProvider.close();

plugins/telemetry-otel/src/test/java/org/opensearch/telemetry/metrics/OTelMetricsTelemetryTests.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,4 +180,34 @@ public void testGauge() throws Exception {
180180
closeable.close();
181181
verify(observableDoubleGauge).close();
182182
}
183+
184+
@SuppressWarnings({ "rawtypes", "unchecked" })
185+
public void testGaugeWithValueAndTagsSupplier() throws Exception {
186+
String observableGaugeName = "test-gauge";
187+
String description = "test";
188+
String unit = "1";
189+
Meter mockMeter = mock(Meter.class);
190+
OpenTelemetry mockOpenTelemetry = mock(OpenTelemetry.class);
191+
ObservableDoubleGauge observableDoubleGauge = mock(ObservableDoubleGauge.class);
192+
DoubleGaugeBuilder mockOTelDoubleGaugeBuilder = mock(DoubleGaugeBuilder.class);
193+
MeterProvider meterProvider = mock(MeterProvider.class);
194+
when(meterProvider.get(OTelTelemetryPlugin.INSTRUMENTATION_SCOPE_NAME)).thenReturn(mockMeter);
195+
MetricsTelemetry metricsTelemetry = new OTelMetricsTelemetry(
196+
new RefCountedReleasable("telemetry", mockOpenTelemetry, () -> {}),
197+
meterProvider
198+
);
199+
when(mockMeter.gaugeBuilder(Mockito.contains(observableGaugeName))).thenReturn(mockOTelDoubleGaugeBuilder);
200+
when(mockOTelDoubleGaugeBuilder.setDescription(description)).thenReturn(mockOTelDoubleGaugeBuilder);
201+
when(mockOTelDoubleGaugeBuilder.setUnit(unit)).thenReturn(mockOTelDoubleGaugeBuilder);
202+
when(mockOTelDoubleGaugeBuilder.buildWithCallback(any(Consumer.class))).thenReturn(observableDoubleGauge);
203+
204+
Closeable closeable = metricsTelemetry.createGauge(
205+
observableGaugeName,
206+
description,
207+
unit,
208+
() -> TaggedMeasurement.create(1.0, Tags.EMPTY)
209+
);
210+
closeable.close();
211+
verify(observableDoubleGauge).close();
212+
}
183213
}

server/src/test/java/org/opensearch/telemetry/TestInMemoryMetricsRegistry.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.opensearch.telemetry.metrics.Counter;
1212
import org.opensearch.telemetry.metrics.Histogram;
1313
import org.opensearch.telemetry.metrics.MetricsRegistry;
14+
import org.opensearch.telemetry.metrics.TaggedMeasurement;
1415
import org.opensearch.telemetry.metrics.tags.Tags;
1516

1617
import java.io.Closeable;
@@ -66,6 +67,11 @@ public Closeable createGauge(String name, String description, String unit, Suppl
6667
return null;
6768
}
6869

70+
@Override
71+
public Closeable createGauge(String name, String description, String unit, Supplier<TaggedMeasurement> value) {
72+
return null;
73+
}
74+
6975
@Override
7076
public void close() throws IOException {}
7177
}

test/framework/src/main/java/org/opensearch/test/telemetry/MockTelemetry.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.opensearch.telemetry.metrics.Counter;
1414
import org.opensearch.telemetry.metrics.Histogram;
1515
import org.opensearch.telemetry.metrics.MetricsTelemetry;
16+
import org.opensearch.telemetry.metrics.TaggedMeasurement;
1617
import org.opensearch.telemetry.metrics.noop.NoopCounter;
1718
import org.opensearch.telemetry.metrics.noop.NoopHistogram;
1819
import org.opensearch.telemetry.metrics.tags.Tags;
@@ -62,6 +63,11 @@ public Closeable createGauge(String name, String description, String unit, Suppl
6263
return () -> {};
6364
}
6465

66+
@Override
67+
public Closeable createGauge(String name, String description, String unit, Supplier<TaggedMeasurement> value) {
68+
return () -> {};
69+
}
70+
6571
@Override
6672
public void close() {
6773

0 commit comments

Comments
 (0)