@@ -39,11 +39,37 @@ func instrumentGRPC(driverType string) grpc.UnaryServerInterceptor {
3939}
4040
4141func recordExecTime (time time.Duration , method , driverType string , err error ) {
42+ // copied from google.golang.org/grpc/server.go
43+ appStatus , ok := status .FromError (err )
44+ if ! ok {
45+ // Convert non-status application error to a status error with code
46+ // Unknown, but handle context errors specifically.
47+ appStatus = status .FromContextError (err )
48+ }
49+
4250 labels := prometheus.Labels {
4351 metric .CsiGrpcExecTimeLabelMethod : method ,
4452 metric .CsiGrpcExecTimeLabelType : driverType ,
45- metric .CsiGrpcExecTimeLabelCode : status .Code (err ).String (),
53+ metric .CsiGrpcExecTimeLabelCode : appStatus .Code ().String (),
4654 }
4755 metric .CsiGrpcExecTimeCollector .ExecCountMetric .With (labels ).Inc ()
4856 metric .CsiGrpcExecTimeCollector .ExecTimeTotalMetric .With (labels ).Add (time .Seconds ())
4957}
58+
59+ // Timeout the request a little bit earlier, to get the error message out.
60+ // reduce the timeout by 1s or 10%, whichever is smaller.
61+ func earlyTimeout (ctx context.Context , req interface {}, _ * grpc.UnaryServerInfo , handler grpc.UnaryHandler ) (interface {}, error ) {
62+ deadline , ok := ctx .Deadline ()
63+ if ! ok {
64+ return handler (ctx , req )
65+ }
66+ timeout := time .Until (deadline )
67+ if time .Second < timeout / 10 {
68+ deadline = deadline .Add (- time .Second )
69+ } else {
70+ deadline = deadline .Add (- timeout / 10 )
71+ }
72+ ctx , cancel := context .WithDeadline (ctx , deadline )
73+ defer cancel ()
74+ return handler (ctx , req )
75+ }
0 commit comments