Skip to content

Commit

Permalink
Merge pull request #345 from nr-swilloughby/344_grpc_tests
Browse files Browse the repository at this point in the history
correct typo in testcases
  • Loading branch information
nr-swilloughby authored Jul 16, 2021
2 parents fb48c02 + 3b6008f commit b1d4b0b
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 37 deletions.
80 changes: 45 additions & 35 deletions v3/integrations/nrgrpc/nrgrpc_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

//
// This integration instruments grpc service calls via
// UnaryServerInterceptor() and StreamServerInterceptor() functions.
// UnaryServerInterceptor and StreamServerInterceptor functions.
//
// The results of these calls are reported as errors or as informational
// messages (of levels OK, Info, Warning, or Error) based on the gRPC status
Expand All @@ -23,9 +23,9 @@
//
// The disposition of each, in terms of how to report each of the various
// gRPC status codes, is determined by a built-in set of defaults. These
// may be overridden on a case-by-case basis using WithStatusHandler()
// options to each UnaryServerInterceptor() or StreamServerInterceptor()
// call, or globally via the Configure() function.
// may be overridden on a case-by-case basis using WithStatusHandler
// options to each UnaryServerInterceptor or StreamServerInterceptor
// call, or globally via the Configure function.
//
// Full example:
// https://github.com/newrelic/go-agent/blob/master/v3/integrations/nrgrpc/example/server/server.go
Expand Down Expand Up @@ -111,13 +111,17 @@ var interceptorStatusHandlerRegistry = statusHandlerMap{
codes.Unauthenticated: InfoInterceptorStatusHandler,
}

type handlerOption func(statusHandlerMap)
//
// HandlerOption is the type for options passed to the interceptor
// functions to specify gRPC status handlers.
//
type HandlerOption func(statusHandlerMap)

