// 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. package metrics import ( "time" ) // This callback is called upon the completion of the timer—i.e., when it stops. type CompletionCallback func(duration time.Duration) // This is meant to capture a function that a StopWatch can call for purposes // of instrumentation. type InstrumentableCall func() // StopWatch is the structure that captures instrumentation for durations. // 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. type StopWatch interface { Stop() time.Duration } type stopWatch struct { endTime time.Time onCompletion CompletionCallback startTime time.Time } // Return a new StopWatch that is ready for instrumentation. func Start(onCompletion CompletionCallback) StopWatch { return &stopWatch{ onCompletion: onCompletion, startTime: time.Now(), } } // Stop the StopWatch returning the elapsed duration of its lifetime while // firing an optional CompletionCallback in the background. func (s *stopWatch) Stop() time.Duration { s.endTime = time.Now() duration := s.endTime.Sub(s.startTime) if s.onCompletion != nil { go s.onCompletion(duration) } return duration } // Provide a quick way of instrumenting a InstrumentableCall and emitting its // duration. func InstrumentCall(instrumentable InstrumentableCall, onCompletion CompletionCallback) time.Duration { s := Start(onCompletion) instrumentable() return s.Stop() }