diff --git a/extraction/processor.go b/extraction/processor.go index e832452..2d9b98c 100644 --- a/extraction/processor.go +++ b/extraction/processor.go @@ -24,7 +24,7 @@ import ( // consumption. type ProcessOptions struct { // Timestamp is added to each value interpreted from the stream. - Timestamp time.Time + Timestamp model.Timestamp } // Ingester consumes result streams in whatever way is desired by the user. diff --git a/model/sample.go b/model/sample.go index 8f5db32..5e2134a 100644 --- a/model/sample.go +++ b/model/sample.go @@ -13,14 +13,10 @@ package model -import ( - "time" -) - type Sample struct { Metric Metric Value SampleValue - Timestamp time.Time + Timestamp Timestamp } func (s *Sample) Equal(o *Sample) bool { diff --git a/model/timestamp.go b/model/timestamp.go new file mode 100644 index 0000000..1b8479f --- /dev/null +++ b/model/timestamp.go @@ -0,0 +1,91 @@ +// Copyright 2013 Prometheus Team +// 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 model + +import ( + "fmt" + native_time "time" +) + +// TODO(julius): Should this use milliseconds/nanoseconds instead? This is +// mostly hidden from the user of these types when using the +// methods below, so it will be easy to change this later +// without requiring significant user code changes. + +// Time in seconds since the epoch (January 1, 1970 UTC). +type Timestamp int64 + +const ( + // The minimum supported time resolution. This has to be at least + // native_time.Second in order for the code below to work. + MinimumTick = native_time.Second + // The timestamp duration equivalent to one second. + second = int64(native_time.Second / MinimumTick) +) + +// Equal reports whether two timestamps represent the same instant. +func (t Timestamp) Equal(o Timestamp) bool { + return t == o +} + +// Before reports whether the timestamp t is before o. +func (t Timestamp) Before(o Timestamp) bool { + return t < o +} + +// Before reports whether the timestamp t is after o. +func (t Timestamp) After(o Timestamp) bool { + return t > o +} + +// Add returns the Timestamp t + d. +func (t Timestamp) Add(d native_time.Duration) Timestamp { + return t + Timestamp(d/MinimumTick) +} + +// Sub returns the Duration t - o. +func (t Timestamp) Sub(o Timestamp) native_time.Duration { + return native_time.Duration(t-o) * MinimumTick +} + +// Time returns the time.Time representation of t. +func (t Timestamp) Time() native_time.Time { + return native_time.Unix(int64(t)/second, (int64(t) % second)) +} + +// Unix returns t as a Unix time, the number of seconds elapsed +// since January 1, 1970 UTC. +func (t Timestamp) Unix() int64 { + return int64(t) / second +} + +// String returns a string representation of the timestamp. +func (t Timestamp) String() string { + return fmt.Sprint(int64(t)) +} + +// Now returns the current time as a Timestamp. +func Now() Timestamp { + return TimestampFromTime(native_time.Now()) +} + +// TimestampFromTime returns the Timestamp equivalent to the time.Time t. +func TimestampFromTime(t native_time.Time) Timestamp { + return TimestampFromUnix(t.Unix()) +} + +// TimestampFromUnix returns the Timestamp equivalent to the Unix timestamp t. +func TimestampFromUnix(t int64) Timestamp { + return Timestamp(t * second) +} diff --git a/model/timestamp_test.go b/model/timestamp_test.go new file mode 100644 index 0000000..d2faf6e --- /dev/null +++ b/model/timestamp_test.go @@ -0,0 +1,83 @@ +// Copyright 2013 Prometheus Team +// 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 model + +import ( + "testing" + native_time "time" +) + +func TestComparators(t *testing.T) { + t1a := TimestampFromUnix(0) + t1b := TimestampFromUnix(0) + t2 := TimestampFromUnix(2*second - 1) + + if !t1a.Equal(t1b) { + t.Fatalf("Expected %s to be equal to %s", t1a, t1b) + } + if t1a.Equal(t2) { + t.Fatalf("Expected %s to not be equal to %s", t1a, t2) + } + + if !t1a.Before(t2) { + t.Fatalf("Expected %s to be before %s", t1a, t2) + } + if t1a.Before(t1b) { + t.Fatalf("Expected %s to not be before %s", t1a, t1b) + } + + if !t2.After(t1a) { + t.Fatalf("Expected %s to be after %s", t2, t1a) + } + if t1b.After(t1a) { + t.Fatalf("Expected %s to not be after %s", t1b, t1a) + } +} + +func TestTimestampConversions(t *testing.T) { + unix := int64(1136239445) + t1 := native_time.Unix(unix, 0) + t2 := native_time.Unix(unix, second-1) + + ts := TimestampFromUnix(unix) + if !ts.Time().Equal(t1) { + t.Fatalf("Expected %s, got %s", t1, ts.Time()) + } + + // Test available precision. + ts = TimestampFromTime(t2) + if !ts.Time().Equal(t1) { + t.Fatalf("Expected %s, got %s", t1, ts.Time()) + } + + if ts.Unix() != unix { + t.Fatalf("Expected %d, got %d", unix, ts.Unix()) + } +} + +func TestDuration(t *testing.T) { + duration := native_time.Second + native_time.Minute + native_time.Hour + goTime := native_time.Unix(1136239445, 0) + + ts := TimestampFromTime(goTime) + if !goTime.Add(duration).Equal(ts.Add(duration).Time()) { + t.Fatalf("%d. Expected %s to be equal to %s", goTime.Add(duration), ts.Add(duration)) + } + + earlier := ts.Add(-duration) + delta := ts.Sub(earlier) + if delta != duration { + t.Fatalf("%d. Expected %s to be equal to %s", delta, duration) + } +}