//
// WithStatusHandler() indicates a handler function to be used to
// WithStatusHandler indicates a handler function to be used to
// report the indicated gRPC status. Zero or more of these may be
// given to the Configure(), StreamServiceInterceptor(), or
// UnaryServiceInterceptor() functions.
// given to the Configure, StreamServiceInterceptor, or
// UnaryServiceInterceptor functions.
//
// The ErrorHandler parameter is generally one of the provided standard
// reporting functions:
Expand All @@ -142,45 +146,50 @@ type handlerOption func(statusHandlerMap)
// If you wish to use your custom handler for a code such as codes.NotFound, you would
// include the parameter
// WithStatusHandler(codes.NotFound, myHandler)
// to your Configure(), StreamServiceInterceptor(), or UnaryServiceInterceptor() function.
// to your Configure, StreamServiceInterceptor, or UnaryServiceInterceptor function.
//
func WithStatusHandler(c codes.Code, h ErrorHandler) handlerOption {
func WithStatusHandler(c codes.Code, h ErrorHandler) HandlerOption {
return func(m statusHandlerMap) {
m[c] = h
}
}

//
// Configure() takes a list of WithStatusHandler() options and sets them
// Configure takes a list of WithStatusHandler options and sets them
// as the new default handlers for the specified gRPC status codes, in the same
// way as if WithStatusHandler() were given to the StreamServiceInterceptor()
// or UnaryServiceInterceptor() functions (q.v.); however, in this case the new handlers
// way as if WithStatusHandler were given to the StreamServiceInterceptor
// or UnaryServiceInterceptor functions (q.v.); however, in this case the new handlers
// become the default for any subsequent interceptors created by the above functions.
//
func Configure(options ...handlerOption) {
func Configure(options ...HandlerOption) {
for _, option := range options {
option(interceptorStatusHandlerRegistry)
}
}

//
// Standard handler: IGNORE
// This does not report anything at all in the context.
// IgnoreInterceptorStatusHandler is our standard handler for
// gRPC statuses which we want to ignore (in terms of any gRPC-specific
// reporting on the transaction).
//
func IgnoreInterceptorStatusHandler(_ context.Context, _ *newrelic.Transaction, _ *status.Status) {}

//
// Standard handler: OK
// Reports only that the RPC call was successful by setting the web response header
// value.
// OKInterceptorStatusHandler is our standard handler for
// gRPC statuses which we want to report as being successful, as with the
// status code OK.
//
// This adds no additional attributes on the transaction other than
// the fact that it was successful.
//
func OKInterceptorStatusHandler(ctx context.Context, txn *newrelic.Transaction, s *status.Status) {
txn.SetWebResponse(nil).WriteHeader(int(codes.OK))
}

//
// Standard handler: ERROR
// Reports the transaction as an error, with the relevant error messages and
// ErrorInterceptorStatusHandler is our standard handler for
// gRPC statuses which we want to report as being errors,
// with the relevant error messages and
// contextual information gleaned from the error value received from the RPC call.
//
func ErrorInterceptorStatusHandler(ctx context.Context, txn *newrelic.Transaction, s *status.Status) {
Expand All @@ -194,11 +203,10 @@ func ErrorInterceptorStatusHandler(ctx context.Context, txn *newrelic.Transactio
txn.AddAttribute("GrpcStatusCode", s.Code().String())
}

// examples
// Class "LoginError", Attr: "username": username

//
// Standard handler: WARNING
// WarningInterceptorStatusHandler is our standard handler for
// gRPC statuses which we want to report as warnings.
//
// Reports the transaction's status with attributes containing information gleaned
// from the error value returned, but does not count this as an error.
//
Expand All @@ -210,7 +218,9 @@ func WarningInterceptorStatusHandler(ctx context.Context, txn *newrelic.Transact
}

//
// Standard handler: INFO
// InfoInterceptorStatusHandler is our standard handler for
// gRPC statuses which we want to report as informational messages only.
//
// Reports the transaction's status with attributes containing information gleaned
// from the error value returned, but does not count this as an error.
//
Expand All @@ -222,14 +232,14 @@ func InfoInterceptorStatusHandler(ctx context.Context, txn *newrelic.Transaction
}

//
// Standard handler: DEFAULT
// The DefaultInterceptorStatusHander is used for any status code which is not
// DefaultInterceptorStatusHandler indicates which of our standard handlers
// will be used for any status code which is not
// explicitly assigned a handler.
//
var DefaultInterceptorStatusHandler = InfoInterceptorStatusHandler

//
// Common routine for reporting any kind of interceptor.
// reportInterceptorStatus is the common routine for reporting any kind of interceptor.
//
func reportInterceptorStatus(ctx context.Context, txn *newrelic.Transaction, handlers statusHandlerMap, err error) {
grpcStatus := status.Convert(err)
Expand Down Expand Up @@ -265,23 +275,23 @@ func reportInterceptorStatus(ctx context.Context, txn *newrelic.Transaction, han
//
// The nrgrpc integration has a built-in set of handlers for each gRPC status
// code encountered. Serious errors are reported as error traces à la the
// newrelic.NoticeError() function, while the others are reported but not
// newrelic.NoticeError function, while the others are reported but not
// counted as errors.
//
// If you wish to change this behavior, you may do so at a global level for
// all intercepted functions by calling the Configure() function, passing
// all intercepted functions by calling the Configure function, passing
// any number of WithStatusHandler(code, handler) functions as parameters.
//
// You can specify a custom set of handlers with each interceptor creation by adding
// WithStatusHandler() calls at the end of the <type>StreamInterceptor() call's parameter list,
// WithStatusHandler calls at the end of the <type>StreamInterceptor call's parameter list,
// like so:
// grpc.UnaryInterceptor(nrgrpc.UnaryServerInterceptor(app,
// nrgrpc.WithStatusHandler(codes.OutOfRange, nrgrpc.WarningInterceptorStatusHandler),
// nrgrpc.WithStatusHandler(codes.Unimplemented, nrgrpc.InfoInterceptorStatusHandler)))
// In this case, those two handlers are used (along with the current defaults for the other status
// codes) only for that interceptor.
//
func UnaryServerInterceptor(app *newrelic.Application, options ...handlerOption) grpc.UnaryServerInterceptor {
func UnaryServerInterceptor(app *newrelic.Application, options ...HandlerOption) grpc.UnaryServerInterceptor {
if app == nil {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
return handler(ctx, req)
Expand Down Expand Up @@ -332,9 +342,9 @@ func newWrappedServerStream(stream grpc.ServerStream, txn *newrelic.Transaction)
// UnaryServerInterceptor and StreamServerInterceptor to instrument unary and
// streaming calls.
//
// See the notes and examples for the UnaryServerInterceptor() function.
// See the notes and examples for the UnaryServerInterceptor function.
//
func StreamServerInterceptor(app *newrelic.Application, options ...handlerOption) grpc.StreamServerInterceptor {
func StreamServerInterceptor(app *newrelic.Application, options ...HandlerOption) grpc.StreamServerInterceptor {
if app == nil {
return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
return handler(srv, ss)
Expand Down
4 changes: 2 additions & 2 deletions v3/integrations/nrgrpc/nrgrpc_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ func TestUnaryServerInterceptorError(t *testing.T) {
}})
app.ExpectErrorEvents(t, []internal.WantEvent{{
Intrinsics: map[string]interface{}{
"error.class": "gRPC Error: DataLoss",
"error.class": "gRPC Status: DataLoss",
"error.message": "oooooops!",
"guid": internal.MatchAnything,
"priority": internal.MatchAnything,
Expand Down Expand Up @@ -606,7 +606,7 @@ func TestStreamServerInterceptorError(t *testing.T) {
}})
app.ExpectErrorEvents(t, []internal.WantEvent{{
Intrinsics: map[string]interface{}{
"error.class": "gRPC Error: DataLoss",
"error.class": "gRPC Status: DataLoss",
"error.message": "oooooops!",
"guid": internal.MatchAnything,
"priority": internal.MatchAnything,
Expand Down

0 comments on commit b1d4b0b

Please sign in to comment.