Skip to content

Commit 8aabda5

Browse files
committed
otel: add LongUpDownCounterMetricInstrument
1 parent 74955e1 commit 8aabda5

File tree

6 files changed

+136
-7
lines changed

6 files changed

+136
-7
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2025 The gRPC Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.grpc;
18+
19+
import java.util.List;
20+
21+
/**
22+
* Represents a long-valued up down counter metric instrument.
23+
*/
24+
@Internal
25+
public final class LongUpDownCounterMetricInstrument extends PartialMetricInstrument {
26+
public LongUpDownCounterMetricInstrument(int index, String name, String description, String unit,
27+
List<String> requiredLabelKeys,
28+
List<String> optionalLabelKeys,
29+
boolean enableByDefault) {
30+
super(index, name, description, unit, requiredLabelKeys, optionalLabelKeys, enableByDefault);
31+
}
32+
}

api/src/main/java/io/grpc/MetricInstrumentRegistry.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,47 @@ public LongCounterMetricInstrument registerLongCounter(String name,
144144
}
145145
}
146146

147+
/**
148+
* Registers a new Long Up Down Counter metric instrument.
149+
*
150+
* @param name the name of the metric
151+
* @param description a description of the metric
152+
* @param unit the unit of measurement for the metric
153+
* @param requiredLabelKeys a list of required label keys
154+
* @param optionalLabelKeys a list of optional label keys
155+
* @param enableByDefault whether the metric should be enabled by default
156+
* @return the newly created LongUpDownCounterMetricInstrument
157+
* @throws IllegalStateException if a metric with the same name already exists
158+
*/
159+
public LongUpDownCounterMetricInstrument registerLongUpDownCounter(String name,
160+
String description,
161+
String unit,
162+
List<String> requiredLabelKeys,
163+
List<String> optionalLabelKeys,
164+
boolean enableByDefault) {
165+
checkArgument(!Strings.isNullOrEmpty(name), "missing metric name");
166+
checkNotNull(description, "description");
167+
checkNotNull(unit, "unit");
168+
checkNotNull(requiredLabelKeys, "requiredLabelKeys");
169+
checkNotNull(optionalLabelKeys, "optionalLabelKeys");
170+
synchronized (lock) {
171+
if (registeredMetricNames.contains(name)) {
172+
throw new IllegalStateException("Metric with name " + name + " already exists");
173+
}
174+
int index = nextAvailableMetricIndex;
175+
if (index + 1 == metricInstruments.length) {
176+
resizeMetricInstruments();
177+
}
178+
LongUpDownCounterMetricInstrument instrument = new LongUpDownCounterMetricInstrument(
179+
index, name, description, unit, requiredLabelKeys, optionalLabelKeys,
180+
enableByDefault);
181+
metricInstruments[index] = instrument;
182+
registeredMetricNames.add(name);
183+
nextAvailableMetricIndex += 1;
184+
return instrument;
185+
}
186+
}
187+
147188
/**
148189
* Registers a new Double Histogram metric instrument.
149190
*

api/src/main/java/io/grpc/MetricRecorder.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ default void addDoubleCounter(DoubleCounterMetricInstrument metricInstrument, do
5050
* Adds a value for a long valued counter metric instrument.
5151
*
5252
* @param metricInstrument The counter metric instrument to add the value against.
53-
* @param value The value to add.
53+
* @param value The value to add. MUST be non-negative.
5454
* @param requiredLabelValues A list of required label values for the metric.
5555
* @param optionalLabelValues A list of additional, optional label values for the metric.
5656
*/
@@ -66,6 +66,29 @@ default void addLongCounter(LongCounterMetricInstrument metricInstrument, long v
6666
metricInstrument.getOptionalLabelKeys().size());
6767
}
6868

69+
/**
70+
* Adds a value for a long valued up down counter metric instrument.
71+
*
72+
* @param metricInstrument The counter metric instrument to add the value against.
73+
* @param value The value to add. May be positive, negative or zero.
74+
* @param requiredLabelValues A list of required label values for the metric.
75+
* @param optionalLabelValues A list of additional, optional label values for the metric.
76+
*/
77+
default void addLongUpDownCounter(LongUpDownCounterMetricInstrument metricInstrument,
78+
long value,
79+
List<String> requiredLabelValues,
80+
List<String> optionalLabelValues) {
81+
checkArgument(requiredLabelValues != null
82+
&& requiredLabelValues.size() == metricInstrument.getRequiredLabelKeys().size(),
83+
"Incorrect number of required labels provided. Expected: %s",
84+
metricInstrument.getRequiredLabelKeys().size());
85+
checkArgument(optionalLabelValues != null
86+
&& optionalLabelValues.size() == metricInstrument.getOptionalLabelKeys().size(),
87+
"Incorrect number of optional labels provided. Expected: %s",
88+
metricInstrument.getOptionalLabelKeys().size());
89+
}
90+
91+
6992
/**
7093
* Records a value for a double-precision histogram metric instrument.
7194
*

api/src/main/java/io/grpc/MetricSink.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,26 @@ default void addDoubleCounter(DoubleCounterMetricInstrument metricInstrument, do
6565
* Adds a value for a long valued counter metric associated with specified metric instrument.
6666
*
6767
* @param metricInstrument The counter metric instrument identifies metric measure to add.
68-
* @param value The value to record.
68+
* @param value The value to record. MUST be non-negative.
6969
* @param requiredLabelValues A list of required label values for the metric.
7070
* @param optionalLabelValues A list of additional, optional label values for the metric.
7171
*/
7272
default void addLongCounter(LongCounterMetricInstrument metricInstrument, long value,
73-
List<String> requiredLabelValues, List<String> optionalLabelValues) {
73+
List<String> requiredLabelValues, List<String> optionalLabelValues) {
74+
}
75+
76+
/**
77+
* Adds a value for a long valued up down counter metric associated with specified metric
78+
* instrument.
79+
*
80+
* @param metricInstrument The counter metric instrument identifies metric measure to add.
81+
* @param value The value to record. May be positive, negative or zero.
82+
* @param requiredLabelValues A list of required label values for the metric.
83+
* @param optionalLabelValues A list of additional, optional label values for the metric.
84+
*/
85+
default void addLongUpDownCounter(LongUpDownCounterMetricInstrument metricInstrument, long value,
86+
List<String> requiredLabelValues,
87+
List<String> optionalLabelValues) {
7488
}
7589

