go.undefinedlabs.com/scopeagent@v0.4.2/instrumentation/grpc/errors.go (about)

     1  package grpc
     2  
     3  import (
     4  	"github.com/opentracing/opentracing-go"
     5  	"github.com/opentracing/opentracing-go/ext"
     6  	"google.golang.org/grpc/codes"
     7  	"google.golang.org/grpc/status"
     8  )
     9  
    10  // A Class is a set of types of outcomes (including errors) that will often
    11  // be handled in the same way.
    12  type Class string
    13  
    14  const (
    15  	Unknown Class = "0xx"
    16  	// Success represents outcomes that achieved the desired results.
    17  	Success Class = "2xx"
    18  	// ClientError represents errors that were the client's fault.
    19  	ClientError Class = "4xx"
    20  	// ServerError represents errors that were the server's fault.
    21  	ServerError Class = "5xx"
    22  )
    23  
    24  var classStrings = map[Class]string{
    25  	Unknown:     "Unknown (0xx)",
    26  	Success:     "Success (2xx)",
    27  	ClientError: "ClientError (4xx)",
    28  	ServerError: "ServerError (5xx)",
    29  }
    30  
    31  var codeStrings = map[codes.Code]string{
    32  	codes.OK:                 "OK",
    33  	codes.Canceled:           "Canceled",
    34  	codes.Unknown:            "Unknown",
    35  	codes.InvalidArgument:    "InvalidArgument",
    36  	codes.DeadlineExceeded:   "DeadlineExceeded",
    37  	codes.NotFound:           "NotFound",
    38  	codes.AlreadyExists:      "AlreadyExists",
    39  	codes.PermissionDenied:   "PermissionDenied",
    40  	codes.ResourceExhausted:  "ResourceExhausted",
    41  	codes.FailedPrecondition: "FailedPrecondition",
    42  	codes.Aborted:            "Aborted",
    43  	codes.OutOfRange:         "OutOfRange",
    44  	codes.Unimplemented:      "Unimplemented",
    45  	codes.Internal:           "Internal",
    46  	codes.Unavailable:        "Unavailable",
    47  	codes.DataLoss:           "DataLoss",
    48  	codes.Unauthenticated:    "Unauthenticated",
    49  }
    50  
    51  // ErrorClass returns the class of the given error
    52  func ErrorClass(err error) Class {
    53  	if s, ok := status.FromError(err); ok {
    54  		switch s.Code() {
    55  		// Success or "success"
    56  		case codes.OK, codes.Canceled:
    57  			return Success
    58  
    59  		// Client errors
    60  		case codes.InvalidArgument, codes.NotFound, codes.AlreadyExists,
    61  			codes.PermissionDenied, codes.Unauthenticated, codes.FailedPrecondition,
    62  			codes.OutOfRange:
    63  			return ClientError
    64  
    65  		// Server errors
    66  		case codes.DeadlineExceeded, codes.ResourceExhausted, codes.Aborted,
    67  			codes.Unimplemented, codes.Internal, codes.Unavailable, codes.DataLoss:
    68  			return ServerError
    69  
    70  		// Not sure
    71  		case codes.Unknown:
    72  			fallthrough
    73  		default:
    74  			return Unknown
    75  		}
    76  	}
    77  	return Unknown
    78  }
    79  
    80  // SetSpanTags sets one or more tags on the given span according to the
    81  // error.
    82  func SetSpanTags(span opentracing.Span, err error, client bool) {
    83  	c := ErrorClass(err)
    84  	code := codes.Unknown
    85  	if s, ok := status.FromError(err); ok {
    86  		code = s.Code()
    87  	}
    88  	if value, ok := codeStrings[code]; ok {
    89  		span.SetTag(Status, value)
    90  	} else {
    91  		span.SetTag(Status, uint32(code))
    92  	}
    93  	if value, ok := classStrings[c]; ok {
    94  		span.SetTag("response_class", value)
    95  	} else {
    96  		span.SetTag("response_class", string(c))
    97  	}
    98  
    99  	if err == nil {
   100  		return
   101  	}
   102  	if client || c == ServerError {
   103  		ext.Error.Set(span, true)
   104  	}
   105  }