Skip to content

Commit

Permalink
fix prometheus interceptors not converting context errors to gRPC cod…
Browse files Browse the repository at this point in the history
…es (grpc-ecosystem#571)

- Previously context.(Canceled|DeadlineExceeded) would result in an
  "Unknown" grpc_code
  • Loading branch information
vtermanis authored Jun 28, 2023
1 parent bfde808 commit e895693
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 6 deletions.
14 changes: 9 additions & 5 deletions providers/prometheus/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ import (
"google.golang.org/grpc/status"
)

// FromError returns a grpc status if error code is a valid grpc status.
func FromError(err error) (s *status.Status, ok bool) {
return status.FromError(err)

// TODO: @yashrsharma44 - discuss if we require more error handling from the previous package
// FromError returns a grpc status. If the error code is neither a valid grpc status nor a context error, codes.Unknown
// will be set.
func FromError(err error) *status.Status {
s, ok := status.FromError(err)
// Mirror what the grpc server itself does, i.e. also convert context errors to status
if !ok {
s = status.FromContextError(err)
}
return s
}

// A CounterOption lets you add options to Counter metrics using With* funcs.
Expand Down
2 changes: 1 addition & 1 deletion providers/prometheus/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type reporter struct {

func (r *reporter) PostCall(err error, rpcDuration time.Duration) {
// get status code from error
status, _ := FromError(err)
status := FromError(err)
code := status.Code()

// perform handling of metrics from code
Expand Down
12 changes: 12 additions & 0 deletions providers/prometheus/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,18 @@ func (s *ServerInterceptorTestSuite) TestStreamingIncrementsMetrics() {
s.serverMetrics.serverHandledHistogram.WithLabelValues("server_stream", testpb.TestServiceFullName, "PingList"))
}

func (s *ServerInterceptorTestSuite) TestContextCancelledTreatedAsStatus() {
ctx, cancel := context.WithCancel(context.TODO())
defer cancel()

stream, _ := s.Client.PingStream(ctx)
stream.Send(&testpb.PingStreamRequest{})
cancel()

requireValueWithRetry(s.SimpleCtx(), s.T(), 1,
s.serverMetrics.serverHandledCounter.WithLabelValues("bidi_stream", testpb.TestServiceFullName, "PingStream", "Canceled"))
}

// fetchPrometheusLines does mocked HTTP GET request against real prometheus handler to get the same view that Prometheus
// would have while scraping this endpoint.
// Order of matching label vales does not matter.
Expand Down

0 comments on commit e895693

Please sign in to comment.