@@ -16,11 +16,15 @@ package etcdserver
16
16
17
17
import (
18
18
"fmt"
19
+ "reflect"
20
+ "strings"
19
21
"time"
20
22
21
23
"github.com/coreos/etcd/etcdserver/api/membership"
22
24
"github.com/coreos/etcd/etcdserver/api/rafthttp"
25
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
23
26
"github.com/coreos/etcd/pkg/types"
27
+ "github.com/golang/protobuf/proto"
24
28
25
29
"go.uber.org/zap"
26
30
)
@@ -99,15 +103,40 @@ func (nc *notifier) notify(err error) {
99
103
close (nc .c )
100
104
}
101
105
102
- func warnOfExpensiveRequest (lg * zap.Logger , now time.Time , stringer fmt.Stringer ) {
103
- warnOfExpensiveGenericRequest (lg , now , stringer , "" )
106
+ func warnOfExpensiveRequest (lg * zap.Logger , now time.Time , reqStringer fmt.Stringer , respMsg proto.Message , err error ) {
107
+ var resp string
108
+ if ! isNil (respMsg ) {
109
+ resp = fmt .Sprintf ("<size:%s>" , proto .Size (respMsg ))
110
+ }
111
+ warnOfExpensiveGenericRequest (lg , now , reqStringer , "" , resp , err )
112
+ }
113
+
114
+ func warnOfExpensiveReadOnlyTxnRequest (lg * zap.Logger , now time.Time , reqStringer fmt.Stringer , txnResponse * pb.TxnResponse , err error ) {
115
+ var resp string
116
+ if ! isNil (txnResponse ) {
117
+ var resps []string
118
+ for _ , r := range txnResponse .Responses {
119
+ switch op := r .Response .(type ) {
120
+ case * pb.ResponseOp_ResponseRange :
121
+ resps = append (resps , fmt .Sprintf ("<range_response_count:%d>" , len (op .ResponseRange .Kvs )))
122
+ default :
123
+ // only range responses should be in a read only txn request
124
+ }
125
+ }
126
+ resp = fmt .Sprintf ("<responses:<%s> size:%s>" , strings .Join (resps , " " ), proto .Size (txnResponse ))
127
+ }
128
+ warnOfExpensiveGenericRequest (lg , now , reqStringer , "read-only range " , resp , err )
104
129
}
105
130
106
- func warnOfExpensiveReadOnlyRangeRequest (lg * zap.Logger , now time.Time , stringer fmt.Stringer ) {
107
- warnOfExpensiveGenericRequest (lg , now , stringer , "read-only range " )
131
+ func warnOfExpensiveReadOnlyRangeRequest (lg * zap.Logger , now time.Time , reqStringer fmt.Stringer , rangeResponse * pb.RangeResponse , err error ) {
132
+ var resp string
133
+ if ! isNil (rangeResponse ) {
134
+ resp = fmt .Sprintf ("<range_response_count:%d size:%s>" , len (rangeResponse .Kvs ), proto .Size (rangeResponse ))
135
+ }
136
+ warnOfExpensiveGenericRequest (lg , now , reqStringer , "read-only range " , resp , err )
108
137
}
109
138
110
- func warnOfExpensiveGenericRequest (lg * zap.Logger , now time.Time , stringer fmt.Stringer , prefix string ) {
139
+ func warnOfExpensiveGenericRequest (lg * zap.Logger , now time.Time , reqStringer fmt.Stringer , prefix string , resp string , err error ) {
111
140
// TODO: add metrics
112
141
d := time .Since (now )
113
142
if d > warnApplyDuration {
@@ -117,11 +146,23 @@ func warnOfExpensiveGenericRequest(lg *zap.Logger, now time.Time, stringer fmt.S
117
146
zap .Duration ("took" , d ),
118
147
zap .Duration ("expected-duration" , warnApplyDuration ),
119
148
zap .String ("prefix" , prefix ),
120
- zap .String ("request" , stringer .String ()),
149
+ zap .String ("request" , reqStringer .String ()),
150
+ zap .String ("response" , resp ),
151
+ zap .Error (err ),
121
152
)
122
153
} else {
123
- plog .Warningf ("%srequest %q took too long (%v) to execute" , prefix , stringer .String (), d )
154
+ var result string
155
+ if err != nil {
156
+ result = fmt .Sprintf ("<error:%v>" , err )
157
+ } else {
158
+ result = resp
159
+ }
160
+ plog .Warningf ("%srequest %q with result %q took too long (%v) to execute" , prefix , reqStringer .String (), result , d )
124
161
}
125
162
slowApplies .Inc ()
126
163
}
127
164
}
165
+
166
+ func isNil (msg proto.Message ) bool {
167
+ return msg == nil || reflect .ValueOf (msg ).IsNil ()
168
+ }
0 commit comments