forked from open-policy-agent/opa
-
Notifications
You must be signed in to change notification settings - Fork 0
/
logging.go
116 lines (103 loc) · 2.84 KB
/
logging.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright 2021 The OPA Authors. All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.
package logging
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"github.com/sirupsen/logrus"
"github.com/open-policy-agent/opa/logging"
)
func GetLevel(level string) (logging.Level, error) {
switch strings.ToLower(level) {
case "debug":
return logging.Debug, nil
case "", "info":
return logging.Info, nil
case "warn":
return logging.Warn, nil
case "error":
return logging.Error, nil
default:
return logging.Debug, fmt.Errorf("invalid log level: %v", level)
}
}
func GetFormatter(format, timestampFormat string) logrus.Formatter {
switch format {
case "text":
return &prettyFormatter{}
case "json-pretty":
return &logrus.JSONFormatter{PrettyPrint: true, TimestampFormat: timestampFormat}
default:
return &logrus.JSONFormatter{TimestampFormat: timestampFormat}
}
}
// prettyFormatter implements the Logrus Formatter interface
// and provides a more simple, but easier to read, text formatter
// option than the default logrus.TextFormatter.
type prettyFormatter struct {
}
func isJSON(buf []byte) bool {
var tmp interface{}
err := json.Unmarshal(buf, &tmp)
return err == nil
}
func spaces(num int) string {
sb := strings.Builder{}
for i := 0; i < num; i++ {
sb.WriteByte(' ')
}
return sb.String()
}
func (p *prettyFormatter) Format(e *logrus.Entry) ([]byte, error) {
b := new(bytes.Buffer)
level := strings.ToUpper(e.Level.String())
b.WriteString(fmt.Sprintf("[%s] %s\n", level, e.Message))
// Format each key for optimal ease of human reading
fieldIndent := 2
multiLineIndent := 6
for k, v := range e.Data {
// Special case for multi-line strings, keep them as-is
// but indent them. Everything else gets json'd
stringVal, ok := v.(string)
if ok && strings.Contains(stringVal, "\n") {
sb := strings.Builder{}
for i, line := range strings.Split(stringVal, "\n") {
// match the json indent helper by not indenting the first value
if i != 0 {
sb.WriteString(spaces(multiLineIndent))
}
sb.WriteString(line)
sb.WriteByte('\n')
stringVal = sb.String()
}
} else if ok && isJSON([]byte(stringVal)) {
var tmp bytes.Buffer
err := json.Indent(&tmp, []byte(stringVal), spaces(multiLineIndent), spaces(2))
if err != nil {
return nil, err
}
stringVal = tmp.String()
} else {
jsonVal, err := json.MarshalIndent(v, spaces(multiLineIndent), spaces(2))
if err != nil {
return nil, err
}
stringVal = string(jsonVal)
}
b.WriteString(spaces(fieldIndent))
b.WriteString(k)
if strings.Contains(stringVal, "\n") {
b.WriteString(" = |\n")
b.WriteString(spaces(multiLineIndent))
} else {
b.WriteString(" = ")
}
b.WriteString(stringVal)
b.WriteString("\n")
}
b.WriteByte('\n')
return b.Bytes(), nil
}