2013-02-12 05:36:06 +04:00
|
|
|
// Copyright (c) 2012, Matt T. Proud
|
|
|
|
// All rights reserved.
|
|
|
|
//
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
2012-05-20 01:59:25 +04:00
|
|
|
|
|
|
|
package metrics
|
|
|
|
|
|
|
|
import (
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2013-02-12 05:36:06 +04:00
|
|
|
// This callback is called upon the completion of the timer—i.e., when it stops.
|
2012-05-20 01:59:25 +04:00
|
|
|
type CompletionCallback func(duration time.Duration)
|
|
|
|
|
2013-02-12 05:36:06 +04:00
|
|
|
// This is meant to capture a function that a StopWatch can call for purposes
|
|
|
|
// of instrumentation.
|
2012-05-20 01:59:25 +04:00
|
|
|
type InstrumentableCall func()
|
|
|
|
|
2013-02-12 05:36:06 +04:00
|
|
|
// StopWatch is the structure that captures instrumentation for durations.
|
2012-05-24 22:02:44 +04:00
|
|
|
|
2013-02-12 05:36:06 +04:00
|
|
|
// N.B.(mtp): A major limitation hereof is that the StopWatch protocol cannot
|
|
|
|
// retain instrumentation if a panic percolates within the context that is
|
|
|
|
// being measured.
|
2013-01-19 17:48:30 +04:00
|
|
|
type StopWatch interface {
|
|
|
|
Stop() time.Duration
|
|
|
|
}
|
|
|
|
|
|
|
|
type stopWatch struct {
|
2012-05-20 01:59:25 +04:00
|
|
|
endTime time.Time
|
|
|
|
onCompletion CompletionCallback
|
2013-01-19 17:48:30 +04:00
|
|
|
startTime time.Time
|
2012-05-20 01:59:25 +04:00
|
|
|
}
|
|
|
|
|
2013-02-12 05:36:06 +04:00
|
|
|
// Return a new StopWatch that is ready for instrumentation.
|
2013-01-19 17:48:30 +04:00
|
|
|
func Start(onCompletion CompletionCallback) StopWatch {
|
|
|
|
return &stopWatch{
|
2012-05-20 01:59:25 +04:00
|
|
|
onCompletion: onCompletion,
|
2013-01-19 17:48:30 +04:00
|
|
|
startTime: time.Now(),
|
2012-05-20 01:59:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-12 05:36:06 +04:00
|
|
|
// Stop the StopWatch returning the elapsed duration of its lifetime while
|
|
|
|
// firing an optional CompletionCallback in the background.
|
2013-01-19 17:48:30 +04:00
|
|
|
func (s *stopWatch) Stop() time.Duration {
|
2012-05-20 01:59:25 +04:00
|
|
|
s.endTime = time.Now()
|
|
|
|
duration := s.endTime.Sub(s.startTime)
|
|
|
|
|
|
|
|
if s.onCompletion != nil {
|
|
|
|
go s.onCompletion(duration)
|
|
|
|
}
|
|
|
|
|
|
|
|
return duration
|
|
|
|
}
|
|
|
|
|
2013-02-12 05:36:06 +04:00
|
|
|
// Provide a quick way of instrumenting a InstrumentableCall and emitting its
|
|
|
|
// duration.
|
2012-05-20 01:59:25 +04:00
|
|
|
func InstrumentCall(instrumentable InstrumentableCall, onCompletion CompletionCallback) time.Duration {
|
|
|
|
s := Start(onCompletion)
|
|
|
|
instrumentable()
|
|
|
|
return s.Stop()
|
|
|
|
}
|