github.com/yandex/pandora@v0.5.32/core/aggregator/netsample/sample.go (about) 1 package netsample 2 3 import ( 4 "net" 5 "net/url" 6 "os" 7 "sync" 8 "syscall" 9 "time" 10 11 "github.com/pkg/errors" 12 ) 13 14 const ( 15 ProtoCodeError = 999 16 DiscardedShootCodeError = 777 17 DiscardedShootTag = "discarded" 18 ) 19 20 const ( 21 keyRTTMicro = iota 22 keyConnectMicro // TODO (skipor): set all for HTTP using httptrace and helper structs 23 keySendMicro 24 keyLatencyMicro 25 keyReceiveMicro 26 keyIntervalEventMicro // TODO: understand WTF is that mean and set it right. 27 keyRequestBytes 28 keyResponseBytes 29 keyErrno 30 keyProtoCode 31 fieldsNum 32 ) 33 34 func Acquire(tag string) *Sample { 35 s := samplePool.Get().(*Sample) 36 *s = Sample{ 37 timeStamp: time.Now(), 38 tags: tag, 39 } 40 return s 41 } 42 43 func releaseSample(s *Sample) { samplePool.Put(s) } 44 45 var samplePool = &sync.Pool{New: func() interface{} { return &Sample{} }} 46 47 type Sample struct { 48 timeStamp time.Time 49 tags string 50 id uint64 51 fields [fieldsNum]int 52 err error 53 } 54 55 func (s *Sample) Tags() string { return s.tags } 56 func (s *Sample) AddTag(tag string) { 57 if s.tags == "" { 58 s.tags = tag 59 return 60 } 61 s.tags += "|" + tag 62 } 63 64 func (s *Sample) ID() uint64 { return s.id } 65 func (s *Sample) SetID(id uint64) { s.id = id } 66 67 func (s *Sample) ProtoCode() int { return s.get(keyProtoCode) } 68 func (s *Sample) SetProtoCode(code int) { 69 s.set(keyProtoCode, code) 70 s.setRTT() 71 } 72 73 func (s *Sample) Err() error { return s.err } 74 func (s *Sample) SetErr(err error) { 75 s.err = err 76 s.set(keyErrno, getErrno(err)) 77 s.setRTT() 78 } 79 80 func (s *Sample) get(k int) int { return s.fields[k] } 81 func (s *Sample) set(k, v int) { s.fields[k] = v } 82 func (s *Sample) setDuration(k int, d time.Duration) { s.set(k, int(d.Nanoseconds()/1000)) } 83 func (s *Sample) setRTT() { 84 if s.get(keyRTTMicro) == 0 { 85 s.setDuration(keyRTTMicro, time.Since(s.timeStamp)) 86 } 87 } 88 89 func (s *Sample) SetUserDuration(d time.Duration) { 90 s.setDuration(keyRTTMicro, d) 91 } 92 93 func (s *Sample) GetUserDurationMicroseconds() int { 94 return s.get(keyRTTMicro) 95 } 96 func (s *Sample) SetUserProto(code int) { 97 s.set(keyProtoCode, code) 98 } 99 100 func (s *Sample) GetUserProto() int { 101 return s.get(keyProtoCode) 102 } 103 104 func (s *Sample) SetUserNet(code int) { 105 s.set(keyErrno, code) 106 } 107 108 func (s *Sample) GetUserNet() int { 109 return s.get(keyErrno) 110 } 111 112 func (s *Sample) SetConnectTime(d time.Duration) { 113 s.setDuration(keyConnectMicro, d) 114 } 115 116 func (s *Sample) GetConnectTimeMicroseconds() int { 117 return s.get(keyConnectMicro) 118 } 119 120 func (s *Sample) SetSendTime(d time.Duration) { 121 s.setDuration(keySendMicro, d) 122 } 123 124 func (s *Sample) GetSendTimeMicroseconds() int { 125 return s.get(keySendMicro) 126 } 127 128 func (s *Sample) SetLatency(d time.Duration) { 129 s.setDuration(keyLatencyMicro, d) 130 } 131 132 func (s *Sample) GetLatencyMicroseconds() int { 133 return s.get(keyLatencyMicro) 134 } 135 136 func (s *Sample) SetReceiveTime(d time.Duration) { 137 s.setDuration(keyReceiveMicro, d) 138 } 139 140 func (s *Sample) GetReceiveTimeMicroseconds() int { 141 return s.get(keyReceiveMicro) 142 } 143 144 func (s *Sample) SetRequestBytes(b int) { 145 s.set(keyRequestBytes, b) 146 } 147 148 func (s *Sample) GetRequestBytes() int { 149 return s.get(keyRequestBytes) 150 } 151 152 func (s *Sample) SetResponseBytes(b int) { 153 s.set(keyResponseBytes, b) 154 } 155 156 func (s *Sample) GetResponseBytes() int { 157 return s.get(keyResponseBytes) 158 } 159 160 func (s *Sample) String() string { 161 return string(appendPhout(s, nil, true)) 162 } 163 164 func getErrno(err error) int { 165 // 166 if e, ok := err.(net.Error); ok && e.Timeout() { 167 return 110 // Handle client Timeout as if it connection timeout 168 } 169 // stackerr.Error and etc. 170 type hasUnderlying interface { 171 Underlying() error 172 } 173 for { 174 typed, ok := err.(hasUnderlying) 175 if !ok { 176 break 177 } 178 err = typed.Underlying() 179 } 180 err = errors.Cause(err) 181 for { 182 switch typed := err.(type) { 183 case *net.OpError: 184 err = typed.Err 185 case *os.SyscallError: 186 err = typed.Err 187 case *url.Error: 188 err = typed.Err 189 case syscall.Errno: 190 return int(typed) 191 default: 192 // Legacy default. 193 return ProtoCodeError 194 } 195 } 196 } 197 198 func DiscardedShootSample() *Sample { 199 sample := &Sample{ 200 timeStamp: time.Now(), 201 tags: DiscardedShootTag, 202 } 203 sample.SetUserNet(DiscardedShootCodeError) 204 205 return sample 206 }