-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlog_file_reader.go
More file actions
136 lines (116 loc) · 3.96 KB
/
log_file_reader.go
File metadata and controls
136 lines (116 loc) · 3.96 KB
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
package main
import (
"bufio"
"fmt"
"golang.org/x/exp/slices"
"io"
"strings"
)
type LogFileReader struct {
pathTransformingRules []PathTransformingRule
targetPaths []string
}
func NewLogFileReader(paths []PathTransformingRule, targetPaths []string) *LogFileReader {
return &LogFileReader{pathTransformingRules: paths, targetPaths: targetPaths}
}
func (p *LogFileReader) Read(r io.Reader) (map[string]*Metric, error) {
scanner := bufio.NewScanner(r)
metricMap := map[string]*Metric{}
for scanner.Scan() {
text := scanner.Text()
r, err := NewAlbLogRecord(text, p.pathTransformingRules)
if err != nil {
fmt.Printf("failed to read alb log record: %s\n", text)
return nil, err
}
if slices.Contains(p.targetPaths, r.RequestPath) {
metricKey := r.MetricKey()
// When metricMap doesn't have key of `metricsKey`, add new Metrics.
if _, ok := metricMap[metricKey]; !ok {
metricMap[metricKey] = &Metric{
RequestCountMap: map[Timestamp]RequestCount{},
TargetProcessingTimesMap: map[Timestamp]TargetProcessingTimes{},
Method: r.RequestMethod,
Path: r.RequestPath,
ElbStatusCode: r.ElbStatusCode,
TargetStatusCode: r.TargetStatusCode,
Elb: r.Elb,
TargetGroupArn: r.TargetGroupArn,
}
}
metric := metricMap[metricKey]
// When RequestCountMap of metric doesn't have key of timestamp, initialize value to 1.
// When RequestCountMap of metric have key of timestamp, increment value.
if _, exist := metric.RequestCountMap[r.Timestamp()]; exist {
metric.RequestCountMap[r.Timestamp()] = metric.RequestCountMap[r.Timestamp()] + RequestCount(1)
} else {
metric.RequestCountMap[r.Timestamp()] = RequestCount(1)
}
// Note: TargetProcessingTime is -1 when load balancer can't dispatch request to target or target doesn't respond until idle timeout.
// see: https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-access-logs.html
targetProcessingTime := TargetProcessingTime(r.TargetProcessingTime)
if _, exist := metric.RequestCountMap[r.Timestamp()]; exist {
metric.TargetProcessingTimesMap[r.Timestamp()] = append(metric.TargetProcessingTimesMap[r.Timestamp()], targetProcessingTime)
} else {
metric.TargetProcessingTimesMap[r.Timestamp()] = TargetProcessingTimes{targetProcessingTime}
}
metricMap[metricKey] = metric
}
}
return metricMap, nil
}
type Timestamp int64
func (ts *Timestamp) PtrInt64() *int64 {
v := int64(*ts)
return &v
}
func (ts *Timestamp) PtrFloat64() *float64 {
v := float64(*ts)
return &v
}
type RequestCount float64
func (c *RequestCount) PtrFloat64() *float64 {
v := float64(*c)
return &v
}
type TargetProcessingTime float64
func (t *TargetProcessingTime) PtrFloat64() *float64 {
v := float64(*t)
return &v
}
type TargetProcessingTimes []TargetProcessingTime
func (t *TargetProcessingTimes) Float64() *[]float64 {
r := make([]float64, len(*t))
for i, f := range *t {
r[i] = float64(f)
}
return &r
}
type Metric struct {
RequestCountMap map[Timestamp]RequestCount
TargetProcessingTimesMap map[Timestamp]TargetProcessingTimes
Method string
Path string
ElbStatusCode string
TargetStatusCode string
Elb string
TargetGroupArn string
}
func (m *Metric) TargetStatusCodeGroup() string {
// TargetStatusCode is - when the target does not send a response
// see: https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-access-logs.html
code := "-"
switch {
case strings.HasPrefix(m.TargetStatusCode, "1"):
code = "1xx"
case strings.HasPrefix(m.TargetStatusCode, "2"):
code = "2xx"
case strings.HasPrefix(m.TargetStatusCode, "3"):
code = "3xx"
case strings.HasPrefix(m.TargetStatusCode, "4"):
code = "4xx"
case strings.HasPrefix(m.TargetStatusCode, "5"):
code = "5xx"
}
return code
}