github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/system/trace/trace.go (about)

     1  package trace
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  )
     7  
     8  type IElapsedTimeInfos interface {
     9  	AddInfo(key string, info string)
    10  	Dump(logger interface{})
    11  	SetElapsedTime(elapsedTime int64)
    12  	GetElapsedTime() int64
    13  }
    14  
    15  func SetInfoObject(e IElapsedTimeInfos) {
    16  	if e != nil {
    17  		elapsedInfo = e
    18  	}
    19  }
    20  
    21  var elapsedInfo IElapsedTimeInfos = &EmptyTimeInfo{}
    22  
    23  func GetElapsedInfo() IElapsedTimeInfos {
    24  	return elapsedInfo
    25  }
    26  
    27  type Tracer struct {
    28  	name             string
    29  	startTime        time.Time
    30  	lastPin          string
    31  	lastPinStartTime time.Time
    32  	pins             []string
    33  	intervals        []time.Duration
    34  	elapsedTime      time.Duration
    35  
    36  	pinMap        map[string]time.Duration
    37  	enableSummary bool
    38  
    39  	wls *WorkloadStatistic
    40  }
    41  
    42  func NewTracer(name string) *Tracer {
    43  	t := &Tracer{
    44  		startTime: time.Now(),
    45  		name:      name,
    46  		pinMap:    make(map[string]time.Duration),
    47  	}
    48  	return t
    49  }
    50  
    51  func (t *Tracer) EnableSummary() {
    52  	t.enableSummary = true
    53  }
    54  
    55  func (t *Tracer) SetWorkloadStatistic(wls *WorkloadStatistic) {
    56  	t.wls = wls
    57  }
    58  
    59  func (t *Tracer) Pin(format string, args ...interface{}) {
    60  	t.pinByFormat(fmt.Sprintf(format, args...))
    61  }
    62  
    63  func (t *Tracer) pinByFormat(tag string) {
    64  	if len(tag) == 0 {
    65  		//panic("invalid tag")
    66  		return
    67  	}
    68  
    69  	if len(t.pins) > 100 {
    70  		// 100 pins limitation
    71  		return
    72  	}
    73  
    74  	now := time.Now()
    75  
    76  	if len(t.lastPin) > 0 {
    77  		t.pins = append(t.pins, t.lastPin)
    78  		duration := now.Sub(t.lastPinStartTime)
    79  		t.intervals = append(t.intervals, duration)
    80  		if t.enableSummary {
    81  			insertElapse(t.lastPin, duration.Milliseconds())
    82  		}
    83  
    84  		if t.wls != nil {
    85  			t.wls.Add(t.lastPin, now, duration)
    86  		}
    87  	}
    88  	t.lastPinStartTime = now
    89  	t.lastPin = tag
    90  }
    91  
    92  func (t *Tracer) Format() string {
    93  	if len(t.pins) == 0 {
    94  		now := time.Now()
    95  		t.elapsedTime = now.Sub(t.startTime)
    96  		return fmt.Sprintf("%dms", t.elapsedTime.Milliseconds())
    97  	}
    98  
    99  	t.Pin("_")
   100  
   101  	now := time.Now()
   102  	t.elapsedTime = now.Sub(t.startTime)
   103  	info := fmt.Sprintf("%s<%dms>",
   104  		t.name,
   105  		t.elapsedTime.Milliseconds(),
   106  	)
   107  
   108  	for i := range t.pins {
   109  		info += fmt.Sprintf(", %s<%dms>", t.pins[i], t.intervals[i].Milliseconds())
   110  	}
   111  	return info
   112  }
   113  
   114  func (t *Tracer) RepeatingPin(format string, args ...interface{}) {
   115  	if len(args) == 0 {
   116  		t.repeatingPinByFormat(format)
   117  	} else {
   118  		t.repeatingPinByFormat(fmt.Sprintf(format, args...))
   119  	}
   120  }
   121  
   122  func (t *Tracer) repeatingPinByFormat(tag string) {
   123  	if len(tag) == 0 {
   124  		//panic("invalid tag")
   125  		return
   126  	}
   127  
   128  	if len(t.pinMap) > 100 {
   129  		// 100 pins limitation
   130  		return
   131  	}
   132  
   133  	now := time.Now()
   134  
   135  	if len(t.lastPin) > 0 {
   136  		t.pinMap[t.lastPin] += now.Sub(t.lastPinStartTime)
   137  	}
   138  	t.lastPinStartTime = now
   139  	t.lastPin = tag
   140  }
   141  
   142  func (t *Tracer) FormatRepeatingPins(ignoredTags string) string {
   143  	var info, comma string
   144  
   145  	if len(t.pinMap) == 0 {
   146  		return info
   147  	}
   148  
   149  	t.RepeatingPin("_")
   150  
   151  	for tag, interval := range t.pinMap {
   152  		if tag == ignoredTags {
   153  			continue
   154  		}
   155  		info += fmt.Sprintf("%s%s<%dms>", comma, tag, interval.Milliseconds())
   156  		comma = ", "
   157  	}
   158  	return info
   159  }
   160  
   161  func (t *Tracer) GetElapsedTime() int64 {
   162  	return t.elapsedTime.Milliseconds()
   163  }
   164  
   165  func (t *Tracer) Reset() {
   166  	t.startTime = time.Now()
   167  	t.lastPin = ""
   168  	t.lastPinStartTime = time.Date(2018, 1, 1, 1, 1, 1, 1, time.Local)
   169  	t.pins = nil
   170  	t.intervals = nil
   171  	t.pinMap = make(map[string]time.Duration)
   172  }
   173  
   174  type EmptyTimeInfo struct {
   175  }
   176  
   177  func (e *EmptyTimeInfo) AddInfo(key string, info string) {
   178  }
   179  
   180  func (e *EmptyTimeInfo) Dump(logger interface{}) {
   181  }
   182  
   183  func (e *EmptyTimeInfo) SetElapsedTime(elapsedTime int64) {
   184  }
   185  
   186  func (e *EmptyTimeInfo) GetElapsedTime() int64 {
   187  	return 0
   188  }