Change kernel specific name in code base and change syslog to filelog.

This commit is contained in:
Random-Liu
2017-02-06 14:29:23 -08:00
parent 6e35bcf5c6
commit 10fc831409
26 changed files with 194 additions and 194 deletions

View File

@@ -20,4 +20,4 @@ RUN test -h /etc/localtime && rm -f /etc/localtime && cp /usr/share/zoneinfo/UTC
ADD ./bin/node-problem-detector /node-problem-detector
ADD config /config
ENTRYPOINT ["/node-problem-detector", "--kernel-monitor=/config/kernel-monitor.json"]
ENTRYPOINT ["/node-problem-detector", "--system-log-monitor=/config/kernel-monitor.json"]

View File

@@ -49,7 +49,7 @@ List of supported problem daemons:
| Problem Daemon | NodeCondition | Description |
|----------------|:---------------:|:------------|
| [KernelMonitor](https://github.com/kubernetes/node-problem-detector/tree/master/pkg/kernelmonitor) | KernelDeadlock | A problem daemon monitors kernel log and reports problem according to predefined rules. |
| [KernelMonitor](https://github.com/kubernetes/node-problem-detector/tree/master/pkg/logmonitor) | KernelDeadlock | A problem daemon monitors kernel log and reports problem according to predefined rules. |
# Usage
## Flags

View File

@@ -26,10 +26,10 @@ import (
"github.com/golang/glog"
"github.com/spf13/pflag"
"k8s.io/node-problem-detector/pkg/kernelmonitor"
"k8s.io/node-problem-detector/pkg/options"
"k8s.io/node-problem-detector/pkg/problemclient"
"k8s.io/node-problem-detector/pkg/problemdetector"
"k8s.io/node-problem-detector/pkg/systemlogmonitor"
"k8s.io/node-problem-detector/pkg/version"
)
@@ -67,9 +67,9 @@ func main() {
os.Exit(0)
}
k := kernelmonitor.NewKernelMonitorOrDie(npdo.KernelMonitorConfigPath)
l := systemlogmonitor.NewLogMonitorOrDie(npdo.SystemLogMonitorConfigPath)
c := problemclient.NewClientOrDie(npdo)
p := problemdetector.NewProblemDetector(k, c)
p := problemdetector.NewProblemDetector(l, c)
// Start http server.
if npdo.ServerPort > 0 {

View File

@@ -1,5 +1,5 @@
{
"plugin": "syslog",
"plugin": "filelog",
"pluginConfig": {
"timestamp": "^time=\"(\\S*)\"",
"message": "msg=\"([^\n]*)\"",

View File

@@ -1,5 +1,5 @@
{
"plugin": "syslog",
"plugin": "filelog",
"pluginConfig": {
"timestamp": "^.{15}",
"message": "kernel: \\[.*\\] (.*)",

View File

@@ -30,8 +30,8 @@ import (
type NodeProblemDetectorOptions struct {
// command line options
// KernelMonitorConfigPath specifies the path to kernel monitor configuration file.
KernelMonitorConfigPath string
// SystemLogMonitorConfigPath specifies the path to system log monitor configuration file.
SystemLogMonitorConfigPath string
// ApiServerOverride is the custom URI used to connect to Kubernetes ApiServer.
ApiServerOverride string
// PrintVersion is the flag determining whether version information is printed.
@@ -55,8 +55,8 @@ func NewNodeProblemDetectorOptions() *NodeProblemDetectorOptions {
// AddFlags adds node problem detector command line options to pflag.
func (npdo *NodeProblemDetectorOptions) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&npdo.KernelMonitorConfigPath, "kernel-monitor",
"/config/kernel-monitor.json", "The path to the kernel monitor config file")
fs.StringVar(&npdo.SystemLogMonitorConfigPath, "system-log-monitor",
"/config/kernel-monitor.json", "The path to the system log monitor config file")
fs.StringVar(&npdo.ApiServerOverride, "apiserver-override",
"", "Custom URI used to connect to Kubernetes ApiServer")
fs.BoolVar(&npdo.PrintVersion, "version", false, "Print version information and quit")

View File

@@ -24,8 +24,8 @@ import (
"k8s.io/kubernetes/pkg/util/clock"
"k8s.io/node-problem-detector/pkg/condition"
"k8s.io/node-problem-detector/pkg/kernelmonitor"
"k8s.io/node-problem-detector/pkg/problemclient"
"k8s.io/node-problem-detector/pkg/systemlogmonitor"
"k8s.io/node-problem-detector/pkg/util"
)
@@ -39,12 +39,12 @@ type problemDetector struct {
client problemclient.Client
conditionManager condition.ConditionManager
// TODO(random-liu): Use slices of problem daemons if multiple monitors are needed in the future
monitor kernelmonitor.KernelMonitor
monitor systemlogmonitor.LogMonitor
}
// NewProblemDetector creates the problem detector. Currently we just directly passed in the problem daemons, but
// in the future we may want to let the problem daemons register themselves.
func NewProblemDetector(monitor kernelmonitor.KernelMonitor, client problemclient.Client) ProblemDetector {
func NewProblemDetector(monitor systemlogmonitor.LogMonitor, client problemclient.Client) ProblemDetector {
return &problemDetector{
client: client,
conditionManager: condition.NewConditionManager(client, clock.RealClock{}),

View File

@@ -43,8 +43,8 @@ with new rule definition:
Kernel monitor supports different log management tools with different log
watchers:
* [syslog](https://github.com/kubernetes/node-problem-detector/blob/master/pkg/kernelmonitor/logwatchers/syslog)
* [journald](https://github.com/kubernetes/node-problem-detector/blob/master/pkg/kernelmonitor/logwatchers/journald)
* [syslog](https://github.com/kubernetes/node-problem-detector/blob/master/pkg/logmonitor/logwatchers/syslog)
* [journald](https://github.com/kubernetes/node-problem-detector/blob/master/pkg/logmonitor/logwatchers/journald)
### Change Log Path
@@ -57,5 +57,5 @@ You can always configure `logPath` and volume mount to match your OS distro.
### New Log Watcher
Kernel monitor uses [Log
Watcher](https://github.com/kubernetes/node-problem-detector/blob/master/pkg/kernelmonitor/logwatchers/types/log_watcher.go) to support different log management tools.
Watcher](https://github.com/kubernetes/node-problem-detector/blob/master/pkg/logmonitor/logwatchers/types/log_watcher.go) to support different log management tools.
It is easy to implement a new log watcher.

View File

@@ -14,26 +14,26 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kernelmonitor
package systemlogmonitor
import (
watchertypes "k8s.io/node-problem-detector/pkg/kernelmonitor/logwatchers/types"
kerntypes "k8s.io/node-problem-detector/pkg/kernelmonitor/types"
watchertypes "k8s.io/node-problem-detector/pkg/systemlogmonitor/logwatchers/types"
logtypes "k8s.io/node-problem-detector/pkg/systemlogmonitor/types"
"k8s.io/node-problem-detector/pkg/types"
)
// MonitorConfig is the configuration of kernel monitor.
// MonitorConfig is the configuration of log monitor.
type MonitorConfig struct {
// WatcherConfig is the configuration of kernel log watcher.
// WatcherConfig is the configuration of log watcher.
watchertypes.WatcherConfig
// BufferSize is the size (in lines) of the log buffer.
BufferSize int `json:"bufferSize"`
// Source is the source name of the kernel monitor
// Source is the source name of the log monitor
Source string `json:"source"`
// DefaultConditions are the default states of all the conditions kernel monitor should handle.
// DefaultConditions are the default states of all the conditions log monitor should handle.
DefaultConditions []types.Condition `json:"conditions"`
// Rules are the rules kernel monitor will follow to parse the log file.
Rules []kerntypes.Rule `json:"rules"`
// Rules are the rules log monitor will follow to parse the log file.
Rules []logtypes.Rule `json:"rules"`
}
// applyDefaultConfiguration applies default configurations.

View File

@@ -14,28 +14,28 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kernelmonitor
package systemlogmonitor
import (
"regexp"
"strings"
"k8s.io/node-problem-detector/pkg/kernelmonitor/types"
"k8s.io/node-problem-detector/pkg/systemlogmonitor/types"
)
// LogBuffer buffers the logs and supports match in the log buffer with regular expression.
type LogBuffer interface {
// Push pushes log into the log buffer.
Push(*types.KernelLog)
Push(*types.Log)
// Match with regular expression in the log buffer.
Match(string) []*types.KernelLog
Match(string) []*types.Log
// String returns a concatenated string of the buffered logs.
String() string
}
type logBuffer struct {
// buffer is a simple ring buffer.
buffer []*types.KernelLog
buffer []*types.Log
msg []string
max int
current int
@@ -47,20 +47,20 @@ type logBuffer struct {
// lines of patterns we support.
func NewLogBuffer(maxLines int) *logBuffer {
return &logBuffer{
buffer: make([]*types.KernelLog, maxLines, maxLines),
buffer: make([]*types.Log, maxLines, maxLines),
msg: make([]string, maxLines, maxLines),
max: maxLines,
}
}
func (b *logBuffer) Push(log *types.KernelLog) {
func (b *logBuffer) Push(log *types.Log) {
b.buffer[b.current%b.max] = log
b.msg[b.current%b.max] = log.Message
b.current++
}
// TODO(random-liu): Cache regexp if garbage collection becomes a problem someday.
func (b *logBuffer) Match(expr string) []*types.KernelLog {
func (b *logBuffer) Match(expr string) []*types.Log {
// The expression should be checked outside, and it must match to the end.
reg := regexp.MustCompile(expr + `\z`)
log := b.String()
@@ -72,7 +72,7 @@ func (b *logBuffer) Match(expr string) []*types.KernelLog {
// reverse index
s := len(log) - loc[0] - 1
total := 0
matched := []*types.KernelLog{}
matched := []*types.Log{}
for i := b.tail(); i >= b.current && b.buffer[i%b.max] != nil; i-- {
matched = append(matched, b.buffer[i%b.max])
total += len(b.msg[i%b.max]) + 1 // Add '\n'

View File

@@ -14,13 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kernelmonitor
package systemlogmonitor
import (
"reflect"
"testing"
"k8s.io/node-problem-detector/pkg/kernelmonitor/types"
"k8s.io/node-problem-detector/pkg/systemlogmonitor/types"
)
func TestPush(t *testing.T) {
@@ -52,7 +52,7 @@ func TestPush(t *testing.T) {
} {
b := NewLogBuffer(test.max)
for _, log := range test.logs {
b.Push(&types.KernelLog{Message: log})
b.Push(&types.Log{Message: log})
}
got := b.String()
if test.expected != got {
@@ -94,13 +94,13 @@ func TestMatch(t *testing.T) {
} {
b := NewLogBuffer(max)
for _, log := range test.logs {
b.Push(&types.KernelLog{Message: log})
b.Push(&types.Log{Message: log})
}
for i, expr := range test.exprs {
kLogs := b.Match(expr)
logs := b.Match(expr)
got := []string{}
for _, kLog := range kLogs {
got = append(got, kLog.Message)
for _, log := range logs {
got = append(got, log.Message)
}
if !reflect.DeepEqual(test.expected[i], got) {
t.Errorf("case %d.%d: expected %v, got %v", c+1, i+1, test.expected[i], got)

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kernelmonitor
package systemlogmonitor
import (
"encoding/json"
@@ -22,116 +22,116 @@ import (
"regexp"
"time"
"k8s.io/node-problem-detector/pkg/kernelmonitor/logwatchers"
watchertypes "k8s.io/node-problem-detector/pkg/kernelmonitor/logwatchers/types"
kerntypes "k8s.io/node-problem-detector/pkg/kernelmonitor/types"
"k8s.io/node-problem-detector/pkg/kernelmonitor/util"
"k8s.io/node-problem-detector/pkg/systemlogmonitor/logwatchers"
watchertypes "k8s.io/node-problem-detector/pkg/systemlogmonitor/logwatchers/types"
logtypes "k8s.io/node-problem-detector/pkg/systemlogmonitor/types"
"k8s.io/node-problem-detector/pkg/systemlogmonitor/util"
"k8s.io/node-problem-detector/pkg/types"
"github.com/golang/glog"
)
// KernelMonitor monitors the kernel log and reports node problem condition and event according to
// LogMonitor monitors the log and reports node problem condition and event according to
// the rules.
type KernelMonitor interface {
// Start starts the kernel monitor.
type LogMonitor interface {
// Start starts the log monitor.
Start() (<-chan *types.Status, error)
// Stop stops the kernel monitor.
// Stop stops the log monitor.
Stop()
}
type kernelMonitor struct {
type logMonitor struct {
watcher watchertypes.LogWatcher
buffer LogBuffer
config MonitorConfig
conditions []types.Condition
logCh <-chan *kerntypes.KernelLog
logCh <-chan *logtypes.Log
output chan *types.Status
tomb *util.Tomb
}
// NewKernelMonitorOrDie create a new KernelMonitor, panic if error occurs.
func NewKernelMonitorOrDie(configPath string) KernelMonitor {
k := &kernelMonitor{
// NewLogMonitorOrDie create a new LogMonitor, panic if error occurs.
func NewLogMonitorOrDie(configPath string) LogMonitor {
l := &logMonitor{
tomb: util.NewTomb(),
}
f, err := ioutil.ReadFile(configPath)
if err != nil {
glog.Fatalf("Failed to read configuration file %q: %v", configPath, err)
}
err = json.Unmarshal(f, &k.config)
err = json.Unmarshal(f, &l.config)
if err != nil {
glog.Fatalf("Failed to unmarshal configuration file %q: %v", configPath, err)
}
// Apply default configurations
applyDefaultConfiguration(&k.config)
err = validateRules(k.config.Rules)
applyDefaultConfiguration(&l.config)
err = validateRules(l.config.Rules)
if err != nil {
glog.Fatalf("Failed to validate matching rules %#v: %v", k.config.Rules, err)
glog.Fatalf("Failed to validate matching rules %#v: %v", l.config.Rules, err)
}
glog.Infof("Finish parsing log file: %+v", k.config)
k.watcher = logwatchers.GetLogWatcherOrDie(k.config.WatcherConfig)
k.buffer = NewLogBuffer(k.config.BufferSize)
glog.Infof("Finish parsing log monitor config file: %+v", l.config)
l.watcher = logwatchers.GetLogWatcherOrDie(l.config.WatcherConfig)
l.buffer = NewLogBuffer(l.config.BufferSize)
// A 1000 size channel should be big enough.
k.output = make(chan *types.Status, 1000)
return k
l.output = make(chan *types.Status, 1000)
return l
}
func (k *kernelMonitor) Start() (<-chan *types.Status, error) {
glog.Info("Start kernel monitor")
func (l *logMonitor) Start() (<-chan *types.Status, error) {
glog.Info("Start log monitor")
var err error
k.logCh, err = k.watcher.Watch()
l.logCh, err = l.watcher.Watch()
if err != nil {
return nil, err
}
go k.monitorLoop()
return k.output, nil
go l.monitorLoop()
return l.output, nil
}
func (k *kernelMonitor) Stop() {
glog.Info("Stop kernel monitor")
k.tomb.Stop()
func (l *logMonitor) Stop() {
glog.Info("Stop log monitor")
l.tomb.Stop()
}
// monitorLoop is the main loop of kernel monitor.
func (k *kernelMonitor) monitorLoop() {
defer k.tomb.Done()
k.initializeStatus()
// monitorLoop is the main loop of log monitor.
func (l *logMonitor) monitorLoop() {
defer l.tomb.Done()
l.initializeStatus()
for {
select {
case log := <-k.logCh:
k.parseLog(log)
case <-k.tomb.Stopping():
k.watcher.Stop()
glog.Infof("Kernel monitor stopped")
case log := <-l.logCh:
l.parseLog(log)
case <-l.tomb.Stopping():
l.watcher.Stop()
glog.Infof("Log monitor stopped")
return
}
}
}
// parseLog parses one log line.
func (k *kernelMonitor) parseLog(log *kerntypes.KernelLog) {
// Once there is new log, kernel monitor will push it into the log buffer and try
// to match each rule. If any rule is matched, kernel monitor will report a status.
k.buffer.Push(log)
for _, rule := range k.config.Rules {
matched := k.buffer.Match(rule.Pattern)
func (l *logMonitor) parseLog(log *logtypes.Log) {
// Once there is new log, log monitor will push it into the log buffer and try
// to match each rule. If any rule is matched, log monitor will report a status.
l.buffer.Push(log)
for _, rule := range l.config.Rules {
matched := l.buffer.Match(rule.Pattern)
if len(matched) == 0 {
continue
}
status := k.generateStatus(matched, rule)
status := l.generateStatus(matched, rule)
glog.Infof("New status generated: %+v", status)
k.output <- status
l.output <- status
}
}
// generateStatus generates status from the logs.
func (k *kernelMonitor) generateStatus(logs []*kerntypes.KernelLog, rule kerntypes.Rule) *types.Status {
func (l *logMonitor) generateStatus(logs []*logtypes.Log, rule logtypes.Rule) *types.Status {
// We use the timestamp of the first log line as the timestamp of the status.
timestamp := logs[0].Timestamp
message := generateMessage(logs)
var events []types.Event
if rule.Type == kerntypes.Temp {
if rule.Type == logtypes.Temp {
// For temporary error only generate event
events = append(events, types.Event{
Severity: types.Warn,
@@ -141,8 +141,8 @@ func (k *kernelMonitor) generateStatus(logs []*kerntypes.KernelLog, rule kerntyp
})
} else {
// For permanent error changes the condition
for i := range k.conditions {
condition := &k.conditions[i]
for i := range l.conditions {
condition := &l.conditions[i]
if condition.Type == rule.Condition {
condition.Type = rule.Condition
// Update transition timestamp and message when the condition
@@ -159,22 +159,22 @@ func (k *kernelMonitor) generateStatus(logs []*kerntypes.KernelLog, rule kerntyp
}
}
return &types.Status{
Source: k.config.Source,
Source: l.config.Source,
// TODO(random-liu): Aggregate events and conditions and then do periodically report.
Events: events,
Conditions: k.conditions,
Conditions: l.conditions,
}
}
// initializeStatus initializes the internal condition and also reports it to the node problem detector.
func (k *kernelMonitor) initializeStatus() {
func (l *logMonitor) initializeStatus() {
// Initialize the default node conditions
k.conditions = initialConditions(k.config.DefaultConditions)
glog.Infof("Initialize condition generated: %+v", k.conditions)
l.conditions = initialConditions(l.config.DefaultConditions)
glog.Infof("Initialize condition generated: %+v", l.conditions)
// Update the initial status
k.output <- &types.Status{
Source: k.config.Source,
Conditions: k.conditions,
l.output <- &types.Status{
Source: l.config.Source,
Conditions: l.conditions,
}
}
@@ -190,7 +190,7 @@ func initialConditions(defaults []types.Condition) []types.Condition {
}
// validateRules verifies whether the regular expressions in the rules are valid.
func validateRules(rules []kerntypes.Rule) error {
func validateRules(rules []logtypes.Rule) error {
for _, rule := range rules {
_, err := regexp.Compile(rule.Pattern)
if err != nil {
@@ -200,7 +200,7 @@ func validateRules(rules []kerntypes.Rule) error {
return nil
}
func generateMessage(logs []*kerntypes.KernelLog) string {
func generateMessage(logs []*logtypes.Log) string {
messages := []string{}
for _, log := range logs {
messages = append(messages, log.Message)

View File

@@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kernelmonitor
package systemlogmonitor
import (
"reflect"
"testing"
"time"
kerntypes "k8s.io/node-problem-detector/pkg/kernelmonitor/types"
logtypes "k8s.io/node-problem-detector/pkg/systemlogmonitor/types"
"k8s.io/node-problem-detector/pkg/types"
)
@@ -45,7 +45,7 @@ func TestGenerateStatus(t *testing.T) {
Transition: time.Unix(500, 500),
},
}
logs := []*kerntypes.KernelLog{
logs := []*logtypes.Log{
{
Timestamp: time.Unix(1000, 1000),
Message: "test message 1",
@@ -56,13 +56,13 @@ func TestGenerateStatus(t *testing.T) {
},
}
for c, test := range []struct {
rule kerntypes.Rule
rule logtypes.Rule
expected types.Status
}{
// Do not need Pattern because we don't do pattern match in this test
{
rule: kerntypes.Rule{
Type: kerntypes.Perm,
rule: logtypes.Rule{
Type: logtypes.Perm,
Condition: testConditionA,
Reason: "test reason",
},
@@ -82,8 +82,8 @@ func TestGenerateStatus(t *testing.T) {
},
// Should not update transition time when status and reason are not changed.
{
rule: kerntypes.Rule{
Type: kerntypes.Perm,
rule: logtypes.Rule{
Type: logtypes.Perm,
Condition: testConditionA,
Reason: "initial reason",
},
@@ -101,8 +101,8 @@ func TestGenerateStatus(t *testing.T) {
},
},
{
rule: kerntypes.Rule{
Type: kerntypes.Temp,
rule: logtypes.Rule{
Type: logtypes.Temp,
Reason: "test reason",
},
expected: types.Status{
@@ -117,7 +117,7 @@ func TestGenerateStatus(t *testing.T) {
},
},
} {
k := &kernelMonitor{
l := &logMonitor{
config: MonitorConfig{
Source: testSource,
},
@@ -125,7 +125,7 @@ func TestGenerateStatus(t *testing.T) {
// during the test.
conditions: append([]types.Condition{}, initConditions...),
}
got := k.generateStatus(logs, test.rule)
got := l.generateStatus(logs, test.rule)
if !reflect.DeepEqual(&test.expected, got) {
t.Errorf("case %d: expected status %+v, got %+v", c+1, test.expected, got)
}

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package syslog
package filelog
import (
"bufio"
@@ -30,36 +30,36 @@ import (
"github.com/golang/glog"
"github.com/google/cadvisor/utils/tail"
"k8s.io/node-problem-detector/pkg/kernelmonitor/logwatchers/types"
kerntypes "k8s.io/node-problem-detector/pkg/kernelmonitor/types"
"k8s.io/node-problem-detector/pkg/kernelmonitor/util"
"k8s.io/node-problem-detector/pkg/systemlogmonitor/logwatchers/types"
logtypes "k8s.io/node-problem-detector/pkg/systemlogmonitor/types"
"k8s.io/node-problem-detector/pkg/systemlogmonitor/util"
)
type syslogWatcher struct {
type filelogWatcher struct {
cfg types.WatcherConfig
reader *bufio.Reader
closer io.Closer
translator *translator
logCh chan *kerntypes.KernelLog
logCh chan *logtypes.Log
uptime time.Time
tomb *util.Tomb
clock utilclock.Clock
}
// NewSyslogWatcherOrDie creates a new kernel log watcher. The function panics
// NewSyslogWatcherOrDie creates a new log watcher. The function panics
// when encounters an error.
func NewSyslogWatcherOrDie(cfg types.WatcherConfig) types.LogWatcher {
var info syscall.Sysinfo_t
if err := syscall.Sysinfo(&info); err != nil {
glog.Fatalf("Failed to get system info: %v", err)
}
return &syslogWatcher{
return &filelogWatcher{
cfg: cfg,
translator: newTranslatorOrDie(cfg.PluginConfig),
uptime: time.Now().Add(time.Duration(-info.Uptime * int64(time.Second))),
tomb: util.NewTomb(),
// A capacity 1000 buffer should be enough
logCh: make(chan *kerntypes.KernelLog, 1000),
logCh: make(chan *logtypes.Log, 1000),
clock: utilclock.NewClock(),
}
}
@@ -67,30 +67,30 @@ func NewSyslogWatcherOrDie(cfg types.WatcherConfig) types.LogWatcher {
// Make sure NewSyslogWathcer is types.WatcherCreateFunc.
var _ types.WatcherCreateFunc = NewSyslogWatcherOrDie
// Watch starts the syslog watcher.
func (s *syslogWatcher) Watch() (<-chan *kerntypes.KernelLog, error) {
// Watch starts the filelog watcher.
func (s *filelogWatcher) Watch() (<-chan *logtypes.Log, error) {
r, err := getLogReader(s.cfg.LogPath)
if err != nil {
return nil, err
}
s.reader = bufio.NewReader(r)
s.closer = r
glog.Info("Start watching syslog")
glog.Info("Start watching filelog")
go s.watchLoop()
return s.logCh, nil
}
// Stop stops the syslog watcher.
func (s *syslogWatcher) Stop() {
// Stop stops the filelog watcher.
func (s *filelogWatcher) Stop() {
s.tomb.Stop()
}
// watchPollInterval is the interval syslog log watcher will
// watchPollInterval is the interval filelog log watcher will
// poll for pod change after reading to the end.
const watchPollInterval = 500 * time.Millisecond
// watchLoop is the main watch loop of syslog watcher.
func (s *syslogWatcher) watchLoop() {
// watchLoop is the main watch loop of filelog watcher.
func (s *filelogWatcher) watchLoop() {
defer func() {
s.closer.Close()
close(s.logCh)
@@ -105,14 +105,14 @@ func (s *syslogWatcher) watchLoop() {
for {
select {
case <-s.tomb.Stopping():
glog.Infof("Stop watching syslog")
glog.Infof("Stop watching filelog")
return
default:
}
line, err := s.reader.ReadString('\n')
if err != nil && err != io.EOF {
glog.Errorf("Exiting syslog watch with error: %v", err)
glog.Errorf("Exiting filelog watch with error: %v", err)
return
}
buffer.WriteString(line)
@@ -135,7 +135,7 @@ func (s *syslogWatcher) watchLoop() {
}
}
// getLogReader returns log reader for syslog log. Note that getLogReader doesn't look back
// getLogReader returns log reader for filelog log. Note that getLogReader doesn't look back
// to the rolled out logs.
func getLogReader(path string) (io.ReadCloser, error) {
if path == "" {

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package syslog
package filelog
import (
"io/ioutil"
@@ -22,8 +22,8 @@ import (
"testing"
"time"
"k8s.io/node-problem-detector/pkg/kernelmonitor/logwatchers/types"
kerntypes "k8s.io/node-problem-detector/pkg/kernelmonitor/types"
"k8s.io/node-problem-detector/pkg/systemlogmonitor/logwatchers/types"
logtypes "k8s.io/node-problem-detector/pkg/systemlogmonitor/types"
"code.cloudfoundry.org/clock/fakeclock"
"github.com/stretchr/testify/assert"
@@ -45,7 +45,7 @@ func TestWatch(t *testing.T) {
fakeClock := fakeclock.NewFakeClock(now)
testCases := []struct {
log string
logs []kerntypes.KernelLog
logs []logtypes.Log
uptime time.Time
lookback string
}{
@@ -56,7 +56,7 @@ Jan 2 03:04:06 kernel: [1.000000] 2
Jan 2 03:04:07 kernel: [2.000000] 3
`,
lookback: "0",
logs: []kerntypes.KernelLog{
logs: []logtypes.Log{
{
Timestamp: now,
Message: "1",
@@ -78,7 +78,7 @@ Jan 2 03:04:05 kernel: [1.000000] 2
Jan 2 03:04:06 kernel: [2.000000] 3
`,
lookback: "0",
logs: []kerntypes.KernelLog{
logs: []logtypes.Log{
{
Timestamp: now,
Message: "2",
@@ -96,7 +96,7 @@ Jan 2 03:04:04 kernel: [1.000000] 2
Jan 2 03:04:05 kernel: [2.000000] 3
`,
lookback: "1s",
logs: []kerntypes.KernelLog{
logs: []logtypes.Log{
{
Timestamp: now.Add(-time.Second),
Message: "2",
@@ -116,7 +116,7 @@ Jan 2 03:04:05 kernel: [2.000000] 3
`,
uptime: time.Date(time.Now().Year(), time.January, 2, 3, 4, 4, 0, time.Local),
lookback: "2s",
logs: []kerntypes.KernelLog{
logs: []logtypes.Log{
{
Timestamp: now.Add(-time.Second),
Message: "2",
@@ -130,7 +130,7 @@ Jan 2 03:04:05 kernel: [2.000000] 3
}
for c, test := range testCases {
t.Logf("TestCase #%d: %#v", c+1, test)
f, err := ioutil.TempFile("", "kernel_log_watcher_test")
f, err := ioutil.TempFile("", "log_watcher_test")
assert.NoError(t, err)
defer func() {
f.Close()
@@ -140,15 +140,15 @@ Jan 2 03:04:05 kernel: [2.000000] 3
assert.NoError(t, err)
w := NewSyslogWatcherOrDie(types.WatcherConfig{
Plugin: "syslog",
Plugin: "filelog",
PluginConfig: getTestPluginConfig(),
LogPath: f.Name(),
Lookback: test.lookback,
})
// Set the uptime.
w.(*syslogWatcher).uptime = test.uptime
w.(*filelogWatcher).uptime = test.uptime
// Set the fake clock.
w.(*syslogWatcher).clock = fakeClock
w.(*filelogWatcher).clock = fakeClock
logCh, err := w.Watch()
assert.NoError(t, err)
defer w.Stop()

View File

@@ -13,14 +13,14 @@ 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 syslog
package filelog
import (
"fmt"
"regexp"
"time"
kerntypes "k8s.io/node-problem-detector/pkg/kernelmonitor/types"
logtypes "k8s.io/node-problem-detector/pkg/systemlogmonitor/types"
"github.com/golang/glog"
)
@@ -56,7 +56,7 @@ func newTranslatorOrDie(pluginConfig map[string]string) *translator {
}
// translate translates the log line into internal type.
func (t *translator) translate(line string) (*kerntypes.KernelLog, error) {
func (t *translator) translate(line string) (*logtypes.Log, error) {
// Parse timestamp.
matches := t.timestampRegexp.FindStringSubmatch(line)
if len(matches) == 0 {
@@ -74,7 +74,7 @@ func (t *translator) translate(line string) (*kerntypes.KernelLog, error) {
return nil, fmt.Errorf("no message found in line %q with regular expression %v", line, t.messageRegexp)
}
message := matches[len(matches)-1]
return &kerntypes.KernelLog{
return &logtypes.Log{
Timestamp: timestamp,
Message: message,
}, nil
@@ -95,7 +95,7 @@ func validatePluginConfig(cfg map[string]string) error {
}
// formalizeTimestamp formalizes the timestamp. We need this because some log doesn't contain full
// timestamp, e.g. syslog.
// timestamp, e.g. filelog.
func formalizeTimestamp(t time.Time) time.Time {
if t.Year() == 0 {
t = t.AddDate(time.Now().Year(), 0, 0)

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package syslog
package filelog
import (
"testing"
@@ -23,7 +23,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
kerntypes "k8s.io/node-problem-detector/pkg/kernelmonitor/types"
logtypes "k8s.io/node-problem-detector/pkg/systemlogmonitor/types"
)
func TestTranslate(t *testing.T) {
@@ -32,7 +32,7 @@ func TestTranslate(t *testing.T) {
config map[string]string
input string
err bool
log *kerntypes.KernelLog
log *logtypes.Log
}{
{
// missing year and timezone
@@ -41,7 +41,7 @@ func TestTranslate(t *testing.T) {
// "timestampFormat": "Jan _2 15:04:05",
config: getTestPluginConfig(),
input: "May 1 12:23:45 hostname kernel: [0.000000] component: log message",
log: &kerntypes.KernelLog{
log: &logtypes.Log{
Timestamp: time.Date(year, time.May, 1, 12, 23, 45, 0, time.Local),
Message: "component: log message",
},
@@ -50,7 +50,7 @@ func TestTranslate(t *testing.T) {
// no log message
config: getTestPluginConfig(),
input: "May 21 12:23:45 hostname kernel: [9.999999] ",
log: &kerntypes.KernelLog{
log: &logtypes.Log{
Timestamp: time.Date(year, time.May, 21, 12, 23, 45, 0, time.Local),
Message: "",
},
@@ -69,7 +69,7 @@ func TestTranslate(t *testing.T) {
"timestampFormat": "2006-01-02T15:04:05.999999999-07:00",
},
input: `time="2017-02-01T17:58:34.999999999-08:00" level=error msg="test log line1\n test log line2"`,
log: &kerntypes.KernelLog{
log: &logtypes.Log{
Timestamp: time.Date(2017, 2, 1, 17, 58, 34, 999999999, time.FixedZone("PST", -8*3600)),
Message: `test log line1\n test log line2`,
},

View File

@@ -26,9 +26,9 @@ import (
"github.com/coreos/go-systemd/sdjournal"
"github.com/golang/glog"
"k8s.io/node-problem-detector/pkg/kernelmonitor/logwatchers/types"
kerntypes "k8s.io/node-problem-detector/pkg/kernelmonitor/types"
"k8s.io/node-problem-detector/pkg/kernelmonitor/util"
"k8s.io/node-problem-detector/pkg/systemlogmonitor/logwatchers/types"
logtypes "k8s.io/node-problem-detector/pkg/systemlogmonitor/types"
"k8s.io/node-problem-detector/pkg/systemlogmonitor/util"
)
// Compiling go-systemd/sdjournald needs libsystemd-dev or libsystemd-journal-dev,
@@ -40,7 +40,7 @@ import (
type journaldWatcher struct {
journal *sdjournal.Journal
cfg types.WatcherConfig
logCh chan *kerntypes.KernelLog
logCh chan *logtypes.Log
tomb *util.Tomb
}
@@ -50,7 +50,7 @@ func NewJournaldWatcher(cfg types.WatcherConfig) types.LogWatcher {
cfg: cfg,
tomb: util.NewTomb(),
// A capacity 1000 buffer should be enough
logCh: make(chan *kerntypes.KernelLog, 1000),
logCh: make(chan *logtypes.Log, 1000),
}
}
@@ -58,7 +58,7 @@ func NewJournaldWatcher(cfg types.WatcherConfig) types.LogWatcher {
var _ types.WatcherCreateFunc = NewJournaldWatcher
// Watch starts the journal watcher.
func (j *journaldWatcher) Watch() (<-chan *kerntypes.KernelLog, error) {
func (j *journaldWatcher) Watch() (<-chan *logtypes.Log, error) {
journal, err := getJournal(j.cfg)
if err != nil {
return nil, err
@@ -162,10 +162,10 @@ func getJournal(cfg types.WatcherConfig) (*sdjournal.Journal, error) {
}
// translate translates journal entry into internal type.
func translate(entry *sdjournal.JournalEntry) *kerntypes.KernelLog {
func translate(entry *sdjournal.JournalEntry) *logtypes.Log {
timestamp := time.Unix(0, int64(time.Duration(entry.RealtimeTimestamp)*time.Microsecond))
message := strings.TrimSpace(entry.Fields["MESSAGE"])
return &kerntypes.KernelLog{
return &logtypes.Log{
Timestamp: timestamp,
Message: message,
}

View File

@@ -25,13 +25,13 @@ import (
"github.com/coreos/go-systemd/sdjournal"
"github.com/stretchr/testify/assert"
kerntypes "k8s.io/node-problem-detector/pkg/kernelmonitor/types"
logtypes "k8s.io/node-problem-detector/pkg/systemlogmonitor/types"
)
func TestTranslate(t *testing.T) {
testCases := []struct {
entry *sdjournal.JournalEntry
log *kerntypes.KernelLog
log *logtypes.Log
}{
{
// has log message
@@ -39,7 +39,7 @@ func TestTranslate(t *testing.T) {
Fields: map[string]string{"MESSAGE": "log message"},
RealtimeTimestamp: 123456789,
},
log: &kerntypes.KernelLog{
log: &logtypes.Log{
Timestamp: time.Unix(0, 123456789*1000),
Message: "log message",
},
@@ -50,7 +50,7 @@ func TestTranslate(t *testing.T) {
Fields: map[string]string{},
RealtimeTimestamp: 987654321,
},
log: &kerntypes.KernelLog{
log: &logtypes.Log{
Timestamp: time.Unix(0, 987654321*1000),
Message: "",
},

View File

@@ -17,7 +17,7 @@ limitations under the License.
package logwatchers
import (
"k8s.io/node-problem-detector/pkg/kernelmonitor/logwatchers/types"
"k8s.io/node-problem-detector/pkg/systemlogmonitor/logwatchers/types"
"github.com/golang/glog"
)

View File

@@ -17,12 +17,12 @@ limitations under the License.
package logwatchers
import (
"k8s.io/node-problem-detector/pkg/kernelmonitor/logwatchers/syslog"
"k8s.io/node-problem-detector/pkg/systemlogmonitor/logwatchers/filelog"
)
const syslogPluginName = "syslog"
const filelogPluginName = "filelog"
func init() {
// Register the syslog plugin.
registerLogWatcher(syslogPluginName, syslog.NewSyslogWatcherOrDie)
// Register the filelog plugin.
registerLogWatcher(filelogPluginName, filelog.NewSyslogWatcherOrDie)
}

View File

@@ -19,12 +19,12 @@ limitations under the License.
package logwatchers
import (
"k8s.io/node-problem-detector/pkg/kernelmonitor/logwatchers/journald"
"k8s.io/node-problem-detector/pkg/systemlogmonitor/logwatchers/journald"
)
const journaldPluginName = "journald"
func init() {
// Register the syslog plugin.
// Register the journald plugin.
registerLogWatcher(journaldPluginName, journald.NewJournaldWatcher)
}

View File

@@ -17,13 +17,13 @@ limitations under the License.
package types
import (
"k8s.io/node-problem-detector/pkg/kernelmonitor/types"
"k8s.io/node-problem-detector/pkg/systemlogmonitor/types"
)
// LogWatcher is the interface of a log watcher.
type LogWatcher interface {
// Watch starts watching logs and returns logs via a channel.
Watch() (<-chan *types.KernelLog, error)
Watch() (<-chan *types.Log, error)
// Stop stops the log watcher. Resources open should be closed properly.
Stop()
}
@@ -31,14 +31,14 @@ type LogWatcher interface {
// WatcherConfig is the configuration of the log watcher.
type WatcherConfig struct {
// Plugin is the name of plugin which is currently used.
// Currently supported: syslog, journald.
// Currently supported: filelog, journald.
Plugin string `json:"plugin, omitempty"`
// PluginConfig is a key/value configuration of a plugin. Valid configurations
// are defined in different log watcher plugin.
PluginConfig map[string]string `json:"pluginConfig, omitempty"`
// LogPath is the path to the log
LogPath string `json:"logPath, omitempty"`
// Lookback is the time kernel watcher looks up
// Lookback is the time log watcher looks up
Lookback string `json:"lookback, omitempty"`
}

View File

@@ -20,34 +20,34 @@ import (
"time"
)
// KernelLog is the log item returned by translator. It's very easy to extend this
// Log is the log item returned by translator. It's very easy to extend this
// to support other log monitoring, such as docker log monitoring.
type KernelLog struct {
type Log struct {
Timestamp time.Time
Message string
}
// Type is the type of the kernel problem.
// Type is the type of the problem.
type Type string
const (
// Temp means the kernel problem is temporary, only need to report an event.
// Temp means the problem is temporary, only need to report an event.
Temp Type = "temporary"
// Perm means the kernel problem is permanent, need to change the node condition.
// Perm means the problem is permanent, need to change the node condition.
Perm Type = "permanent"
)
// Rule describes how kernel monitor should analyze the kernel log.
// Rule describes how log monitor should analyze the log.
type Rule struct {
// Type is the type of matched kernel problem.
// Type is the type of matched problem.
Type Type `json:"type"`
// Condition is the type of the condition the kernel problem triggered. Notice that
// the Condition field should be set only when the problem is permanent, or else the
// field will be ignored.
// Condition is the type of the condition the problem triggered. Notice that
// the Condition field should be set only when the problem is permanent, or
// else the field will be ignored.
Condition string `json:"condition"`
// Reason is the short reason of the kernel problem.
// Reason is the short reason of the problem.
Reason string `json:"reason"`
// Pattern is the regular expression to match the kernel problem in kernel log.
// Pattern is the regular expression to match the problem in log.
// Notice that the pattern must match to the end of the line.
Pattern string `json:"pattern"`
}