// Copyright (C) 2016 Space Monkey, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package monkit import ( "sync" "time" "github.com/spacemonkeygo/monkit/v3/monotime" ) // Timer is a threadsafe convenience wrapper around a DurationDist. You should // construct with NewTimer(), though the expected usage is from a Scope like // so: // // var mon = monkit.Package() // // func MyFunc() { // ... // timer := mon.Timer("event") // // perform event // timer.Stop() // ... // } // // Timers implement StatSource. type Timer struct { mtx sync.Mutex times *DurationDist } // NewTimer constructs a new Timer. func NewTimer(key SeriesKey) *Timer { return &Timer{times: NewDurationDist(key)} } // Start constructs a RunningTimer func (t *Timer) Start() *RunningTimer { return &RunningTimer{ start: monotime.Now(), t: t} } // RunningTimer should be constructed from a Timer. type RunningTimer struct { start time.Time t *Timer stopped bool } // Elapsed just returns the amount of time since the timer started func (r *RunningTimer) Elapsed() time.Duration { return time.Since(r.start) } // Stop stops the timer, adds the duration to the statistics information, and // returns the elapsed time. func (r *RunningTimer) Stop() time.Duration { elapsed := r.Elapsed() r.t.mtx.Lock() if !r.stopped { r.t.times.Insert(elapsed) r.stopped = true } r.t.mtx.Unlock() return elapsed } // Values returns the main timer values func (t *Timer) Values() *DurationDist { t.mtx.Lock() rv := t.times.Copy() t.mtx.Unlock() return rv } // Stats implements the StatSource interface func (t *Timer) Stats(cb func(key SeriesKey, field string, val float64)) { t.mtx.Lock() times := t.times.Copy() t.mtx.Unlock() times.Stats(cb) }