17
17
package com .google .cloud .storage ;
18
18
19
19
import com .google .api .core .ApiFunction ;
20
- import com .google .api .gax .grpc .InstantiatingGrpcChannelProvider ;
21
20
import com .google .api .gax .rpc .PermissionDeniedException ;
22
21
import com .google .api .gax .rpc .UnavailableException ;
23
22
import com .google .cloud .opentelemetry .metric .GoogleCloudMetricExporter ;
59
58
import java .util .concurrent .atomic .AtomicBoolean ;
60
59
import java .util .logging .Logger ;
61
60
import java .util .stream .Collectors ;
61
+ import org .checkerframework .checker .nullness .qual .NonNull ;
62
+ import org .checkerframework .checker .nullness .qual .Nullable ;
62
63
63
64
final class OpenTelemetryBootstrappingUtils {
64
65
private static final Collection <String > METRICS_TO_ENABLE =
@@ -88,15 +89,41 @@ final class OpenTelemetryBootstrappingUtils {
88
89
89
90
static final Logger log = Logger .getLogger (OpenTelemetryBootstrappingUtils .class .getName ());
90
91
91
- static void enableGrpcMetrics (
92
- InstantiatingGrpcChannelProvider .Builder channelProviderBuilder ,
92
+ @ NonNull
93
+ static ChannelConfigurator enableGrpcMetrics (
94
+ @ Nullable ChannelConfigurator channelConfigurator ,
93
95
String endpoint ,
94
- String projectId ,
96
+ @ Nullable String projectId ,
95
97
String universeDomain ,
96
98
boolean shouldSuppressExceptions ) {
99
+ GCPResourceProvider resourceProvider = new GCPResourceProvider ();
100
+ Attributes detectedAttributes = resourceProvider .getAttributes ();
101
+
102
+ @ Nullable String detectedProjectId =
103
+ detectedAttributes .get (AttributeKey .stringKey ("cloud.account.id" ));
104
+ if (projectId == null && detectedProjectId == null ) {
105
+ log .warning (
106
+ "Unable to determine the Project ID in order to report metrics. No gRPC client metrics will be reported." );
107
+ return channelConfigurator != null ? channelConfigurator : ChannelConfigurator .identity ();
108
+ }
109
+
110
+ String projectIdToUse = detectedProjectId == null ? projectId : detectedProjectId ;
111
+ if (!projectIdToUse .equals (projectId )) {
112
+ log .warning (
113
+ "The Project ID configured for gRPC client metrics is "
114
+ + projectIdToUse
115
+ + ", but the Project ID of the storage client is "
116
+ + projectId
117
+ + ". Make sure that the service account in use has the required metric writing role "
118
+ + "(roles/monitoring.metricWriter) in the project "
119
+ + projectIdToUse
120
+ + ", or metrics will not be written." );
121
+ }
122
+
97
123
String metricServiceEndpoint = getCloudMonitoringEndpoint (endpoint , universeDomain );
98
124
SdkMeterProvider provider =
99
- createMeterProvider (metricServiceEndpoint , projectId , shouldSuppressExceptions );
125
+ createMeterProvider (
126
+ metricServiceEndpoint , projectIdToUse , detectedAttributes , shouldSuppressExceptions );
100
127
101
128
OpenTelemetrySdk openTelemetrySdk =
102
129
OpenTelemetrySdk .builder ().setMeterProvider (provider ).build ();
@@ -106,16 +133,48 @@ static void enableGrpcMetrics(
106
133
.addOptionalLabel ("grpc.lb.locality" )
107
134
.enableMetrics (METRICS_TO_ENABLE )
108
135
.build ();
109
- ApiFunction <ManagedChannelBuilder , ManagedChannelBuilder > channelConfigurator =
110
- channelProviderBuilder .getChannelConfigurator ();
111
- channelProviderBuilder .setChannelConfigurator (
136
+ ChannelConfigurator otelConfigurator =
112
137
b -> {
113
138
grpcOpenTelemetry .configureChannelBuilder (b );
114
- if (channelConfigurator != null ) {
115
- return channelConfigurator .apply (b );
116
- }
117
139
return b ;
118
- });
140
+ };
141
+ return otelConfigurator .andThen (channelConfigurator );
142
+ }
143
+
144
+ @ SuppressWarnings ("rawtypes" ) // ManagedChannelBuilder
145
+ @ FunctionalInterface
146
+ interface ChannelConfigurator extends ApiFunction <ManagedChannelBuilder , ManagedChannelBuilder > {
147
+ @ NonNull
148
+ default ChannelConfigurator andThen (@ Nullable ChannelConfigurator then ) {
149
+ if (then == null ) {
150
+ return this ;
151
+ }
152
+ return b -> then .apply (this .apply (b ));
153
+ }
154
+
155
+ static ChannelConfigurator identity () {
156
+ return IdentityChannelConfigurator .INSTANCE ;
157
+ }
158
+
159
+ static ChannelConfigurator lift (
160
+ @ Nullable ApiFunction <ManagedChannelBuilder , ManagedChannelBuilder > f ) {
161
+ if (f == null ) {
162
+ return identity ();
163
+ }
164
+ return f ::apply ;
165
+ }
166
+ }
167
+
168
+ @ SuppressWarnings ("rawtypes" ) // ManagedChannelBuilder
169
+ private static final class IdentityChannelConfigurator implements ChannelConfigurator {
170
+ private static final IdentityChannelConfigurator INSTANCE = new IdentityChannelConfigurator ();
171
+
172
+ private IdentityChannelConfigurator () {}
173
+
174
+ @ Override
175
+ public ManagedChannelBuilder apply (ManagedChannelBuilder input ) {
176
+ return input ;
177
+ }
119
178
}
120
179
121
180
@ VisibleForTesting
@@ -147,24 +206,10 @@ static String getCloudMonitoringEndpoint(String endpoint, String universeDomain)
147
206
148
207
@ VisibleForTesting
149
208
static SdkMeterProvider createMeterProvider (
150
- String metricServiceEndpoint , String projectId , boolean shouldSuppressExceptions ) {
151
- GCPResourceProvider resourceProvider = new GCPResourceProvider ();
152
- Attributes detectedAttributes = resourceProvider .getAttributes ();
153
-
154
- String detectedProjectId = detectedAttributes .get (AttributeKey .stringKey ("cloud.account.id" ));
155
- String projectIdToUse = detectedProjectId == null ? projectId : detectedProjectId ;
156
-
157
- if (!projectIdToUse .equals (projectId )) {
158
- log .warning (
159
- "The Project ID configured for metrics is "
160
- + projectIdToUse
161
- + ", but the Project ID of the storage client is "
162
- + projectId
163
- + ". Make sure that the service account in use has the required metric writing role "
164
- + "(roles/monitoring.metricWriter) in the project "
165
- + projectIdToUse
166
- + ", or metrics will not be written." );
167
- }
209
+ String metricServiceEndpoint ,
210
+ String projectIdToUse ,
211
+ Attributes detectedAttributes ,
212
+ boolean shouldSuppressExceptions ) {
168
213
169
214
MonitoredResourceDescription monitoredResourceDescription =
170
215
new MonitoredResourceDescription (
0 commit comments