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  }