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 Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
// vespa logfmt command
// Author: arnej
package logfmt
import (
"fmt"
"strconv"
"strings"
"time"
)
// handle a line in "vespa.log" format; do filtering and formatting as specified in opts
func handleLine(opts *Options, line string) (output string, err error) {
fields := strings.SplitN(line, "\t", 7)
if len(fields) < 7 {
return "", fmt.Errorf("not enough fields: '%s'", line)
}
timestampfield := fields[0] // seconds, optional fractional seconds
hostfield := fields[1]
pidfield := fields[2] // pid, optional tid
servicefield := fields[3]
componentfield := fields[4]
levelfield := fields[5]
messagefields := fields[6:]
if !opts.showLevel(levelfield) {
return "", nil
}
if opts.OnlyHostname != "" && opts.OnlyHostname != hostfield {
return "", nil
}
if opts.OnlyPid != "" && opts.OnlyPid != pidfield {
return "", nil
}
if opts.OnlyService != "" && opts.OnlyService != servicefield {
return "", nil
}
if opts.OnlyInternal && !isInternal(componentfield) {
return "", nil
}
if opts.ComponentFilter.unmatched(componentfield) {
return "", nil
}
if opts.MessageFilter.unmatched(strings.Join(messagefields, "\t")) {
return "", nil
}
var buf strings.Builder
if opts.showField("fmttime") {
secs, err := strconv.ParseFloat(timestampfield, 64)
if err != nil {
return "", err
}
nsecs := int64(secs * 1e9)
timestamp := time.Unix(0, nsecs)
if opts.showField("usecs") {
buf.WriteString(timestamp.Format("[2006-01-02 15:04:05.000000] "))
} else if opts.showField("msecs") {
buf.WriteString(timestamp.Format("[2006-01-02 15:04:05.000] "))
} else {
buf.WriteString(timestamp.Format("[2006-01-02 15:04:05] "))
}
} else if opts.showField("time") {
buf.WriteString(timestampfield)
buf.WriteString(" ")
}
if opts.showField("host") {
buf.WriteString(fmt.Sprintf("%-8s ", hostfield))
}
if opts.showField("level") {
buf.WriteString(fmt.Sprintf("%-7s ", strings.ToUpper(levelfield)))
}
if opts.showField("pid") {
// OnlyPid, _, _ := strings.Cut(pidfield, "/")
buf.WriteString(fmt.Sprintf("%6s ", pidfield))
}
if opts.showField("service") {
if opts.TruncateService {
buf.WriteString(fmt.Sprintf("%-9.9s ", servicefield))
} else {
buf.WriteString(fmt.Sprintf("%-16s ", servicefield))
}
}
if opts.showField("component") {
if opts.TruncateComponent {
buf.WriteString(fmt.Sprintf("%-15.15s ", componentfield))
} else {
buf.WriteString(fmt.Sprintf("%s\t", componentfield))
}
}
if opts.showField("message") {
var msgBuf strings.Builder
for idx, message := range messagefields {
if idx > 0 {
msgBuf.WriteString("\n\t")
}
if opts.DequoteNewlines {
message = strings.ReplaceAll(message, "\\n\\t", "\n\t")
message = strings.ReplaceAll(message, "\\n", "\n\t")
}
msgBuf.WriteString(message)
}
message := msgBuf.String()
if strings.Contains(message, "\n") {
buf.WriteString("\n\t")
}
buf.WriteString(message)
}
buf.WriteString("\n")
output = buf.String()
return
}
|