mirror of
https://github.com/kubernetes/node-problem-detector.git
synced 2026-08-23 22:26:27 +00:00
Precompile log buffer regular expressions
Compile fixed patterns during monitor and log counter initialization, pass compiled expressions to the log buffer, and reject invalid log counter patterns before watching logs.
This commit is contained in:
@@ -21,6 +21,7 @@ package logcounter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"k8s.io/utils/clock"
|
||||
@@ -42,12 +43,24 @@ const (
|
||||
type logCounter struct {
|
||||
logCh <-chan *systemtypes.Log
|
||||
buffer systemlogmonitor.LogBuffer
|
||||
pattern string
|
||||
revertPattern string
|
||||
pattern *regexp.Regexp
|
||||
revertPattern *regexp.Regexp
|
||||
clock clock.Clock
|
||||
}
|
||||
|
||||
func NewJournaldLogCounter(options *options.LogCounterOptions) (types.LogCounter, error) {
|
||||
pattern, err := systemlogmonitor.CompilePattern(options.Pattern)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid pattern %q: %w", options.Pattern, err)
|
||||
}
|
||||
var revertPattern *regexp.Regexp
|
||||
if options.RevertPattern != "" {
|
||||
revertPattern, err = systemlogmonitor.CompilePattern(options.RevertPattern)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid revert pattern %q: %w", options.RevertPattern, err)
|
||||
}
|
||||
}
|
||||
|
||||
watcher := journald.NewJournaldWatcher(watchertypes.WatcherConfig{
|
||||
Plugin: "journald",
|
||||
PluginConfig: map[string]string{journaldSourceKey: options.JournaldSource},
|
||||
@@ -62,8 +75,8 @@ func NewJournaldLogCounter(options *options.LogCounterOptions) (types.LogCounter
|
||||
return &logCounter{
|
||||
logCh: logCh,
|
||||
buffer: systemlogmonitor.NewLogBuffer(bufferSize),
|
||||
pattern: options.Pattern,
|
||||
revertPattern: options.RevertPattern,
|
||||
pattern: pattern,
|
||||
revertPattern: revertPattern,
|
||||
clock: clock.RealClock{},
|
||||
}, nil
|
||||
}
|
||||
@@ -86,7 +99,7 @@ func (e *logCounter) Count() (count int, err error) {
|
||||
if len(e.buffer.Match(e.pattern)) != 0 {
|
||||
count++
|
||||
}
|
||||
if e.revertPattern != "" && len(e.buffer.Match(e.revertPattern)) != 0 {
|
||||
if e.revertPattern != nil && len(e.buffer.Match(e.revertPattern)) != 0 {
|
||||
count--
|
||||
}
|
||||
case <-e.clock.After(timeout):
|
||||
|
||||
@@ -20,27 +20,67 @@ limitations under the License.
|
||||
package logcounter
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
testclock "k8s.io/utils/clock/testing"
|
||||
|
||||
"k8s.io/node-problem-detector/cmd/logcounter/options"
|
||||
"k8s.io/node-problem-detector/pkg/logcounter/types"
|
||||
"k8s.io/node-problem-detector/pkg/systemlogmonitor"
|
||||
systemtypes "k8s.io/node-problem-detector/pkg/systemlogmonitor/types"
|
||||
)
|
||||
|
||||
func NewTestLogCounter(pattern string, startTime time.Time) (types.LogCounter, *testclock.FakeClock, chan *systemtypes.Log) {
|
||||
func newTestLogCounter(t *testing.T, pattern string, startTime time.Time) (types.LogCounter, *testclock.FakeClock, chan *systemtypes.Log) {
|
||||
t.Helper()
|
||||
compiledPattern, err := systemlogmonitor.CompilePattern(pattern)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to compile pattern %q: %v", pattern, err)
|
||||
}
|
||||
logCh := make(chan *systemtypes.Log)
|
||||
clock := testclock.NewFakeClock(startTime)
|
||||
return &logCounter{
|
||||
logCh: logCh,
|
||||
buffer: systemlogmonitor.NewLogBuffer(bufferSize),
|
||||
pattern: pattern,
|
||||
pattern: compiledPattern,
|
||||
clock: clock,
|
||||
}, clock, logCh
|
||||
}
|
||||
|
||||
func TestNewJournaldLogCounterRejectsInvalidPatterns(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
pattern string
|
||||
revertPattern string
|
||||
errorContains string
|
||||
}{
|
||||
{
|
||||
name: "pattern",
|
||||
pattern: "[",
|
||||
errorContains: `invalid pattern "["`,
|
||||
},
|
||||
{
|
||||
name: "revert pattern",
|
||||
revertPattern: "[",
|
||||
errorContains: `invalid revert pattern "["`,
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
_, err := NewJournaldLogCounter(&options.LogCounterOptions{
|
||||
Pattern: tc.pattern,
|
||||
RevertPattern: tc.revertPattern,
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("expected invalid pattern error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), tc.errorContains) {
|
||||
t.Errorf("expected error containing %q, got %q", tc.errorContains, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCount(t *testing.T) {
|
||||
startTime := time.Now()
|
||||
for _, tc := range []struct {
|
||||
@@ -113,7 +153,7 @@ func TestCount(t *testing.T) {
|
||||
},
|
||||
} {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
counter, fakeClock, logCh := NewTestLogCounter(tc.pattern, startTime)
|
||||
counter, fakeClock, logCh := newTestLogCounter(t, tc.pattern, startTime)
|
||||
go func(logs []*systemtypes.Log, ch chan<- *systemtypes.Log) {
|
||||
for _, log := range logs {
|
||||
ch <- log
|
||||
|
||||
Reference in New Issue
Block a user