Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package grpcmon | 5 package grpcmon |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "time" | 8 "time" |
| 9 | 9 |
| 10 "golang.org/x/net/context" | 10 "golang.org/x/net/context" |
| 11 "google.golang.org/grpc" | 11 "google.golang.org/grpc" |
| 12 "google.golang.org/grpc/codes" | |
| 12 | 13 |
| 13 "github.com/luci/luci-go/common/clock" | 14 "github.com/luci/luci-go/common/clock" |
| 14 "github.com/luci/luci-go/common/tsmon/distribution" | 15 "github.com/luci/luci-go/common/tsmon/distribution" |
| 15 "github.com/luci/luci-go/common/tsmon/field" | 16 "github.com/luci/luci-go/common/tsmon/field" |
| 16 "github.com/luci/luci-go/common/tsmon/metric" | 17 "github.com/luci/luci-go/common/tsmon/metric" |
| 17 "github.com/luci/luci-go/common/tsmon/types" | 18 "github.com/luci/luci-go/common/tsmon/types" |
| 18 ) | 19 ) |
| 19 | 20 |
| 20 var ( | 21 var ( |
| 21 grpcServerCount = metric.NewCounter( | 22 grpcServerCount = metric.NewCounter( |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 37 // NewUnaryServerInterceptor returns an interceptor that gathers RPC handler | 38 // NewUnaryServerInterceptor returns an interceptor that gathers RPC handler |
| 38 // metrics and sends them to tsmon. | 39 // metrics and sends them to tsmon. |
| 39 // | 40 // |
| 40 // It can be optionally chained with other interceptor. The reported metrics | 41 // It can be optionally chained with other interceptor. The reported metrics |
| 41 // include time spent in this other interceptor too. | 42 // include time spent in this other interceptor too. |
| 42 // | 43 // |
| 43 // It assumes the RPC context has tsmon initialized already. | 44 // It assumes the RPC context has tsmon initialized already. |
| 44 func NewUnaryServerInterceptor(next grpc.UnaryServerInterceptor) grpc.UnaryServe rInterceptor { | 45 func NewUnaryServerInterceptor(next grpc.UnaryServerInterceptor) grpc.UnaryServe rInterceptor { |
| 45 return func(ctx context.Context, req interface{}, info *grpc.UnaryServer Info, handler grpc.UnaryHandler) (resp interface{}, err error) { | 46 return func(ctx context.Context, req interface{}, info *grpc.UnaryServer Info, handler grpc.UnaryHandler) (resp interface{}, err error) { |
| 46 started := clock.Now(ctx) | 47 started := clock.Now(ctx) |
| 48 panicing := true | |
| 47 defer func() { | 49 defer func() { |
| 48 » » » reportServerRPCMetrics(ctx, info.FullMethod, err, clock. Now(ctx).Sub(started)) | 50 » » » // We don't want to recover anything, but we want to log Internal error |
| 51 » » » // in case of a panic. We pray here reportServerRPCMetri cs is very | |
| 52 » » » // lightweight and it doesn't panic itself. | |
| 53 » » » code := codes.OK | |
| 54 » » » switch { | |
| 55 » » » case err != nil: | |
| 56 » » » » code = grpc.Code(err) | |
| 57 » » » case panicing: | |
| 58 » » » » code = codes.Internal | |
|
Vadim Sh.
2017/06/20 04:30:12
I think it used to log it as codes.OK because it s
| |
| 59 » » » } | |
| 60 » » » reportServerRPCMetrics(ctx, info.FullMethod, code, clock .Now(ctx).Sub(started)) | |
| 49 }() | 61 }() |
| 50 if next != nil { | 62 if next != nil { |
| 51 » » » return next(ctx, req, info, handler) | 63 » » » resp, err = next(ctx, req, info, handler) |
| 64 » » } else { | |
| 65 » » » resp, err = handler(ctx, req) | |
| 52 } | 66 } |
| 53 » » return handler(ctx, req) | 67 » » panicing = false // normal exit, no panic happened, disarms defe r |
| 68 » » return | |
| 54 } | 69 } |
| 55 } | 70 } |
| 56 | 71 |
| 57 // reportServerRPCMetrics sends metrics after RPC handler has finished. | 72 // reportServerRPCMetrics sends metrics after RPC handler has finished. |
| 58 func reportServerRPCMetrics(ctx context.Context, method string, err error, dur t ime.Duration) { | 73 func reportServerRPCMetrics(ctx context.Context, method string, code codes.Code, dur time.Duration) { |
| 59 » code := 0 | 74 » grpcServerCount.Add(ctx, 1, method, int(code)) |
| 60 » if err != nil { | 75 » grpcServerDuration.Add(ctx, float64(dur.Nanoseconds()/1e6), method, int( code)) |
| 61 » » code = int(grpc.Code(err)) | |
| 62 » } | |
| 63 » grpcServerCount.Add(ctx, 1, method, code) | |
| 64 » grpcServerDuration.Add(ctx, float64(dur.Nanoseconds()/1e6), method, code ) | |
| 65 } | 76 } |
| OLD | NEW |