forked from influxdata/telegraf
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfile.go
138 lines (119 loc) · 3.33 KB
/
file.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package testutil
import (
"bufio"
"fmt"
"os"
"strings"
"github.com/influxdata/telegraf"
)
type LineParser interface {
ParseLine(line string) (telegraf.Metric, error)
}
// ParseRawLinesFrom returns the raw lines between the given header and a trailing blank line
func ParseRawLinesFrom(lines []string, header string) ([]string, error) {
if len(lines) < 2 {
// We need a line for HEADER and EMPTY TRAILING LINE
return nil, fmt.Errorf("expected at least two lines to parse from")
}
start := -1
for i := range lines {
if strings.TrimLeft(lines[i], "# ") == header {
start = i + 1
break
}
}
if start < 0 {
return nil, fmt.Errorf("header %q does not exist", header)
}
output := make([]string, 0)
for _, line := range lines[start:] {
if !strings.HasPrefix(strings.TrimLeft(line, "\t "), "#") {
return nil, fmt.Errorf("section does not end with trailing empty line")
}
// Stop at empty line
content := strings.TrimLeft(line, "# \t")
if content == "" || content == "'''" {
break
}
output = append(output, content)
}
return output, nil
}
// ParseMetricsFrom parses metrics from the given lines in line-protocol following a header, with a trailing blank line
func ParseMetricsFrom(lines []string, header string, parser LineParser) ([]telegraf.Metric, error) {
if len(lines) < 2 {
// We need a line for HEADER and EMPTY TRAILING LINE
return nil, fmt.Errorf("expected at least two lines to parse from")
}
start := -1
for i := range lines {
if strings.TrimLeft(lines[i], "# ") == header {
start = i + 1
break
}
}
if start < 0 {
return nil, fmt.Errorf("header %q does not exist", header)
}
metrics := make([]telegraf.Metric, 0)
for _, line := range lines[start:] {
if !strings.HasPrefix(strings.TrimLeft(line, "\t "), "#") {
return nil, fmt.Errorf("section does not end with trailing empty line")
}
// Stop at empty line
content := strings.TrimLeft(line, "# \t")
if content == "" || content == "'''" {
break
}
m, err := parser.ParseLine(content)
if err != nil {
return nil, fmt.Errorf("unable to parse metric in %q failed: %w", content, err)
}
metrics = append(metrics, m)
}
return metrics, nil
}
// ParseMetricsFromFile parses metrics from the given file in line-protocol
func ParseMetricsFromFile(filename string, parser telegraf.Parser) ([]telegraf.Metric, error) {
var metrics []telegraf.Metric
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Bytes()
if len(line) == 0 || strings.HasPrefix(string(line), "#") {
continue
}
nonutc, err := parser.Parse(line)
if err != nil {
return nil, fmt.Errorf("unable to parse metric in %q failed: %w", line, err)
}
for _, m := range nonutc {
// The timezone needs to be UTC to match the timestamp test results
m.SetTime(m.Time().UTC())
metrics = append(metrics, m)
}
}
return metrics, nil
}
// ParseLinesFromFile returns the lines of the file as strings
func ParseLinesFromFile(filename string) ([]string, error) {
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
var lines []string
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
if len(line) == 0 || strings.HasPrefix(line, "#") {
continue
}
lines = append(lines, line)
}
return lines, nil
}