This repository has been archived by the owner on Feb 7, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfileprovider.go
97 lines (87 loc) · 2.45 KB
/
fileprovider.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
package metric
import (
"fmt"
"io"
"os"
"strconv"
"strings"
"time"
"github.com/satyrius/gonx"
)
const fileError = "log file is nil or config string is empty"
// FileProvider respect a log file data
type fileProvider struct {
logFile *os.File
config string
}
// NewFileProvider 返回一个从 file 中一行一行读取数据的 DataProvider
func NewFileProvider(file *os.File, config string) DataProvider {
return &fileProvider{
logFile: file,
config: config,
}
}
// ReadData read the nginx log data and parse it
func (fprovider *fileProvider) ReadData(ch chan *Item) error {
if fprovider.logFile == nil || fprovider.config == "" {
panic(fileError)
}
config := strings.NewReader(fprovider.config)
reader, err := gonx.NewNginxReader(fprovider.logFile, config, "main")
if err != nil {
return fmt.Errorf("create file reader failure %w", err)
}
for {
rec, err := reader.Read()
if err == io.EOF {
close(ch)
break
} else if err != nil {
ch <- &Item{
Error: fmt.Errorf("read log failure"),
}
} else {
request := readDataFromGnoxEntry(rec, "request")
remoteAddr := readDataFromGnoxEntry(rec, "remote_addr")
remoteUser := readDataFromGnoxEntry(rec, "remote_user")
timeStr := readDataFromGnoxEntry(rec, "time_local")
timeLocal, err := time.Parse("02/Jan/2006:15:04:05 -0700", timeStr)
if err != nil {
timeLocal = time.Now() //TODO 这里应该返回错误, 并阻止程序继续运行
}
status, err := strconv.Atoi(readDataFromGnoxEntry(rec, "status"))
if err != nil {
status = 0 //TODO 这里应该返回错误, 并阻止程序继续运行
}
bodyBytes, err := strconv.Atoi(readDataFromGnoxEntry(rec, "body_bytes_sent"))
if err != nil {
bodyBytes = 0 //TODO 这里应该返回错误, 并阻止程序继续运行
}
httpReferer := readDataFromGnoxEntry(rec, "http_referer")
httpUserAgent := readDataFromGnoxEntry(rec, "http_user_agent")
ch <- &Item{
Log{
Request: request,
RemoteAddr: remoteAddr,
RemoteUser: remoteUser,
TimeLocal: timeLocal,
Status: statusCode(status),
BodyBytes: uint(bodyBytes),
HTTPReferer: httpReferer,
HTTPUserAgent: httpUserAgent,
},
nil,
}
}
}
return nil
}
// read the data from gnox.Entry
// if gnox.Entry.Field() return error, return ""
func readDataFromGnoxEntry(entry *gonx.Entry, field string) string {
val, err := entry.Field(field)
if err != nil {
return ""
}
return val
}