github.com/blend/go-sdk@v1.20220411.3/stats/grpcstats/listeners.go (about)

     1  /*
     2  
     3  Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file.
     5  
     6  */
     7  
     8  package grpcstats
     9  
    10  import (
    11  	"context"
    12  	"strconv"
    13  
    14  	"google.golang.org/grpc/status"
    15  
    16  	"github.com/blend/go-sdk/grpcutil"
    17  	"github.com/blend/go-sdk/logger"
    18  	"github.com/blend/go-sdk/stats"
    19  	"github.com/blend/go-sdk/timeutil"
    20  )
    21  
    22  // AddListeners adds grpc listeners.
    23  func AddListeners(log logger.Listenable, collector stats.Collector, opts ...stats.AddListenerOption) {
    24  	if log == nil || collector == nil {
    25  		return
    26  	}
    27  
    28  	options := stats.NewAddListenerOptions(opts...)
    29  
    30  	log.Listen(grpcutil.FlagRPC, stats.ListenerNameStats, grpcutil.NewRPCEventListener(func(ctx context.Context, re grpcutil.RPCEvent) {
    31  		var tags []string
    32  
    33  		labels := logger.GetLabels(ctx)
    34  		for key, value := range labels {
    35  			tags = append(tags, stats.Tag(key, value))
    36  		}
    37  
    38  		if len(re.Method) > 0 {
    39  			tags = append(tags, stats.Tag(TagRPCMethod, re.Method))
    40  		} else {
    41  			tags = append(tags, stats.Tag(TagRPCMethod, RPCMethodUnknown))
    42  		}
    43  
    44  		if re.Engine != "" {
    45  			tags = append(tags, stats.Tag(TagRPCEngine, re.Engine))
    46  		}
    47  		if re.Peer != "" {
    48  			tags = append(tags, stats.Tag(TagRPCPeer, re.Peer))
    49  		}
    50  
    51  		if re.Err != nil {
    52  			tags = append(tags, getErrorTag(re.Err))
    53  		}
    54  
    55  		tags = append(tags, options.GetLoggerLabelsAsTags(ctx)...)
    56  
    57  		_ = collector.Increment(MetricNameRPC, tags...)
    58  		_ = collector.Gauge(MetricNameRPCElapsedLast, timeutil.Milliseconds(re.Elapsed), tags...)
    59  		_ = collector.Histogram(MetricNameRPCElapsed, timeutil.Milliseconds(re.Elapsed), tags...)
    60  	}))
    61  
    62  	log.Listen(grpcutil.FlagRPCStreamMessage, stats.ListenerNameStats, grpcutil.NewRPCStreamMessageEventListener(func(ctx context.Context, re grpcutil.RPCStreamMessageEvent) {
    63  		var tags []string
    64  
    65  		labels := logger.GetLabels(ctx)
    66  		for key, value := range labels {
    67  			tags = append(tags, stats.Tag(key, value))
    68  		}
    69  
    70  		if len(re.Method) > 0 {
    71  			tags = append(tags, stats.Tag(TagRPCMethod, re.Method))
    72  		} else {
    73  			tags = append(tags, stats.Tag(TagRPCMethod, RPCMethodUnknown))
    74  		}
    75  
    76  		if re.Engine != "" {
    77  			tags = append(tags, stats.Tag(TagRPCEngine, re.Engine))
    78  		}
    79  		if re.Peer != "" {
    80  			tags = append(tags, stats.Tag(TagRPCPeer, re.Peer))
    81  		}
    82  
    83  		if re.Direction != "" {
    84  			tags = append(tags, stats.Tag(TagRPCStreamMessageDirection, string(re.Direction)))
    85  		}
    86  		if re.Err != nil {
    87  			tags = append(tags, getErrorTag(re.Err))
    88  		}
    89  
    90  		tags = append(tags, options.GetLoggerLabelsAsTags(ctx)...)
    91  
    92  		_ = collector.Increment(MetricNameRPCStreamMessage, tags...)
    93  		_ = collector.Gauge(MetricNameRPCStreamMessageElapsedLast, timeutil.Milliseconds(re.Elapsed), tags...)
    94  		_ = collector.Histogram(MetricNameRPCStreamMessageElapsed, timeutil.Milliseconds(re.Elapsed), tags...)
    95  	}))
    96  }
    97  
    98  func getErrorTag(err error) string {
    99  	if e, ok := status.FromError(err); ok {
   100  		code := e.Code()
   101  		return stats.Tag(stats.TagError, strconv.Itoa(int(code)))
   102  	}
   103  	return stats.TagError
   104  }