2017-04-10 20:59:45 +02:00
// Copyright 2017 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.
2016-12-04 13:16:11 +01:00
package tsdb
2017-04-18 17:22:13 +01:00
import (
"io/ioutil"
2017-08-29 00:39:17 +02:00
"math"
2017-05-23 18:13:30 +05:30
"math/rand"
2017-04-18 17:22:13 +01:00
"os"
2017-08-29 00:39:17 +02:00
"sort"
2017-04-18 17:22:13 +01:00
"testing"
2017-05-17 16:43:01 +02:00
"github.com/pkg/errors"
2017-04-18 17:22:13 +01:00
"github.com/prometheus/tsdb/labels"
2017-12-06 17:06:14 -08:00
"github.com/prometheus/tsdb/testutil"
2017-04-18 17:22:13 +01:00
)
2017-08-29 00:39:17 +02:00
func openTestDB ( t testing . TB , opts * Options ) ( db * DB , close func ( ) ) {
2017-11-21 16:45:02 +05:30
tmpdir , err := ioutil . TempDir ( "" , "test" )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-08-29 00:39:17 +02:00
2017-11-21 16:45:02 +05:30
db , err = Open ( tmpdir , nil , nil , opts )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-08-29 00:39:17 +02:00
// Do not close the test database by default as it will deadlock on test failures.
2017-08-30 18:34:54 +02:00
return db , func ( ) { os . RemoveAll ( tmpdir ) }
2017-08-29 00:39:17 +02:00
}
2017-11-13 12:16:58 +01:00
// query runs a matcher query against the querier and fully expands its data.
func query ( t testing . TB , q Querier , matchers ... labels . Matcher ) map [ string ] [ ] sample {
ss , err := q . Select ( matchers ... )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-11-13 12:16:58 +01:00
2017-04-20 14:24:35 +01:00
result := map [ string ] [ ] sample { }
for ss . Next ( ) {
series := ss . At ( )
samples := [ ] sample { }
it := series . Iterator ( )
for it . Next ( ) {
t , v := it . At ( )
samples = append ( samples , sample { t : t , v : v } )
}
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , it . Err ( ) )
2017-04-20 14:24:35 +01:00
name := series . Labels ( ) . String ( )
result [ name ] = samples
}
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , ss . Err ( ) )
2017-08-29 00:39:17 +02:00
return result
2017-04-20 14:24:35 +01:00
}
2017-04-18 17:22:13 +01:00
func TestDataAvailableOnlyAfterCommit ( t * testing . T ) {
2017-08-29 00:39:17 +02:00
db , close := openTestDB ( t , nil )
defer close ( )
2017-12-10 12:02:01 -06:00
defer db . Close ( )
2017-04-18 17:22:13 +01:00
app := db . Appender ( )
2017-08-29 00:39:17 +02:00
_ , err := app . Add ( labels . FromStrings ( "foo" , "bar" ) , 0 , 0 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-04-18 17:22:13 +01:00
2017-10-09 15:21:46 +02:00
querier , err := db . Querier ( 0 , 1 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-11-13 12:16:58 +01:00
seriesSet := query ( t , querier , labels . NewEqualMatcher ( "foo" , "bar" ) )
2017-08-29 00:39:17 +02:00
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , seriesSet , map [ string ] [ ] sample { } )
testutil . Ok ( t , querier . Close ( ) )
2017-04-18 17:22:13 +01:00
err = app . Commit ( )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-04-18 17:22:13 +01:00
2017-10-09 15:21:46 +02:00
querier , err = db . Querier ( 0 , 1 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-04-18 17:22:13 +01:00
defer querier . Close ( )
2017-11-13 12:16:58 +01:00
seriesSet = query ( t , querier , labels . NewEqualMatcher ( "foo" , "bar" ) )
2017-08-29 00:39:17 +02:00
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , seriesSet , map [ string ] [ ] sample { ` { foo="bar"} ` : [ ] sample { { t : 0 , v : 0 } } } )
2017-04-18 17:22:13 +01:00
}
func TestDataNotAvailableAfterRollback ( t * testing . T ) {
2017-08-29 00:39:17 +02:00
db , close := openTestDB ( t , nil )
defer close ( )
2017-12-10 12:02:01 -06:00
defer db . Close ( )
2017-04-18 17:22:13 +01:00
app := db . Appender ( )
2017-08-29 00:39:17 +02:00
_ , err := app . Add ( labels . FromStrings ( "foo" , "bar" ) , 0 , 0 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-04-18 17:22:13 +01:00
err = app . Rollback ( )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-04-18 17:22:13 +01:00
2017-10-09 15:21:46 +02:00
querier , err := db . Querier ( 0 , 1 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-04-18 17:22:13 +01:00
defer querier . Close ( )
2017-11-13 12:16:58 +01:00
seriesSet := query ( t , querier , labels . NewEqualMatcher ( "foo" , "bar" ) )
2017-08-29 00:39:17 +02:00
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , seriesSet , map [ string ] [ ] sample { } )
2017-04-18 17:22:13 +01:00
}
2017-04-28 15:24:28 +02:00
func TestDBAppenderAddRef ( t * testing . T ) {
2017-08-29 00:39:17 +02:00
db , close := openTestDB ( t , nil )
defer close ( )
2017-12-10 12:02:01 -06:00
defer db . Close ( )
2017-04-28 15:24:28 +02:00
2017-05-18 16:09:30 +02:00
app1 := db . Appender ( )
2017-04-28 15:24:28 +02:00
2017-09-05 11:45:18 +02:00
ref1 , err := app1 . Add ( labels . FromStrings ( "a" , "b" ) , 123 , 0 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-04-28 15:24:28 +02:00
2017-09-05 11:45:18 +02:00
// Reference should already work before commit.
err = app1 . AddFast ( ref1 , 124 , 1 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-05-17 16:43:01 +02:00
2017-05-18 16:09:30 +02:00
err = app1 . Commit ( )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-05-17 16:43:01 +02:00
2017-05-18 16:09:30 +02:00
app2 := db . Appender ( )
2017-09-05 11:45:18 +02:00
// first ref should already work in next transaction.
err = app2 . AddFast ( ref1 , 125 , 0 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-05-17 16:43:01 +02:00
2017-09-05 11:45:18 +02:00
ref2 , err := app2 . Add ( labels . FromStrings ( "a" , "b" ) , 133 , 1 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-09-05 11:45:18 +02:00
2017-12-06 17:06:14 -08:00
testutil . Assert ( t , ref1 == ref2 , "" )
2017-09-05 11:45:18 +02:00
2017-04-28 15:24:28 +02:00
// Reference must be valid to add another sample.
2017-09-05 11:45:18 +02:00
err = app2 . AddFast ( ref2 , 143 , 2 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-04-28 15:24:28 +02:00
2017-09-05 11:45:18 +02:00
err = app2 . AddFast ( 9999999 , 1 , 1 )
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , errors . Cause ( err ) , ErrNotFound )
2017-08-29 00:39:17 +02:00
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , app2 . Commit ( ) )
2017-08-29 00:39:17 +02:00
2017-10-09 15:21:46 +02:00
q , err := db . Querier ( 0 , 200 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-10-09 15:21:46 +02:00
2017-11-13 12:16:58 +01:00
res := query ( t , q , labels . NewEqualMatcher ( "a" , "b" ) )
2017-08-29 00:39:17 +02:00
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , map [ string ] [ ] sample {
2017-08-29 00:39:17 +02:00
labels . FromStrings ( "a" , "b" ) . String ( ) : [ ] sample {
{ t : 123 , v : 0 } ,
2017-09-05 11:45:18 +02:00
{ t : 124 , v : 1 } ,
{ t : 125 , v : 0 } ,
2017-08-29 00:39:17 +02:00
{ t : 133 , v : 1 } ,
{ t : 143 , v : 2 } ,
} ,
} , res )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , q . Close ( ) )
2017-04-28 15:24:28 +02:00
}
2017-05-23 18:13:30 +05:30
func TestDeleteSimple ( t * testing . T ) {
numSamples := int64 ( 10 )
2017-08-29 00:39:17 +02:00
db , close := openTestDB ( t , nil )
defer close ( )
2017-12-10 12:02:01 -06:00
defer db . Close ( )
2017-05-23 18:13:30 +05:30
app := db . Appender ( )
smpls := make ( [ ] float64 , numSamples )
for i := int64 ( 0 ) ; i < numSamples ; i ++ {
smpls [ i ] = rand . Float64 ( )
app . Add ( labels . Labels { { "a" , "b" } } , i , smpls [ i ] )
}
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , app . Commit ( ) )
2017-05-23 18:13:30 +05:30
cases := [ ] struct {
2017-08-25 13:41:46 +05:30
intervals Intervals
2017-05-23 18:13:30 +05:30
remaint [ ] int64
} {
{
2017-08-25 13:41:46 +05:30
intervals : Intervals { { 1 , 3 } , { 4 , 7 } } ,
2017-05-23 18:13:30 +05:30
remaint : [ ] int64 { 0 , 8 , 9 } ,
} ,
}
Outer :
for _ , c := range cases {
// TODO(gouthamve): Reset the tombstones somehow.
// Delete the ranges.
for _ , r := range c . intervals {
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , db . Delete ( r . Mint , r . Maxt , labels . NewEqualMatcher ( "a" , "b" ) ) )
2017-05-23 18:13:30 +05:30
}
// Compare the result.
2017-10-09 15:21:46 +02:00
q , err := db . Querier ( 0 , numSamples )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-10-09 15:21:46 +02:00
2017-11-13 12:16:58 +01:00
res , err := q . Select ( labels . NewEqualMatcher ( "a" , "b" ) )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-05-23 18:13:30 +05:30
expSamples := make ( [ ] sample , 0 , len ( c . remaint ) )
for _ , ts := range c . remaint {
expSamples = append ( expSamples , sample { ts , smpls [ ts ] } )
}
expss := newListSeriesSet ( [ ] Series {
newSeries ( map [ string ] string { "a" : "b" } , expSamples ) ,
} )
if len ( expSamples ) == 0 {
2017-12-06 17:06:14 -08:00
testutil . Assert ( t , res . Next ( ) == false , "" )
2017-05-23 18:13:30 +05:30
continue
}
for {
eok , rok := expss . Next ( ) , res . Next ( )
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , eok , rok )
2017-05-23 18:13:30 +05:30
if ! eok {
continue Outer
}
sexp := expss . At ( )
sres := res . At ( )
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , sexp . Labels ( ) , sres . Labels ( ) )
2017-05-23 18:13:30 +05:30
smplExp , errExp := expandSeriesIterator ( sexp . Iterator ( ) )
smplRes , errRes := expandSeriesIterator ( sres . Iterator ( ) )
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , errExp , errRes )
testutil . Equals ( t , smplExp , smplRes )
2017-05-23 18:13:30 +05:30
}
}
}
2017-08-29 00:39:17 +02:00
func TestAmendDatapointCausesError ( t * testing . T ) {
db , close := openTestDB ( t , nil )
defer close ( )
2017-12-10 12:02:01 -06:00
defer db . Close ( )
2017-08-29 00:39:17 +02:00
app := db . Appender ( )
_ , err := app . Add ( labels . Labels { } , 0 , 0 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
testutil . Ok ( t , app . Commit ( ) )
2017-08-29 00:39:17 +02:00
app = db . Appender ( )
_ , err = app . Add ( labels . Labels { } , 0 , 1 )
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , ErrAmendSample , err )
testutil . Ok ( t , app . Rollback ( ) )
2017-08-29 00:39:17 +02:00
}
func TestDuplicateNaNDatapointNoAmendError ( t * testing . T ) {
db , close := openTestDB ( t , nil )
defer close ( )
2017-12-10 12:02:01 -06:00
defer db . Close ( )
2017-08-29 00:39:17 +02:00
app := db . Appender ( )
_ , err := app . Add ( labels . Labels { } , 0 , math . NaN ( ) )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
testutil . Ok ( t , app . Commit ( ) )
2017-08-29 00:39:17 +02:00
app = db . Appender ( )
_ , err = app . Add ( labels . Labels { } , 0 , math . NaN ( ) )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-08-29 00:39:17 +02:00
}
func TestNonDuplicateNaNDatapointsCausesAmendError ( t * testing . T ) {
db , close := openTestDB ( t , nil )
defer close ( )
2017-12-10 12:02:01 -06:00
defer db . Close ( )
2017-08-29 00:39:17 +02:00
app := db . Appender ( )
_ , err := app . Add ( labels . Labels { } , 0 , math . Float64frombits ( 0x7ff0000000000001 ) )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
testutil . Ok ( t , app . Commit ( ) )
2017-08-29 00:39:17 +02:00
app = db . Appender ( )
_ , err = app . Add ( labels . Labels { } , 0 , math . Float64frombits ( 0x7ff0000000000002 ) )
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , ErrAmendSample , err )
2017-08-29 00:39:17 +02:00
}
func TestSkippingInvalidValuesInSameTxn ( t * testing . T ) {
db , close := openTestDB ( t , nil )
defer close ( )
2017-12-10 12:02:01 -06:00
defer db . Close ( )
2017-08-29 00:39:17 +02:00
// Append AmendedValue.
app := db . Appender ( )
_ , err := app . Add ( labels . Labels { { "a" , "b" } } , 0 , 1 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-08-29 00:39:17 +02:00
_ , err = app . Add ( labels . Labels { { "a" , "b" } } , 0 , 2 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
testutil . Ok ( t , app . Commit ( ) )
2017-08-29 00:39:17 +02:00
// Make sure the right value is stored.
2017-10-09 15:21:46 +02:00
q , err := db . Querier ( 0 , 10 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-10-09 15:21:46 +02:00
2017-11-13 12:16:58 +01:00
ssMap := query ( t , q , labels . NewEqualMatcher ( "a" , "b" ) )
2017-08-29 00:39:17 +02:00
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , map [ string ] [ ] sample {
2017-08-29 00:39:17 +02:00
labels . New ( labels . Label { "a" , "b" } ) . String ( ) : [ ] sample { { 0 , 1 } } ,
} , ssMap )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , q . Close ( ) )
2017-08-29 00:39:17 +02:00
// Append Out of Order Value.
app = db . Appender ( )
_ , err = app . Add ( labels . Labels { { "a" , "b" } } , 10 , 3 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-08-29 00:39:17 +02:00
_ , err = app . Add ( labels . Labels { { "a" , "b" } } , 7 , 5 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
testutil . Ok ( t , app . Commit ( ) )
2017-08-29 00:39:17 +02:00
2017-10-09 15:21:46 +02:00
q , err = db . Querier ( 0 , 10 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-10-09 15:21:46 +02:00
2017-11-13 12:16:58 +01:00
ssMap = query ( t , q , labels . NewEqualMatcher ( "a" , "b" ) )
2017-08-29 00:39:17 +02:00
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , map [ string ] [ ] sample {
2017-08-29 00:39:17 +02:00
labels . New ( labels . Label { "a" , "b" } ) . String ( ) : [ ] sample { { 0 , 1 } , { 10 , 3 } } ,
} , ssMap )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , q . Close ( ) )
2017-08-29 00:39:17 +02:00
}
2017-10-03 13:06:26 +01:00
func TestDB_Snapshot ( t * testing . T ) {
db , close := openTestDB ( t , nil )
defer close ( )
// append data
app := db . Appender ( )
mint := int64 ( 1414141414000 )
for i := 0 ; i < 1000 ; i ++ {
_ , err := app . Add ( labels . FromStrings ( "foo" , "bar" ) , mint + int64 ( i ) , 1.0 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-10-03 13:06:26 +01:00
}
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , app . Commit ( ) )
testutil . Ok ( t , app . Rollback ( ) )
2017-10-03 13:06:26 +01:00
// create snapshot
snap , err := ioutil . TempDir ( "" , "snap" )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2018-02-28 12:04:55 +01:00
2018-02-23 17:04:50 +02:00
defer os . RemoveAll ( snap )
2018-02-28 12:04:55 +01:00
testutil . Ok ( t , db . Snapshot ( snap , true ) )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , db . Close ( ) )
2017-10-03 13:06:26 +01:00
// reopen DB from snapshot
db , err = Open ( snap , nil , nil , nil )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-12-10 12:02:01 -06:00
defer db . Close ( )
2017-10-03 13:06:26 +01:00
2017-10-09 15:21:46 +02:00
querier , err := db . Querier ( mint , mint + 1000 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-10-03 13:06:26 +01:00
defer querier . Close ( )
// sum values
2017-11-13 12:16:58 +01:00
seriesSet , err := querier . Select ( labels . NewEqualMatcher ( "foo" , "bar" ) )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-11-13 12:16:58 +01:00
2017-10-03 13:06:26 +01:00
sum := 0.0
for seriesSet . Next ( ) {
series := seriesSet . At ( ) . Iterator ( )
for series . Next ( ) {
_ , v := series . At ( )
sum += v
}
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , series . Err ( ) )
2017-10-03 13:06:26 +01:00
}
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , seriesSet . Err ( ) )
testutil . Equals ( t , sum , 1000.0 )
2017-10-03 13:06:26 +01:00
}
2017-11-22 17:58:06 +05:30
func TestDB_SnapshotWithDelete ( t * testing . T ) {
numSamples := int64 ( 10 )
db , close := openTestDB ( t , nil )
defer close ( )
app := db . Appender ( )
smpls := make ( [ ] float64 , numSamples )
for i := int64 ( 0 ) ; i < numSamples ; i ++ {
smpls [ i ] = rand . Float64 ( )
app . Add ( labels . Labels { { "a" , "b" } } , i , smpls [ i ] )
}
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , app . Commit ( ) )
2017-11-22 17:58:06 +05:30
cases := [ ] struct {
intervals Intervals
remaint [ ] int64
} {
{
intervals : Intervals { { 1 , 3 } , { 4 , 7 } } ,
remaint : [ ] int64 { 0 , 8 , 9 } ,
} ,
}
Outer :
for _ , c := range cases {
// TODO(gouthamve): Reset the tombstones somehow.
// Delete the ranges.
for _ , r := range c . intervals {
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , db . Delete ( r . Mint , r . Maxt , labels . NewEqualMatcher ( "a" , "b" ) ) )
2017-11-22 17:58:06 +05:30
}
// create snapshot
snap , err := ioutil . TempDir ( "" , "snap" )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2018-02-28 12:04:55 +01:00
2018-02-23 17:04:50 +02:00
defer os . RemoveAll ( snap )
2018-02-28 12:04:55 +01:00
testutil . Ok ( t , db . Snapshot ( snap , true ) )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , db . Close ( ) )
2017-11-22 17:58:06 +05:30
// reopen DB from snapshot
db , err = Open ( snap , nil , nil , nil )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-12-10 12:02:01 -06:00
defer db . Close ( )
2017-11-22 17:58:06 +05:30
// Compare the result.
q , err := db . Querier ( 0 , numSamples )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-12-10 12:02:01 -06:00
defer q . Close ( )
2017-11-22 17:58:06 +05:30
2017-11-30 13:28:52 +05:30
res , err := q . Select ( labels . NewEqualMatcher ( "a" , "b" ) )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-11-22 17:58:06 +05:30
expSamples := make ( [ ] sample , 0 , len ( c . remaint ) )
for _ , ts := range c . remaint {
expSamples = append ( expSamples , sample { ts , smpls [ ts ] } )
}
expss := newListSeriesSet ( [ ] Series {
newSeries ( map [ string ] string { "a" : "b" } , expSamples ) ,
} )
if len ( expSamples ) == 0 {
2017-12-06 17:06:14 -08:00
testutil . Assert ( t , res . Next ( ) == false , "" )
2017-11-22 17:58:06 +05:30
continue
}
for {
eok , rok := expss . Next ( ) , res . Next ( )
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , eok , rok )
2017-11-22 17:58:06 +05:30
if ! eok {
continue Outer
}
sexp := expss . At ( )
sres := res . At ( )
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , sexp . Labels ( ) , sres . Labels ( ) )
2017-11-22 17:58:06 +05:30
smplExp , errExp := expandSeriesIterator ( sexp . Iterator ( ) )
smplRes , errRes := expandSeriesIterator ( sres . Iterator ( ) )
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , errExp , errRes )
testutil . Equals ( t , smplExp , smplRes )
2017-11-22 17:58:06 +05:30
}
}
}
2017-08-29 00:39:17 +02:00
func TestDB_e2e ( t * testing . T ) {
const (
numDatapoints = 1000
numRanges = 1000
timeInterval = int64 ( 3 )
maxTime = int64 ( 2 * 1000 )
minTime = int64 ( 200 )
)
// Create 8 series with 1000 data-points of different ranges and run queries.
lbls := [ ] [ ] labels . Label {
{
{ "a" , "b" } ,
{ "instance" , "localhost:9090" } ,
{ "job" , "prometheus" } ,
} ,
{
{ "a" , "b" } ,
{ "instance" , "127.0.0.1:9090" } ,
{ "job" , "prometheus" } ,
} ,
{
{ "a" , "b" } ,
{ "instance" , "127.0.0.1:9090" } ,
{ "job" , "prom-k8s" } ,
} ,
{
{ "a" , "b" } ,
{ "instance" , "localhost:9090" } ,
{ "job" , "prom-k8s" } ,
} ,
{
{ "a" , "c" } ,
{ "instance" , "localhost:9090" } ,
{ "job" , "prometheus" } ,
} ,
{
{ "a" , "c" } ,
{ "instance" , "127.0.0.1:9090" } ,
{ "job" , "prometheus" } ,
} ,
{
{ "a" , "c" } ,
{ "instance" , "127.0.0.1:9090" } ,
{ "job" , "prom-k8s" } ,
} ,
{
{ "a" , "c" } ,
{ "instance" , "localhost:9090" } ,
{ "job" , "prom-k8s" } ,
} ,
}
seriesMap := map [ string ] [ ] sample { }
for _ , l := range lbls {
seriesMap [ labels . New ( l ... ) . String ( ) ] = [ ] sample { }
}
db , close := openTestDB ( t , nil )
defer close ( )
2017-12-10 12:02:01 -06:00
defer db . Close ( )
2017-08-29 00:39:17 +02:00
app := db . Appender ( )
for _ , l := range lbls {
lset := labels . New ( l ... )
series := [ ] sample { }
ts := rand . Int63n ( 300 )
for i := 0 ; i < numDatapoints ; i ++ {
v := rand . Float64 ( )
series = append ( series , sample { ts , v } )
_ , err := app . Add ( lset , ts , v )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-08-29 00:39:17 +02:00
ts += rand . Int63n ( timeInterval ) + 1
}
seriesMap [ lset . String ( ) ] = series
}
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , app . Commit ( ) )
2017-08-29 00:39:17 +02:00
// Query each selector on 1000 random time-ranges.
queries := [ ] struct {
ms [ ] labels . Matcher
} {
{
ms : [ ] labels . Matcher { labels . NewEqualMatcher ( "a" , "b" ) } ,
} ,
{
ms : [ ] labels . Matcher {
labels . NewEqualMatcher ( "a" , "b" ) ,
labels . NewEqualMatcher ( "job" , "prom-k8s" ) ,
} ,
} ,
{
ms : [ ] labels . Matcher {
labels . NewEqualMatcher ( "a" , "c" ) ,
labels . NewEqualMatcher ( "instance" , "localhost:9090" ) ,
labels . NewEqualMatcher ( "job" , "prometheus" ) ,
} ,
} ,
// TODO: Add Regexp Matchers.
}
for _ , qry := range queries {
matched := labels . Slice { }
for _ , ls := range lbls {
s := labels . Selector ( qry . ms )
if s . Matches ( ls ) {
matched = append ( matched , ls )
}
}
sort . Sort ( matched )
for i := 0 ; i < numRanges ; i ++ {
mint := rand . Int63n ( 300 )
maxt := mint + rand . Int63n ( timeInterval * int64 ( numDatapoints ) )
expected := map [ string ] [ ] sample { }
// Build the mockSeriesSet.
for _ , m := range matched {
smpls := boundedSamples ( seriesMap [ m . String ( ) ] , mint , maxt )
if len ( smpls ) > 0 {
expected [ m . String ( ) ] = smpls
}
}
2017-10-09 15:21:46 +02:00
q , err := db . Querier ( mint , maxt )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-10-09 15:21:46 +02:00
2017-11-13 12:16:58 +01:00
ss , err := q . Select ( qry . ms ... )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-08-29 00:39:17 +02:00
result := map [ string ] [ ] sample { }
for ss . Next ( ) {
x := ss . At ( )
smpls , err := expandSeriesIterator ( x . Iterator ( ) )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-08-29 00:39:17 +02:00
if len ( smpls ) > 0 {
result [ x . Labels ( ) . String ( ) ] = smpls
}
}
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , ss . Err ( ) )
testutil . Equals ( t , expected , result )
2017-08-29 00:39:17 +02:00
q . Close ( )
}
}
return
}
2017-11-10 21:19:39 +01:00
func TestWALFlushedOnDBClose ( t * testing . T ) {
2018-02-23 17:04:50 +02:00
db , close := openTestDB ( t , nil )
defer close ( )
2017-11-10 21:19:39 +01:00
2018-02-23 17:04:50 +02:00
dirDb := db . Dir ( )
2017-11-10 21:19:39 +01:00
lbls := labels . Labels { labels . Label { Name : "labelname" , Value : "labelvalue" } }
app := db . Appender ( )
2018-02-23 17:04:50 +02:00
_ , err := app . Add ( lbls , 0 , 1 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
testutil . Ok ( t , app . Commit ( ) )
2017-11-10 21:19:39 +01:00
2017-12-10 12:02:01 -06:00
testutil . Ok ( t , db . Close ( ) )
2017-11-10 21:19:39 +01:00
2018-02-23 17:04:50 +02:00
db , err = Open ( dirDb , nil , nil , nil )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-12-10 12:02:01 -06:00
defer db . Close ( )
2017-11-10 21:19:39 +01:00
q , err := db . Querier ( 0 , 1 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-11-10 21:19:39 +01:00
values , err := q . LabelValues ( "labelname" )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
testutil . Equals ( t , values , [ ] string { "labelvalue" } )
2017-11-10 21:19:39 +01:00
}
2017-11-23 18:57:10 +05:30
2017-11-22 18:04:50 +05:30
func TestTombstoneClean ( t * testing . T ) {
numSamples := int64 ( 10 )
db , close := openTestDB ( t , nil )
defer close ( )
app := db . Appender ( )
smpls := make ( [ ] float64 , numSamples )
for i := int64 ( 0 ) ; i < numSamples ; i ++ {
smpls [ i ] = rand . Float64 ( )
app . Add ( labels . Labels { { "a" , "b" } } , i , smpls [ i ] )
}
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , app . Commit ( ) )
2017-11-22 18:04:50 +05:30
cases := [ ] struct {
intervals Intervals
remaint [ ] int64
} {
{
intervals : Intervals { { 1 , 3 } , { 4 , 7 } } ,
remaint : [ ] int64 { 0 , 8 , 9 } ,
} ,
}
for _ , c := range cases {
// Delete the ranges.
// create snapshot
snap , err := ioutil . TempDir ( "" , "snap" )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2018-02-28 12:04:55 +01:00
2018-02-23 17:04:50 +02:00
defer os . RemoveAll ( snap )
2018-02-28 12:04:55 +01:00
testutil . Ok ( t , db . Snapshot ( snap , true ) )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , db . Close ( ) )
2017-11-22 18:04:50 +05:30
// reopen DB from snapshot
db , err = Open ( snap , nil , nil , nil )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-12-10 12:02:01 -06:00
defer db . Close ( )
2017-11-22 18:04:50 +05:30
for _ , r := range c . intervals {
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , db . Delete ( r . Mint , r . Maxt , labels . NewEqualMatcher ( "a" , "b" ) ) )
2017-11-22 18:04:50 +05:30
}
// All of the setup for THIS line.
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , db . CleanTombstones ( ) )
2017-11-22 18:04:50 +05:30
// Compare the result.
q , err := db . Querier ( 0 , numSamples )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-12-10 12:02:01 -06:00
defer q . Close ( )
2017-11-22 18:04:50 +05:30
2017-11-30 13:15:23 +05:30
res , err := q . Select ( labels . NewEqualMatcher ( "a" , "b" ) )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-11-22 18:04:50 +05:30
expSamples := make ( [ ] sample , 0 , len ( c . remaint ) )
for _ , ts := range c . remaint {
expSamples = append ( expSamples , sample { ts , smpls [ ts ] } )
}
expss := newListSeriesSet ( [ ] Series {
newSeries ( map [ string ] string { "a" : "b" } , expSamples ) ,
} )
if len ( expSamples ) == 0 {
2017-12-06 17:06:14 -08:00
testutil . Assert ( t , res . Next ( ) == false , "" )
2017-11-22 18:04:50 +05:30
continue
}
for {
eok , rok := expss . Next ( ) , res . Next ( )
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , eok , rok )
2017-11-22 18:04:50 +05:30
if ! eok {
break
}
sexp := expss . At ( )
sres := res . At ( )
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , sexp . Labels ( ) , sres . Labels ( ) )
2017-11-22 18:04:50 +05:30
smplExp , errExp := expandSeriesIterator ( sexp . Iterator ( ) )
smplRes , errRes := expandSeriesIterator ( sres . Iterator ( ) )
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , errExp , errRes )
testutil . Equals ( t , smplExp , smplRes )
2017-11-22 18:04:50 +05:30
}
for _ , b := range db . blocks {
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , emptyTombstoneReader , b . tombstones )
2017-11-22 18:04:50 +05:30
}
}
}
2017-11-30 13:15:23 +05:30
2017-11-23 18:57:10 +05:30
func TestDB_Retention ( t * testing . T ) {
2018-02-23 17:04:50 +02:00
db , close := openTestDB ( t , nil )
defer close ( )
2017-11-23 18:57:10 +05:30
lbls := labels . Labels { labels . Label { Name : "labelname" , Value : "labelvalue" } }
app := db . Appender ( )
2018-02-23 17:04:50 +02:00
_ , err := app . Add ( lbls , 0 , 1 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
testutil . Ok ( t , app . Commit ( ) )
2017-11-23 18:57:10 +05:30
// create snapshot to make it create a block.
// TODO(gouthamve): Add a method to compact headblock.
snap , err := ioutil . TempDir ( "" , "snap" )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2018-02-28 12:04:55 +01:00
2018-02-23 17:04:50 +02:00
defer os . RemoveAll ( snap )
2018-02-28 12:04:55 +01:00
testutil . Ok ( t , db . Snapshot ( snap , true ) )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , db . Close ( ) )
2017-11-23 18:57:10 +05:30
// reopen DB from snapshot
db , err = Open ( snap , nil , nil , nil )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-11-23 18:57:10 +05:30
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , 1 , len ( db . blocks ) )
2017-11-23 18:57:10 +05:30
app = db . Appender ( )
_ , err = app . Add ( lbls , 100 , 1 )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
testutil . Ok ( t , app . Commit ( ) )
2017-11-23 18:57:10 +05:30
// Snapshot again to create another block.
snap , err = ioutil . TempDir ( "" , "snap" )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2018-02-23 17:04:50 +02:00
defer os . RemoveAll ( snap )
2018-02-28 12:04:55 +01:00
testutil . Ok ( t , db . Snapshot ( snap , true ) )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , db . Close ( ) )
2017-11-23 18:57:10 +05:30
// reopen DB from snapshot
db , err = Open ( snap , nil , nil , & Options {
RetentionDuration : 10 ,
BlockRanges : [ ] int64 { 50 } ,
} )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
2017-12-10 12:02:01 -06:00
defer db . Close ( )
2017-11-23 18:57:10 +05:30
2017-12-06 17:06:14 -08:00
testutil . Equals ( t , 2 , len ( db . blocks ) )
2017-11-23 18:57:10 +05:30
2018-01-10 11:36:56 +01:00
// Now call retention.
2017-11-23 18:57:10 +05:30
changes , err := db . retentionCutoff ( )
2017-12-06 17:06:14 -08:00
testutil . Ok ( t , err )
testutil . Assert ( t , changes , "there should be changes" )
testutil . Equals ( t , 1 , len ( db . blocks ) )
testutil . Equals ( t , int64 ( 100 ) , db . blocks [ 0 ] . meta . MaxTime ) // To verify its the right block.
2017-11-23 18:57:10 +05:30
}
2017-12-17 23:38:21 +05:30
func TestNotMatcherSelectsLabelsUnsetSeries ( t * testing . T ) {
2018-02-23 17:04:50 +02:00
db , close := openTestDB ( t , nil )
defer close ( )
2017-12-17 23:38:21 +05:30
labelpairs := [ ] labels . Labels {
labels . FromStrings ( "a" , "abcd" , "b" , "abcde" ) ,
labels . FromStrings ( "labelname" , "labelvalue" ) ,
}
app := db . Appender ( )
for _ , lbls := range labelpairs {
2018-02-23 17:04:50 +02:00
_ , err := app . Add ( lbls , 0 , 1 )
2017-12-17 23:38:21 +05:30
testutil . Ok ( t , err )
}
testutil . Ok ( t , app . Commit ( ) )
cases := [ ] struct {
selector labels . Selector
series [ ] labels . Labels
} { {
selector : labels . Selector {
labels . Not ( labels . NewEqualMatcher ( "lname" , "lvalue" ) ) ,
} ,
series : labelpairs ,
} , {
selector : labels . Selector {
labels . NewEqualMatcher ( "a" , "abcd" ) ,
labels . Not ( labels . NewEqualMatcher ( "b" , "abcde" ) ) ,
} ,
series : [ ] labels . Labels { } ,
} , {
selector : labels . Selector {
labels . NewEqualMatcher ( "a" , "abcd" ) ,
labels . Not ( labels . NewEqualMatcher ( "b" , "abc" ) ) ,
} ,
series : [ ] labels . Labels { labelpairs [ 0 ] } ,
} , {
selector : labels . Selector {
labels . Not ( labels . NewMustRegexpMatcher ( "a" , "abd.*" ) ) ,
} ,
series : labelpairs ,
} , {
selector : labels . Selector {
labels . Not ( labels . NewMustRegexpMatcher ( "a" , "abc.*" ) ) ,
} ,
series : labelpairs [ 1 : ] ,
} , {
selector : labels . Selector {
labels . Not ( labels . NewMustRegexpMatcher ( "c" , "abd.*" ) ) ,
} ,
series : labelpairs ,
} , {
selector : labels . Selector {
labels . Not ( labels . NewMustRegexpMatcher ( "labelname" , "labelvalue" ) ) ,
} ,
series : labelpairs [ : 1 ] ,
} }
q , err := db . Querier ( 0 , 10 )
testutil . Ok ( t , err )
defer q . Close ( )
for _ , c := range cases {
ss , err := q . Select ( c . selector ... )
testutil . Ok ( t , err )
lres , err := expandSeriesSet ( ss )
testutil . Ok ( t , err )
testutil . Equals ( t , c . series , lres )
}
}
func expandSeriesSet ( ss SeriesSet ) ( [ ] labels . Labels , error ) {
result := [ ] labels . Labels { }
for ss . Next ( ) {
result = append ( result , ss . At ( ) . Labels ( ) )
}
return result , ss . Err ( )
}
2018-03-28 15:50:52 +01:00
func TestValidateBlockSequenceDetectsAllOverlaps ( t * testing . T ) {
var metas [ ] BlockMeta
// Create 10 blocks that does not overlap (0-10, 10-20, ..., 90-100)
for i := 0 ; i < 10 ; i ++ {
metas = append ( metas , BlockMeta { MinTime : int64 ( i * 10 ) , MaxTime : int64 ( ( i + 1 ) * 10 ) } )
}
overlappedBlocks := ValidateBlockSequence ( metas )
testutil . Assert ( t , len ( overlappedBlocks ) == 0 , "we found unexpected overlaps" )
// Add overlaping blocks.
// o1 overlaps with 10-20.
o1 := BlockMeta { MinTime : 15 , MaxTime : 17 }
overlappedBlocks = ValidateBlockSequence ( append ( metas , o1 ) )
expectedOverlaps := [ ] [ ] BlockMeta {
{ metas [ 1 ] , o1 } ,
}
testutil . Equals ( t , expectedOverlaps , overlappedBlocks )
//// o2 overlaps with 20-30 and 30-40.
//o2 := BlockMeta{MinTime: 21, MaxTime: 31}
//
//// o3a and o3b overlaps with 30-40 and each other.
//o3a := BlockMeta{MinTime: 33, MaxTime: 39}
//o3b := BlockMeta{MinTime: 34, MaxTime: 36}
//
//// o4 is 1:1 overlap with 50-60
//o4 := BlockMeta{MinTime: 50, MaxTime: 60}
//
//// o5 overlaps with 50-60, 60-70 and 70,80
//o5 := BlockMeta{MinTime: 60, MaxTime: 80}
//
//expectedOverlaps := [][]block.Meta{
// {metas[1], o1},
// {metas[2], o2},
// {metas[3], o2},
// {metas[3], o3, o3b},
//}
}