github.com/haraldrudell/parl@v0.4.176/slow-detector-invocation.go (about)

     1  /*
     2  © 2023–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package parl
     7  
     8  import (
     9  	"strconv"
    10  	"strings"
    11  	"sync"
    12  	"sync/atomic"
    13  	"time"
    14  
    15  	"github.com/haraldrudell/parl/ptime"
    16  )
    17  
    18  // SlowDetectorInvocation is a container used by SlowDetectorCore
    19  type SlowDetectorInvocation struct {
    20  	sID       slowID
    21  	threadID  ThreadID
    22  	invoLabel string
    23  	t0        time.Time
    24  	stop      func(sdi *SlowDetectorInvocation, value ...time.Time)
    25  	sd        *SlowDetectorCore
    26  
    27  	tx        atomic.Pointer[time.Time]
    28  	lock      sync.Mutex
    29  	intervals []Interval
    30  }
    31  
    32  type Interval struct {
    33  	label string
    34  	t     time.Time
    35  }
    36  
    37  // Stop ends an invocation part of SlowDetectorCore
    38  func (sdi *SlowDetectorInvocation) Stop(value ...time.Time) {
    39  	sdi.stop(sdi, value...)
    40  }
    41  
    42  // Stop ends an invocation part of SlowDetectorCore
    43  func (sdi *SlowDetectorInvocation) Interval(label string, t ...time.Time) {
    44  	var t0 time.Time
    45  	if len(t) > 0 {
    46  		t0 = t[0]
    47  	}
    48  	if t0.IsZero() {
    49  		t0 = time.Now()
    50  	}
    51  
    52  	sdi.lock.Lock()
    53  	defer sdi.lock.Unlock()
    54  
    55  	if label == "" {
    56  		label = strconv.Itoa(len(sdi.intervals) + 1)
    57  	}
    58  	sdi.intervals = append(sdi.intervals, Interval{label: label, t: t0})
    59  }
    60  
    61  // ThreadID returns the thread ID dor the thread invoking Start
    62  func (sdi *SlowDetectorInvocation) ThreadID() (threadID ThreadID) {
    63  	return sdi.threadID
    64  }
    65  
    66  // T0 returns the effective time of the invocation of Start
    67  func (sdi *SlowDetectorInvocation) T0() (t0 time.Time) {
    68  	return sdi.t0
    69  }
    70  
    71  // Label returns the label for this invocation
    72  func (sdi *SlowDetectorInvocation) Label() (label string) {
    73  	return sdi.invoLabel
    74  }
    75  
    76  // T0 returns the effective time of the invocation of Start
    77  func (sdi *SlowDetectorInvocation) Time(t time.Time) (previousT time.Time) {
    78  	var tp *time.Time
    79  	if t.IsZero() {
    80  		tp = sdi.tx.Load()
    81  	} else {
    82  		tp = sdi.tx.Swap(&t)
    83  	}
    84  	if tp != nil {
    85  		previousT = *tp
    86  	}
    87  	return
    88  }
    89  
    90  func (sdi *SlowDetectorInvocation) Intervals() (intervalStr string) {
    91  	sdi.lock.Lock()
    92  	defer sdi.lock.Unlock()
    93  
    94  	if length := len(sdi.intervals); length > 0 {
    95  		sList := make([]string, length)
    96  		t0 := sdi.t0
    97  		for i, ivl := range sdi.intervals {
    98  			t := ivl.t
    99  			sList[i] = ptime.Duration(t.Sub(t0)) + "\x20" + ivl.label
   100  			t0 = t
   101  		}
   102  		intervalStr = "\x20" + strings.Join(sList, "\x20")
   103  	}
   104  	return
   105  }