7690
/**

core/src/main/java/io/grpc/internal/SubchannelMetrics.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.google.common.collect.ImmutableList;
2020
import com.google.common.collect.Lists;
2121
import io.grpc.LongCounterMetricInstrument;
22+
import io.grpc.LongUpDownCounterMetricInstrument;
2223
import io.grpc.MetricInstrumentRegistry;
2324
import io.grpc.MetricRecorder;
2425

@@ -27,7 +28,7 @@ public final class SubchannelMetrics {
2728
private static final LongCounterMetricInstrument disconnections;
2829
private static final LongCounterMetricInstrument connectionAttemptsSucceeded;
2930
private static final LongCounterMetricInstrument connectionAttemptsFailed;
30-
private static final LongCounterMetricInstrument openConnections;
31+
private static final LongUpDownCounterMetricInstrument openConnections;
3132
private final MetricRecorder metricRecorder;
3233

3334
public SubchannelMetrics(MetricRecorder metricRecorder) {
@@ -64,7 +65,7 @@ public SubchannelMetrics(MetricRecorder metricRecorder) {
6465
false
6566
);
6667

67-
openConnections = metricInstrumentRegistry.registerLongCounter(
68+
openConnections = metricInstrumentRegistry.registerLongUpDownCounter(
6869
"grpc.subchannel.open_connections",
6970
"EXPERIMENTAL. Number of open connections.",
7071
"{connection}",
@@ -80,7 +81,7 @@ public void recordConnectionAttemptSucceeded(OtelMetricsAttributes labelSet) {
8081
ImmutableList.of(labelSet.target),
8182
ImmutableList.of(labelSet.backendService, labelSet.locality));
8283
metricRecorder
83-
.addLongCounter(openConnections, 1,
84+
.addLongUpDownCounter(openConnections, 1,
8485
ImmutableList.of(labelSet.target),
8586
ImmutableList.of(labelSet.securityLevel, labelSet.backendService, labelSet.locality));
8687
}
@@ -98,7 +99,7 @@ public void recordDisconnection(OtelMetricsAttributes labelSet) {
9899
ImmutableList.of(labelSet.target),
99100
ImmutableList.of(labelSet.backendService, labelSet.locality, labelSet.disconnectError));
100101
metricRecorder
101-
.addLongCounter(openConnections, -11,
102+
.addLongUpDownCounter(openConnections, -1,
102103
ImmutableList.of(labelSet.target),
103104
ImmutableList.of(labelSet.securityLevel, labelSet.backendService, labelSet.locality));
104105
}

opentelemetry/src/main/java/io/grpc/opentelemetry/OpenTelemetryMetricSink.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import io.grpc.LongCounterMetricInstrument;
2828
import io.grpc.LongGaugeMetricInstrument;
2929
import io.grpc.LongHistogramMetricInstrument;
30+
import io.grpc.LongUpDownCounterMetricInstrument;
3031
import io.grpc.MetricInstrument;
3132
import io.grpc.MetricSink;
3233
import io.opentelemetry.api.common.Attributes;
@@ -36,6 +37,7 @@
3637
import io.opentelemetry.api.metrics.DoubleHistogram;
3738
import io.opentelemetry.api.metrics.LongCounter;
3839
import io.opentelemetry.api.metrics.LongHistogram;
40+
import io.opentelemetry.api.metrics.LongUpDownCounter;
3941
import io.opentelemetry.api.metrics.Meter;
4042
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
4143
import io.opentelemetry.api.metrics.ObservableMeasurement;
@@ -117,6 +119,22 @@ public void addLongCounter(LongCounterMetricInstrument metricInstrument, long va
117119
counter.add(value, attributes);
118120
}
119121

122+
@Override
123+
public void addLongUpDownCounter(LongUpDownCounterMetricInstrument metricInstrument, long value,
124+
List<String> requiredLabelValues,
125+
List<String> optionalLabelValues) {
126+
MeasuresData instrumentData = measures.get(metricInstrument.getIndex());
127+
if (instrumentData == null) {
128+
// Disabled metric
129+
return;
130+
}
131+
Attributes attributes = createAttributes(metricInstrument.getRequiredLabelKeys(),
132+
metricInstrument.getOptionalLabelKeys(), requiredLabelValues, optionalLabelValues,
133+
instrumentData.getOptionalLabelsBitSet());
134+
LongUpDownCounter counter = (LongUpDownCounter) instrumentData.getMeasure();
135+
counter.add(value, attributes);
136+
}
137+
120138
@Override
121139
public void recordDoubleHistogram(DoubleHistogramMetricInstrument metricInstrument, double value,
122140
List<String> requiredLabelValues, List<String> optionalLabelValues) {

0 commit comments

Comments
 (0)