Skip to content

Commit 13a9290

Browse files
authored
Add MetricSink implementation for gRPC OpenTelemetry
This adds the following components that are required for gRPC A79 non-per-call metrics architecture. - MetricSink implementation for gRPC OpenTelemetry - Configurator for plumbing per call metrics ClientInterceptor and ServerStreamTracer.Factory via unified OpenTelemetryModule.
1 parent 6585d05 commit 13a9290

23 files changed

+1153
-170
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2024 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+
/**
20+
* Provides hooks for modifying gRPC channels and servers during their construction.
21+
*/
22+
@Internal
23+
public interface Configurator {
24+
/**
25+
* Allows implementations to modify the channel builder.
26+
*
27+
* @param channelBuilder the channel builder being constructed
28+
*/
29+
default void configureChannelBuilder(ManagedChannelBuilder<?> channelBuilder) {}
30+
31+
/**
32+
* Allows implementations to modify the server builder.
33+
*
34+
* @param serverBuilder the server builder being constructed
35+
*/
36+
default void configureServerBuilder(ServerBuilder<?> serverBuilder) {}
37+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright 2024 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.ArrayList;
20+
import java.util.Collections;
21+
import java.util.List;
22+
23+
/**
24+
* A registry for {@link Configurator} instances.
25+
*
26+
* <p>This class is responsible for maintaining a list of configurators and providing access to
27+
* them. The default registry can be obtained using {@link #getDefaultRegistry()}.
28+
*/
29+
@Internal
30+
public final class ConfiguratorRegistry {
31+
private static ConfiguratorRegistry instance;
32+
private static boolean isConfiguratorsSet;
33+
private List<Configurator> configurators = Collections.emptyList();
34+
35+
ConfiguratorRegistry() {}
36+
37+
/**
38+
* Returns the default global instance of the configurator registry.
39+
*/
40+
public static synchronized ConfiguratorRegistry getDefaultRegistry() {
41+
if (instance == null) {
42+
instance = new ConfiguratorRegistry();
43+
}
44+
return instance;
45+
}
46+
47+
/**
48+
* Sets the configurators in this registry. This method can only be called once.
49+
*
50+
* @param configurators the configurators to set
51+
* @throws IllegalStateException if this method is called more than once
52+
*/
53+
public synchronized void setConfigurators(List<Configurator> configurators) {
54+
if (isConfiguratorsSet) {
55+
throw new IllegalStateException("Configurators are already set");
56+
}
57+
configurators = Collections.unmodifiableList(new ArrayList<>(configurators));
58+
isConfiguratorsSet = true;
59+
}
60+
61+
/**
62+
* Returns a list of the configurators in this registry.
63+
*/
64+
public synchronized List<Configurator> getConfigurators() {
65+
return configurators;
66+
}
67+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
*/
2424
@Internal
2525
public final class DoubleCounterMetricInstrument extends PartialMetricInstrument {
26-
DoubleCounterMetricInstrument(int index, String name, String description, String unit,
26+
public DoubleCounterMetricInstrument(int index, String name, String description, String unit,
2727
List<String> requiredLabelKeys, List<String> optionalLabelKeys, boolean enableByDefault) {
2828
super(index, name, description, unit, requiredLabelKeys, optionalLabelKeys, enableByDefault);
2929
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
public final class DoubleHistogramMetricInstrument extends PartialMetricInstrument {
2626
private final List<Double> bucketBoundaries;
2727

28-
DoubleHistogramMetricInstrument(int index, String name, String description, String unit,
28+
public DoubleHistogramMetricInstrument(int index, String name, String description, String unit,
2929
List<Double> bucketBoundaries, List<String> requiredLabelKeys, List<String> optionalLabelKeys,
3030
boolean enableByDefault) {
3131
super(index, name, description, unit, requiredLabelKeys, optionalLabelKeys, enableByDefault);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
*/
2424
@Internal
2525
public final class LongCounterMetricInstrument extends PartialMetricInstrument {
26-
LongCounterMetricInstrument(int index, String name, String description, String unit,
26+
public LongCounterMetricInstrument(int index, String name, String description, String unit,
2727
List<String> requiredLabelKeys, List<String> optionalLabelKeys, boolean enableByDefault) {
2828
super(index, name, description, unit, requiredLabelKeys, optionalLabelKeys, enableByDefault);
2929
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
*/
2424
@Internal
2525
public final class LongGaugeMetricInstrument extends PartialMetricInstrument {
26-
LongGaugeMetricInstrument(int index, String name, String description, String unit,
26+
public LongGaugeMetricInstrument(int index, String name, String description, String unit,
2727
List<String> requiredLabelKeys, List<String> optionalLabelKeys, boolean enableByDefault) {
2828
super(index, name, description, unit, requiredLabelKeys, optionalLabelKeys, enableByDefault);
2929
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
public final class LongHistogramMetricInstrument extends PartialMetricInstrument {
2626
private final List<Long> bucketBoundaries;
2727

28-
LongHistogramMetricInstrument(int index, String name, String description, String unit,
28+
public LongHistogramMetricInstrument(int index, String name, String description, String unit,
2929
List<Long> bucketBoundaries, List<String> requiredLabelKeys, List<String> optionalLabelKeys,
3030
boolean enableByDefault) {
3131
super(index, name, description, unit, requiredLabelKeys, optionalLabelKeys, enableByDefault);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public DoubleCounterMetricInstrument registerDoubleCounter(String name,
9595
if (index + 1 == metricInstruments.length) {
9696
resizeMetricInstruments();
9797
}
98+
// TODO(dnvindhya): add limit for number of optional labels allowed
9899
DoubleCounterMetricInstrument instrument = new DoubleCounterMetricInstrument(
99100
index, name, description, unit, requiredLabelKeys, optionalLabelKeys,
100101
enableByDefault);

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

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package io.grpc;
1818

1919
import java.util.List;
20+
import java.util.Map;
2021
import java.util.Set;
2122

2223
/**
@@ -26,50 +27,49 @@
2627
public interface MetricSink {
2728

2829
/**
29-
* Returns a set of names for the metrics that are currently enabled for this `MetricSink`.
30+
* Returns a set of names for the metrics that are currently enabled or disabled.
3031
*
3132
* @return A set of enabled metric names.
3233
*/
33-
Set<String> getEnabledMetrics();
34+
Map<String, Boolean> getEnabledMetrics();
3435

3536
/**
36-
* Returns a list of label names that are considered optional for metrics collected by this
37-
* `MetricSink`.
37+
* Returns a set of optional label names for metrics that the sink actually wants.
3838
*
39-
* @return A list of optional label names.
39+
* @return A set of optional label names.
4040
*/
41-
List<String> getOptionalLabels();
41+
Set<String> getOptionalLabels();
4242

4343
/**
44-
* Returns a list of metric measures used to record metric values. These measures are created
44+
* Returns size of metric measures used to record metric values. These measures are created
4545
* based on registered metrics (via MetricInstrumentRegistry) and are ordered according to their
4646
* registration sequence.
4747
*
48-
* @return A list of metric measures.
48+
* @return Size of metric measures.
4949
*/
50-
List<Object> getMetricsMeasures();
50+
int getMeasuresSize();
5151

5252
/**
53-
* Records a value for a double-precision counter associated with specified metric instrument.
53+
* Adds a value for a double-precision counter associated with specified metric instrument.
5454
*
55-
* @param metricInstrument The counter metric instrument identifies metric measure to record.
55+
* @param metricInstrument The counter metric instrument identifies metric measure to add.
5656
* @param value The value to record.
5757
* @param requiredLabelValues A list of required label values for the metric.
5858
* @param optionalLabelValues A list of additional, optional label values for the metric.
5959
*/
60-
default void recordDoubleCounter(DoubleCounterMetricInstrument metricInstrument, double value,
60+
default void addDoubleCounter(DoubleCounterMetricInstrument metricInstrument, double value,
6161
List<String> requiredLabelValues, List<String> optionalLabelValues) {
6262
}
6363

6464
/**
65-
* Records a value for a long valued counter metric associated with specified metric instrument.
65+
* Adds a value for a long valued counter metric associated with specified metric instrument.
6666
*
67-
* @param metricInstrument The counter metric instrument identifies metric measure to record.
67+
* @param metricInstrument The counter metric instrument identifies metric measure to add.
6868
* @param value The value to record.
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
*/
72-
default void recordLongCounter(LongCounterMetricInstrument metricInstrument, long value,
72+
default void addLongCounter(LongCounterMetricInstrument metricInstrument, long value,
7373
List<String> requiredLabelValues, List<String> optionalLabelValues) {
7474
}
7575

@@ -99,5 +99,5 @@ default void recordLongHistogram(LongHistogramMetricInstrument metricInstrument,
9999
List<String> requiredLabelValues, List<String> optionalLabelValues) {
100100
}
101101

102-
default void updateMeasures(List<MetricInstrument> instruments) {}
102+
void updateMeasures(List<MetricInstrument> instruments);
103103
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272
import io.grpc.ManagedChannelBuilder;
7373
import io.grpc.Metadata;
7474
import io.grpc.MethodDescriptor;
75+
import io.grpc.MetricInstrumentRegistry;
76+
import io.grpc.MetricRecorder;
7577
import io.grpc.NameResolver;
7678
import io.grpc.NameResolver.ConfigOrError;
7779
import io.grpc.NameResolver.ResolutionResult;
@@ -588,6 +590,7 @@ ClientStream newSubstream(
588590
private final ChannelStreamProvider transportProvider = new ChannelStreamProvider();
589591

590592
private final Rescheduler idleTimer;
593+
private final MetricRecorder metricRecorder;
591594

592595
ManagedChannelImpl(
593596
ManagedChannelImplBuilder builder,
@@ -715,6 +718,8 @@ public CallTracer create() {
715718
}
716719
serviceConfigUpdated = true;
717720
}
721+
this.metricRecorder = new MetricRecorderImpl(builder.metricSinks,
722+
MetricInstrumentRegistry.getDefaultRegistry());
718723
}
719724

720725
@VisibleForTesting
@@ -1743,6 +1748,11 @@ public NameResolverRegistry getNameResolverRegistry() {
17431748
return nameResolverRegistry;
17441749
}
17451750

1751+
@Override
1752+
public MetricRecorder getMetricRecorder() {
1753+
return metricRecorder;
1754+
}
1755+
17461756
/**
17471757
* A placeholder for channel creds if user did not specify channel creds for the channel.
17481758
*/

0 commit comments

Comments
 (0)