github.com/letsencrypt/trillian@v1.1.2-0.20180615153820-ae375a99d36a/monitoring/rpc_stats_interceptor_test.go (about) 1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package monitoring_test 16 17 import ( 18 "context" 19 "errors" 20 "fmt" 21 "testing" 22 "time" 23 24 "github.com/google/trillian/monitoring" 25 "github.com/google/trillian/util" 26 "google.golang.org/grpc" 27 ) 28 29 // Arbitrary time for use in tests 30 var fakeTime = time.Date(2016, 10, 3, 12, 38, 27, 36, time.UTC) 31 32 type recordingUnaryHandler struct { 33 // ctx and req are recorded on invocation 34 ctx context.Context 35 req interface{} 36 // rsp and err are returned on invocation 37 rsp interface{} 38 err error 39 } 40 41 func (r recordingUnaryHandler) handler() grpc.UnaryHandler { 42 return func(ctx context.Context, req interface{}) (interface{}, error) { 43 r.ctx = ctx 44 r.req = req 45 return r.rsp, r.err 46 } 47 } 48 49 func TestSingleRequests(t *testing.T) { 50 var tests = []struct { 51 name string 52 method string 53 handler recordingUnaryHandler 54 timeSource util.IncrementingFakeTimeSource 55 }{ 56 // This is an OK request with 500ms latency 57 { 58 name: "ok_request", 59 method: "getmethod", 60 handler: recordingUnaryHandler{req: "OK", err: nil}, 61 timeSource: util.IncrementingFakeTimeSource{ 62 BaseTime: fakeTime, 63 Increments: []time.Duration{0, time.Millisecond * 500}, 64 }, 65 }, 66 // This is an errored request with 3000ms latency 67 { 68 name: "error_request", 69 method: "setmethod", 70 handler: recordingUnaryHandler{err: errors.New("bang")}, 71 timeSource: util.IncrementingFakeTimeSource{ 72 BaseTime: fakeTime, 73 Increments: []time.Duration{0, time.Millisecond * 3000}, 74 }, 75 }, 76 } 77 78 for _, test := range tests { 79 prefix := fmt.Sprintf("test_%s", test.name) 80 stats := monitoring.NewRPCStatsInterceptor(&test.timeSource, prefix, monitoring.InertMetricFactory{}) 81 i := stats.Interceptor() 82 83 // Invoke the test handler wrapped by the interceptor. 84 got, err := i(context.Background(), "wibble", &grpc.UnaryServerInfo{FullMethod: test.method}, test.handler.handler()) 85 86 // Check the interceptor passed through the results. 87 if got != test.handler.rsp || (err != nil) != (test.handler.err != nil) { 88 t.Errorf("interceptor(%s)=%v,%v; want %v,%v", test.name, got, err, test.handler.rsp, test.handler.err) 89 } 90 91 // Now check the resulting state of the metrics. 92 if got, want := stats.ReqCount.Value(test.method), 1.0; got != want { 93 t.Errorf("stats.ReqCount=%v; want %v", got, want) 94 } 95 wantLatency := test.timeSource.Increments[1].Seconds() 96 wantErrors := 0.0 97 wantSuccess := 0.0 98 if test.handler.err == nil { 99 wantSuccess = 1.0 100 } else { 101 wantErrors = 1.0 102 } 103 if got := stats.ReqSuccessCount.Value(test.method); got != wantSuccess { 104 t.Errorf("stats.ReqSuccessCount=%v; want %v", got, wantSuccess) 105 } 106 if got := stats.ReqErrorCount.Value(test.method); got != wantErrors { 107 t.Errorf("stats.ReqErrorCount=%v; want %v", got, wantSuccess) 108 } 109 110 if gotCount, gotSum := stats.ReqSuccessLatency.Info(test.method); gotCount != uint64(wantSuccess) { 111 t.Errorf("stats.ReqSuccessLatency.Count=%v; want %v", gotCount, wantSuccess) 112 } else if gotSum != wantLatency*wantSuccess { 113 t.Errorf("stats.ReqSuccessLatency.Sum=%v; want %v", gotSum, wantLatency*wantSuccess) 114 } 115 if gotCount, gotSum := stats.ReqErrorLatency.Info(test.method); gotCount != uint64(wantErrors) { 116 t.Errorf("stats.ReqErrorLatency.Count=%v; want %v", gotCount, wantErrors) 117 } else if gotSum != wantLatency*wantErrors { 118 t.Errorf("stats.ReqErrorLatency.Sum=%v; want %v", gotSum, wantLatency*wantErrors) 119 } 120 } 121 } 122 123 func TestMultipleOKRequestsTotalLatency(t *testing.T) { 124 // We're going to make 3 requests so set up the time source appropriately 125 ts := util.IncrementingFakeTimeSource{ 126 BaseTime: fakeTime, 127 Increments: []time.Duration{ 128 0, 129 time.Millisecond * 500, 130 0, 131 time.Millisecond * 2000, 132 0, 133 time.Millisecond * 1337, 134 }, 135 } 136 handler := recordingUnaryHandler{rsp: "OK", err: nil} 137 stats := monitoring.NewRPCStatsInterceptor(&ts, "test_multi_ok", monitoring.InertMetricFactory{}) 138 i := stats.Interceptor() 139 140 for r := 0; r < 3; r++ { 141 rsp, err := i(context.Background(), "wibble", &grpc.UnaryServerInfo{FullMethod: "testmethod"}, handler.handler()) 142 if rsp != "OK" || err != nil { 143 t.Fatalf("interceptor()=%v,%v; want 'OK',nil", rsp, err) 144 } 145 } 146 count, sum := stats.ReqSuccessLatency.Info("testmethod") 147 if wantCount, wantSum := uint64(3), time.Duration(3837*time.Millisecond).Seconds(); count != wantCount || sum != wantSum { 148 t.Errorf("stats.ReqSuccessLatency.Info=%v,%v; want %v,%v", count, sum, wantCount, wantSum) 149 } 150 } 151 152 func TestMultipleErrorRequestsTotalLatency(t *testing.T) { 153 // We're going to make 3 requests so set up the time source appropriately 154 ts := util.IncrementingFakeTimeSource{ 155 BaseTime: fakeTime, 156 Increments: []time.Duration{ 157 0, 158 time.Millisecond * 427, 159 0, 160 time.Millisecond * 1066, 161 0, 162 time.Millisecond * 1123, 163 }, 164 } 165 handler := recordingUnaryHandler{rsp: "", err: errors.New("bang")} 166 stats := monitoring.NewRPCStatsInterceptor(&ts, "test_multi_err", monitoring.InertMetricFactory{}) 167 i := stats.Interceptor() 168 169 for r := 0; r < 3; r++ { 170 _, err := i(context.Background(), "wibble", &grpc.UnaryServerInfo{FullMethod: "testmethod"}, handler.handler()) 171 if err == nil { 172 t.Fatalf("interceptor()=_,%v; want _,'bang'", err) 173 } 174 } 175 176 count, sum := stats.ReqErrorLatency.Info("testmethod") 177 if wantCount, wantSum := uint64(3), 2.6160; count != wantCount || sum != wantSum { 178 t.Errorf("stats.ReqSuccessLatency.Info=%v,%v; want %v,%v", count, sum, wantCount, wantSum) 179 } 180 }