mirror of
https://github.com/hanzoai/telemetry.git
synced 2026-10-30 20:01:49 +00:00
When servers are in a high memory usage mode, the amount of times GC is called creates a high CPU usage which combined with a high ingest rate limits capability to offload existing queued data. Configuring the minimum interval even for hard limit, allows the system to spend some CPU cycles between GCs to offload old data from queues/batch processor. The most amount of data I've seen accumulated are blocked in the batch processor queue (incoming channel) not in the exporter queue. Signed-off-by: Bogdan Drutu <[email protected]>
98 lines
2.2 KiB
Go
98 lines
2.2 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package memorylimiterextension
|
|
|
|
import (
|
|
"context"
|
|
"runtime"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap"
|
|
|
|
"go.opentelemetry.io/collector/component/componenttest"
|
|
"go.opentelemetry.io/collector/internal/memorylimiter"
|
|
"go.opentelemetry.io/collector/internal/memorylimiter/iruntime"
|
|
)
|
|
|
|
func TestMemoryPressureResponse(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
tests := []struct {
|
|
name string
|
|
mlCfg *Config
|
|
memAlloc uint64
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "Below memAllocLimit",
|
|
mlCfg: &Config{
|
|
CheckInterval: time.Second,
|
|
MemoryLimitPercentage: 50,
|
|
MemorySpikePercentage: 1,
|
|
},
|
|
memAlloc: 800,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Above memAllocLimit",
|
|
mlCfg: &Config{
|
|
CheckInterval: time.Second,
|
|
MemoryLimitPercentage: 50,
|
|
MemorySpikePercentage: 1,
|
|
},
|
|
memAlloc: 1800,
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "Below memSpikeLimit",
|
|
mlCfg: &Config{
|
|
CheckInterval: time.Second,
|
|
MemoryLimitPercentage: 50,
|
|
MemorySpikePercentage: 10,
|
|
},
|
|
memAlloc: 800,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Above memSpikeLimit",
|
|
mlCfg: &Config{
|
|
CheckInterval: time.Second,
|
|
MemoryLimitPercentage: 50,
|
|
MemorySpikePercentage: 11,
|
|
},
|
|
memAlloc: 800,
|
|
expectError: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
memorylimiter.GetMemoryFn = func() (uint64, error) {
|
|
return uint64(2048), nil
|
|
}
|
|
memorylimiter.ReadMemStatsFn = func(ms *runtime.MemStats) {
|
|
ms.Alloc = tt.memAlloc
|
|
}
|
|
t.Cleanup(func() {
|
|
memorylimiter.GetMemoryFn = iruntime.TotalMemory
|
|
memorylimiter.ReadMemStatsFn = runtime.ReadMemStats
|
|
})
|
|
ml, err := newMemoryLimiter(tt.mlCfg, zap.NewNop())
|
|
assert.NoError(t, err)
|
|
|
|
assert.NoError(t, ml.Start(ctx, componenttest.NewNopHost()))
|
|
ml.memLimiter.CheckMemLimits()
|
|
mustRefuse := ml.MustRefuse()
|
|
if tt.expectError {
|
|
assert.True(t, mustRefuse)
|
|
} else {
|
|
require.NoError(t, err)
|
|
}
|
|
assert.NoError(t, ml.Shutdown(ctx))
|
|
})
|
|
}
|
|
}
|