@ -61,7 +61,7 @@ func TestLabelsCollisions(t *testing.T) {
require . NoError ( t , err )
limiter := NewLimiter ( limits , NilMetrics , & ringCountMock { count : 1 } , 1 )
i , err := newInstance ( defaultConfig ( ) , defaultPeriodConfigs , "test" , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil )
i , err := newInstance ( defaultConfig ( ) , defaultPeriodConfigs , "test" , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil , NewStreamRateCalculator ( ) )
require . Nil ( t , err )
// avoid entries from the future.
@ -89,7 +89,7 @@ func TestConcurrentPushes(t *testing.T) {
require . NoError ( t , err )
limiter := NewLimiter ( limits , NilMetrics , & ringCountMock { count : 1 } , 1 )
inst , err := newInstance ( defaultConfig ( ) , defaultPeriodConfigs , "test" , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil )
inst , err := newInstance ( defaultConfig ( ) , defaultPeriodConfigs , "test" , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil , NewStreamRateCalculator ( ) )
require . Nil ( t , err )
const (
@ -136,6 +136,93 @@ func TestConcurrentPushes(t *testing.T) {
// test passes if no goroutine reports error
}
func TestGetStreamRates ( t * testing . T ) {
limits , err := validation . NewOverrides ( defaultLimitsTestConfig ( ) , nil )
require . NoError ( t , err )
limiter := NewLimiter ( limits , NilMetrics , & ringCountMock { count : 1 } , 1 )
inst , err := newInstance ( defaultConfig ( ) , defaultPeriodConfigs , "test" , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil , NewStreamRateCalculator ( ) )
require . NoError ( t , err )
const (
concurrent = 10
iterations = 100
entriesPerIteration = 100
)
uniqueLabels := map [ string ] bool { }
startChannel := make ( chan struct { } )
labelsByHash := map [ uint64 ] labels . Labels { }
wg := sync . WaitGroup { }
for i := 0 ; i < concurrent ; i ++ {
l := makeRandomLabels ( )
for uniqueLabels [ l . String ( ) ] {
l = makeRandomLabels ( )
}
uniqueLabels [ l . String ( ) ] = true
labelsByHash [ l . Hash ( ) ] = l
wg . Add ( 1 )
go func ( labels string ) {
defer wg . Done ( )
<- startChannel
tt := time . Now ( ) . Add ( - 5 * time . Minute )
for i := 0 ; i < iterations ; i ++ {
// each iteration generated the entries [hello 0, hello 100) for a total of 790 bytes per push
_ = inst . Push ( context . Background ( ) , & logproto . PushRequest { Streams : [ ] logproto . Stream {
{ Labels : labels , Entries : entries ( entriesPerIteration , tt ) } ,
} } )
tt = tt . Add ( entriesPerIteration * time . Nanosecond )
}
} ( l . String ( ) )
}
close ( startChannel )
wg . Wait ( )
var rates [ ] * logproto . StreamRate
require . Eventually ( t , func ( ) bool {
rates = inst . GetStreamRates ( context . Background ( ) , & logproto . StreamRatesRequest { } )
if len ( rates ) != concurrent {
return false
}
valid := true
for i := 0 ; i < len ( rates ) ; i ++ {
streamRates := rates [ i ]
origLabels , ok := labelsByHash [ streamRates . StreamHash ]
valid = valid && ok &&
streamRates . Rate == 79000 && // Each stream gets 100 pushes of 790 bytes
labelHashNoShard ( origLabels ) == streamRates . StreamHashNoShard
}
return valid
} , 3 * time . Second , 100 * time . Millisecond )
// Decay back to 0
require . Eventually ( t , func ( ) bool {
rates = inst . GetStreamRates ( context . Background ( ) , & logproto . StreamRatesRequest { } )
for _ , r := range rates {
if r . Rate != 0 {
return false
}
}
return true
} , 3 * time . Second , 100 * time . Millisecond )
}
func labelHashNoShard ( l labels . Labels ) uint64 {
buf := make ( [ ] byte , 256 )
hash , _ := l . HashWithoutLabels ( buf , ShardLbName )
return hash
}
func TestSyncPeriod ( t * testing . T ) {
limits , err := validation . NewOverrides ( defaultLimitsTestConfig ( ) , nil )
require . NoError ( t , err )
@ -148,7 +235,7 @@ func TestSyncPeriod(t *testing.T) {
minUtil = 0.20
)
inst , err := newInstance ( defaultConfig ( ) , defaultPeriodConfigs , "test" , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil )
inst , err := newInstance ( defaultConfig ( ) , defaultPeriodConfigs , "test" , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil , NewStreamRateCalculator ( ) )
require . Nil ( t , err )
lbls := makeRandomLabels ( )
@ -193,7 +280,7 @@ func setupTestStreams(t *testing.T) (*instance, time.Time, int) {
cfg . SyncMinUtilization = 0.20
cfg . IndexShards = indexShards
instance , err := newInstance ( cfg , defaultPeriodConfigs , "test" , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil )
instance , err := newInstance ( cfg , defaultPeriodConfigs , "test" , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil , NewStreamRateCalculator ( ) )
require . Nil ( t , err )
currentTime := time . Now ( )
@ -206,7 +293,7 @@ func setupTestStreams(t *testing.T) (*instance, time.Time, int) {
for _ , testStream := range testStreams {
stream , err := instance . getOrCreateStream ( testStream , recordPool . GetRecord ( ) )
require . NoError ( t , err )
chunk := newStream ( cfg , limiter , "fake" , 0 , nil , true , NilMetrics ) . NewChunk ( )
chunk := newStream ( cfg , limiter , "fake" , 0 , nil , true , NewStreamRateCalculator ( ) , NilMetrics ) . NewChunk ( )
for _ , entry := range testStream . Entries {
err = chunk . Append ( & entry )
require . NoError ( t , err )
@ -399,7 +486,7 @@ func Benchmark_PushInstance(b *testing.B) {
require . NoError ( b , err )
limiter := NewLimiter ( limits , NilMetrics , & ringCountMock { count : 1 } , 1 )
i , _ := newInstance ( & Config { IndexShards : 1 } , defaultPeriodConfigs , "test" , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil )
i , _ := newInstance ( & Config { IndexShards : 1 } , defaultPeriodConfigs , "test" , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil , NewStreamRateCalculator ( ) )
ctx := context . Background ( )
for n := 0 ; n < b . N ; n ++ {
@ -443,7 +530,7 @@ func Benchmark_instance_addNewTailer(b *testing.B) {
ctx := context . Background ( )
inst , _ := newInstance ( & Config { } , defaultPeriodConfigs , "test" , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil )
inst , _ := newInstance ( & Config { } , defaultPeriodConfigs , "test" , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil , NewStreamRateCalculator ( ) )
t , err := newTailer ( "foo" , ` { namespace="foo",pod="bar",instance=~"10.*"} ` , nil , 10 )
require . NoError ( b , err )
for i := 0 ; i < 10000 ; i ++ {
@ -459,7 +546,7 @@ func Benchmark_instance_addNewTailer(b *testing.B) {
lbs := makeRandomLabels ( )
b . Run ( "addTailersToNewStream" , func ( b * testing . B ) {
for n := 0 ; n < b . N ; n ++ {
inst . addTailersToNewStream ( newStream ( nil , limiter , "fake" , 0 , lbs , true , NilMetrics ) )
inst . addTailersToNewStream ( newStream ( nil , limiter , "fake" , 0 , lbs , true , NewStreamRateCalculator ( ) , NilMetrics ) )
}
} )
}
@ -712,7 +799,7 @@ func TestStreamShardingUsage(t *testing.T) {
} )
t . Run ( "invalid push returns error" , func ( t * testing . T ) {
i , _ := newInstance ( & Config { IndexShards : 1 } , defaultPeriodConfigs , customTenant1 , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil )
i , _ := newInstance ( & Config { IndexShards : 1 } , defaultPeriodConfigs , customTenant1 , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil , NewStreamRateCalculator ( ) )
ctx := context . Background ( )
err = i . Push ( ctx , & logproto . PushRequest {
@ -731,7 +818,7 @@ func TestStreamShardingUsage(t *testing.T) {
} )
t . Run ( "valid push returns no error" , func ( t * testing . T ) {
i , _ := newInstance ( & Config { IndexShards : 1 } , defaultPeriodConfigs , customTenant2 , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil )
i , _ := newInstance ( & Config { IndexShards : 1 } , defaultPeriodConfigs , customTenant2 , limiter , loki_runtime . DefaultTenantConfigs ( ) , noopWAL { } , NilMetrics , & OnceSwitch { } , nil , NewStreamRateCalculator ( ) )
ctx := context . Background ( )
err = i . Push ( ctx , & logproto . PushRequest {
@ -765,6 +852,7 @@ func defaultInstance(t *testing.T) *instance {
NilMetrics ,
nil ,
nil ,
NewStreamRateCalculator ( ) ,
)
require . Nil ( t , err )
insertData ( t , instance )