diff --git a/util/stats/query_stats.go b/util/stats/query_stats.go index 5e2a9ab13..206131aa8 100644 --- a/util/stats/query_stats.go +++ b/util/stats/query_stats.go @@ -50,8 +50,8 @@ func (s QueryTiming) String() string { } } -// QueryStats with all query timers mapped to durations. -type QueryStats struct { +// QueryTimings with all query timers mapped to durations. +type queryTimings struct { EvalTotalTime float64 `json:"evalTotalTime"` ResultSortTime float64 `json:"resultSortTime"` QueryPreparationTime float64 `json:"queryPreparationTime"` @@ -61,29 +61,35 @@ type QueryStats struct { ExecTotalTime float64 `json:"execTotalTime"` } +// QueryStats currently only holding query timings +type QueryStats struct { + Timings queryTimings `json:"timings,omitempty"` +} + // NewQueryStats makes a QueryStats struct with all QueryTimings found in the // given TimerGroup. func NewQueryStats(tg *TimerGroup) *QueryStats { - var qs QueryStats + var qt queryTimings for s, timer := range tg.timers { switch s { case EvalTotalTime: - qs.EvalTotalTime = timer.Duration() + qt.EvalTotalTime = timer.Duration() case ResultSortTime: - qs.ResultSortTime = timer.Duration() + qt.ResultSortTime = timer.Duration() case QueryPreparationTime: - qs.QueryPreparationTime = timer.Duration() + qt.QueryPreparationTime = timer.Duration() case InnerEvalTime: - qs.InnerEvalTime = timer.Duration() + qt.InnerEvalTime = timer.Duration() case ResultAppendTime: - qs.ResultAppendTime = timer.Duration() + qt.ResultAppendTime = timer.Duration() case ExecQueueTime: - qs.ExecQueueTime = timer.Duration() + qt.ExecQueueTime = timer.Duration() case ExecTotalTime: - qs.ExecTotalTime = timer.Duration() + qt.ExecTotalTime = timer.Duration() } } + qs := QueryStats{Timings: qt} return &qs } diff --git a/util/stats/stats_test.go b/util/stats/stats_test.go new file mode 100644 index 000000000..b56932a34 --- /dev/null +++ b/util/stats/stats_test.go @@ -0,0 +1,55 @@ +// Copyright 2015 The Prometheus Authors +// 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 stats + +import ( + "encoding/json" + "regexp" + "testing" + "time" +) + +func TestTimerGroupNewTimer(t *testing.T) { + tg := NewTimerGroup() + timer := tg.GetTimer(ExecTotalTime) + if duration := timer.Duration(); duration != 0 { + t.Errorf("Expected duration of 0, but it was %f instead.", duration) + } + minimum := 2 * time.Millisecond + timer.Start() + time.Sleep(minimum) + timer.Stop() + if duration := timer.Duration(); duration == 0 { + t.Errorf("Expected duration greater than 0, but it was %f instead.", duration) + } + if elapsed := timer.ElapsedTime(); elapsed < minimum { + t.Errorf("Expected elapsed time to be greater than time slept, elapsed was %d, and time slept was %d.", elapsed.Nanoseconds(), minimum) + } +} + +func TestQueryStatsWithTimers(t *testing.T) { + tg := NewTimerGroup() + timer := tg.GetTimer(ExecTotalTime) + timer.Start() + time.Sleep(2 * time.Millisecond) + timer.Stop() + + var qs *QueryStats + qs = NewQueryStats(tg) + actual, _ := json.Marshal(qs) + match, _ := regexp.MatchString(`[,{]"execTotalTime":\d+\.\d+[,}]`, string(actual)) + if !match { + t.Errorf("Expected timings with one non-zero entry, but got %s.", actual) + } +}