github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/storage/chunk/client/gcp/instrumentation.go (about)

     1  package gcp
     2  
     3  import (
     4  	"net/http"
     5  	"strconv"
     6  	"time"
     7  
     8  	otgrpc "github.com/opentracing-contrib/go-grpc"
     9  	opentracing "github.com/opentracing/opentracing-go"
    10  	"github.com/prometheus/client_golang/prometheus"
    11  	"github.com/prometheus/client_golang/prometheus/promauto"
    12  	"github.com/weaveworks/common/middleware"
    13  	"google.golang.org/api/option"
    14  	"google.golang.org/grpc"
    15  )
    16  
    17  var (
    18  	bigtableRequestDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
    19  		Namespace: "loki",
    20  		Name:      "bigtable_request_duration_seconds",
    21  		Help:      "Time spent doing Bigtable requests.",
    22  
    23  		// Bigtable latency seems to range from a few ms to a several seconds and is
    24  		// important.  So use 9 buckets from 1ms to just over 1 minute (65s).
    25  		Buckets: prometheus.ExponentialBuckets(0.001, 4, 9),
    26  	}, []string{"operation", "status_code"})
    27  
    28  	gcsRequestDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
    29  		Namespace: "loki",
    30  		Name:      "gcs_request_duration_seconds",
    31  		Help:      "Time spent doing GCS requests.",
    32  
    33  		// 6 buckets from 5ms to 20s.
    34  		Buckets: prometheus.ExponentialBuckets(0.005, 4, 7),
    35  	}, []string{"operation", "status_code"})
    36  )
    37  
    38  func bigtableInstrumentation() ([]grpc.UnaryClientInterceptor, []grpc.StreamClientInterceptor) {
    39  	return []grpc.UnaryClientInterceptor{
    40  			otgrpc.OpenTracingClientInterceptor(opentracing.GlobalTracer()),
    41  			middleware.UnaryClientInstrumentInterceptor(bigtableRequestDuration),
    42  		},
    43  		[]grpc.StreamClientInterceptor{
    44  			otgrpc.OpenTracingStreamClientInterceptor(opentracing.GlobalTracer()),
    45  			middleware.StreamClientInstrumentInterceptor(bigtableRequestDuration),
    46  		}
    47  }
    48  
    49  func gcsInstrumentation(transport http.RoundTripper) *http.Client {
    50  	client := &http.Client{
    51  		Transport: instrumentedTransport{
    52  			observer: gcsRequestDuration,
    53  			next:     transport,
    54  		},
    55  	}
    56  	return client
    57  }
    58  
    59  func toOptions(opts []grpc.DialOption) []option.ClientOption {
    60  	result := make([]option.ClientOption, 0, len(opts))
    61  	for _, opt := range opts {
    62  		result = append(result, option.WithGRPCDialOption(opt))
    63  	}
    64  	return result
    65  }
    66  
    67  type instrumentedTransport struct {
    68  	observer prometheus.ObserverVec
    69  	next     http.RoundTripper
    70  }
    71  
    72  func (i instrumentedTransport) RoundTrip(req *http.Request) (*http.Response, error) {
    73  	start := time.Now()
    74  	resp, err := i.next.RoundTrip(req)
    75  	if err == nil {
    76  		i.observer.WithLabelValues(req.Method, strconv.Itoa(resp.StatusCode)).Observe(time.Since(start).Seconds())
    77  	}
    78  	return resp, err
    79  }