@@ -19,8 +19,8 @@ import (
1919
2020 "chainguard.dev/go-grpc-kit/pkg/trace"
2121 "github.com/chainguard-dev/clog"
22+ grpc_prometheus "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus"
2223 grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/retry"
23- grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
2424 "github.com/kelseyhightower/envconfig"
2525 "github.com/prometheus/client_golang/prometheus"
2626 "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
@@ -37,18 +37,17 @@ type envStruct struct {
3737 GrpcClientMaxRetry uint `envconfig:"GRPC_CLIENT_MAX_RETRY" default:"0"`
3838}
3939
40- var (
41- envOnce sync.Once
42-
40+ type initStuff struct {
4341 env envStruct
4442 clientMetrics * grpc_prometheus.ClientMetrics
45- )
43+ }
44+
45+ var (
46+ state = sync .OnceValue (func () initStuff {
47+ init := initStuff {}
4648
47- // Parse these lazily, to allow clients to set their own in their main() or init().
48- func getEnv () * envStruct {
49- envOnce .Do (func () {
5049 logger := clog .FromContext (context .Background ())
51- if err := envconfig .Process ("" , & env ); err != nil {
50+ if err := envconfig .Process ("" , & init . env ); err != nil {
5251 logger .Warn ("Failed to process environment variables" , "error" , err )
5352 }
5453
@@ -58,21 +57,22 @@ func getEnv() *envStruct {
5857
5958 cmOpts := []grpc_prometheus.ClientMetricsOption {}
6059
61- if env .EnableClientHandlingTimeHistogram {
60+ if init . env .EnableClientHandlingTimeHistogram {
6261 cmOpts = append (cmOpts , grpc_prometheus .WithClientHandlingTimeHistogram (hopt ))
6362 }
64- if env .EnableClientStreamReceiveTimeHistogram {
63+ if init . env .EnableClientStreamReceiveTimeHistogram {
6564 cmOpts = append (cmOpts , grpc_prometheus .WithClientStreamRecvHistogram (hopt ))
6665 }
67- if env .EnableClientStreamSendTimeHistogram {
66+ if init . env .EnableClientStreamSendTimeHistogram {
6867 cmOpts = append (cmOpts , grpc_prometheus .WithClientStreamSendHistogram (hopt ))
6968 }
7069
71- clientMetrics = grpc_prometheus .NewClientMetrics (cmOpts ... )
72- prometheus .MustRegister (clientMetrics )
70+ init .clientMetrics = grpc_prometheus .NewClientMetrics (cmOpts ... )
71+ prometheus .MustRegister (init .clientMetrics )
72+
73+ return init
7374 })
74- return & env
75- }
75+ )
7676
7777// ListenerForTest is to support bufnet in our testing.
7878var ListenerForTest DialableListener
@@ -132,14 +132,14 @@ func ClientOptions() []option.ClientOption {
132132func GRPCDialOptions () []grpc.DialOption {
133133 retryOpts := []grpc_retry.CallOption {
134134 grpc_retry .WithBackoff (grpc_retry .BackoffExponential (100 * time .Millisecond )),
135- grpc_retry .WithMax (getEnv () .GrpcClientMaxRetry ),
135+ grpc_retry .WithMax (state (). env .GrpcClientMaxRetry ),
136136 }
137137
138138 return []grpc.DialOption {
139139 grpc .WithStatsHandler (otelgrpc .NewClientHandler ()),
140140 grpc .WithStatsHandler (trace .PreserveTraceParentHandler ),
141- grpc .WithChainUnaryInterceptor (clientMetrics .UnaryClientInterceptor (), grpc_retry .UnaryClientInterceptor (retryOpts ... )),
142- grpc .WithChainStreamInterceptor (clientMetrics .StreamClientInterceptor (), grpc_retry .StreamClientInterceptor (retryOpts ... )),
141+ grpc .WithChainUnaryInterceptor (state (). clientMetrics .UnaryClientInterceptor (), grpc_retry .UnaryClientInterceptor (retryOpts ... )),
142+ grpc .WithChainStreamInterceptor (state (). clientMetrics .StreamClientInterceptor (), grpc_retry .StreamClientInterceptor (retryOpts ... )),
143143 }
144144}
145145
0 commit comments