/
logging_hook.go
83 lines (71 loc) · 2.52 KB
/
logging_hook.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Copyright 2018 Authors of Cilium
//
// 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.
package metrics
import (
"fmt"
"reflect"
"github.com/cilium/cilium/pkg/components"
"github.com/cilium/cilium/pkg/logging/logfields"
"github.com/sirupsen/logrus"
)
// LoggingHook is a hook for logrus which counts error and warning messages as a
// Prometheus metric.
type LoggingHook struct {
metric CounterVec
}
// NewLoggingHook returns a new instance of LoggingHook for the given Cilium
// component.
func NewLoggingHook(component string) *LoggingHook {
// NOTE(mrostecki): For now errors and warning metric exists only for Cilium
// daemon, but support of Prometheus metrics in some other components (i.e.
// cilium-health - GH-4268) is planned.
// Pick a metric for the component.
var metric CounterVec
switch component {
case components.CiliumAgentName:
metric = ErrorsWarnings
case components.CiliumOperatortName:
metric = ErrorsWarnings
default:
panic(fmt.Sprintf("component %s is unsupported by LoggingHook", component))
}
return &LoggingHook{metric: metric}
}
// Levels returns the list of logging levels on which the hook is triggered.
func (h *LoggingHook) Levels() []logrus.Level {
return []logrus.Level{
logrus.ErrorLevel,
logrus.WarnLevel,
}
}
// Fire is the main method which is called every time when logger has an error
// or warning message.
func (h *LoggingHook) Fire(entry *logrus.Entry) error {
// Get information about subsystem from logging entry field.
iSubsystem, ok := entry.Data[logfields.LogSubsys]
if !ok {
serializedEntry, err := entry.String()
if err != nil {
return fmt.Errorf("log entry cannot be serialized and doesn't contain 'subsys' field")
}
return fmt.Errorf("log entry doesn't contain 'subsys' field: %s", serializedEntry)
}
subsystem, ok := iSubsystem.(string)
if !ok {
return fmt.Errorf("type of the 'subsystem' log entry field is not string but %s", reflect.TypeOf(iSubsystem))
}
// Increment the metric.
h.metric.WithLabelValues(entry.Level.String(), subsystem).Inc()
return nil
}