105 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package perf
 | 
						|
 | 
						|
import (
 | 
						|
	"log"
 | 
						|
	"runtime"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
type Timer struct {
 | 
						|
	started time.Time
 | 
						|
	log     bool
 | 
						|
	name    string
 | 
						|
	marked  bool
 | 
						|
}
 | 
						|
 | 
						|
func NewTimer(opts ...timerOpt) (t *Timer) {
 | 
						|
	t = &Timer{
 | 
						|
		started: time.Now(),
 | 
						|
	}
 | 
						|
	for _, o := range opts {
 | 
						|
		o(t)
 | 
						|
	}
 | 
						|
	if t.log && t.name != "" {
 | 
						|
		log.Printf("starting timer %q", t.name)
 | 
						|
	}
 | 
						|
	runtime.SetFinalizer(t, func(t *Timer) {
 | 
						|
		if t.marked {
 | 
						|
			return
 | 
						|
		}
 | 
						|
		log.Printf("timer %#v was never marked", t)
 | 
						|
	})
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
type timerOpt func(*Timer)
 | 
						|
 | 
						|
func Log(t *Timer) {
 | 
						|
	t.log = true
 | 
						|
}
 | 
						|
 | 
						|
func Name(name string) func(*Timer) {
 | 
						|
	return func(t *Timer) {
 | 
						|
		t.name = name
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (t *Timer) Mark(events ...string) time.Duration {
 | 
						|
	d := time.Since(t.started)
 | 
						|
	if len(events) == 0 {
 | 
						|
		if t.name == "" {
 | 
						|
			panic("no name or events specified")
 | 
						|
		}
 | 
						|
		t.addDuration(t.name, d)
 | 
						|
	} else {
 | 
						|
		for _, e := range events {
 | 
						|
			if t.name != "" {
 | 
						|
				e = t.name + "/" + e
 | 
						|
			}
 | 
						|
			t.addDuration(e, d)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return d
 | 
						|
}
 | 
						|
 | 
						|
func (t *Timer) MarkOk(ok bool) {
 | 
						|
	if ok {
 | 
						|
		t.Mark("ok")
 | 
						|
	} else {
 | 
						|
		t.Mark("not ok")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (t *Timer) MarkErr(err error) {
 | 
						|
	if err == nil {
 | 
						|
		t.Mark("success")
 | 
						|
	} else {
 | 
						|
		t.Mark("error")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (t *Timer) addDuration(desc string, d time.Duration) {
 | 
						|
	t.marked = true
 | 
						|
	mu.RLock()
 | 
						|
	e := events[desc]
 | 
						|
	mu.RUnlock()
 | 
						|
	if e == nil {
 | 
						|
		mu.Lock()
 | 
						|
		e = events[desc]
 | 
						|
		if e == nil {
 | 
						|
			e = new(Event)
 | 
						|
			e.Init()
 | 
						|
			events[desc] = e
 | 
						|
		}
 | 
						|
		mu.Unlock()
 | 
						|
	}
 | 
						|
	e.Add(d)
 | 
						|
	if t.log {
 | 
						|
		if t.name != "" {
 | 
						|
			log.Printf("timer %q got event %q after %s", t.name, desc, d)
 | 
						|
		} else {
 | 
						|
			log.Printf("marking event %q after %s", desc, d)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |