Last active
September 22, 2015 15:28
-
-
Save hirokazumiyaji/7024cf1a7ff4110b29cc to your computer and use it in GitHub Desktop.
Nginx Log Aggregator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"encoding/json" | |
"fmt" | |
"os" | |
) | |
/* | |
nginx log format | |
log_format json '{"time": "$time_iso8601", ' | |
'"remote_addr": "$remote_addr", ' | |
'"remote_user": "$remote_user", ' | |
'"body_bytes_sent": $body_bytes_sent, ' | |
'"request_time": $request_time, ' | |
'"status": $status, ' | |
'"request": "$request", ' | |
'"http_referrer": "$http_referer", ' | |
'"http_user_agent": "$http_user_agent"' | |
'"upstream_response_time": $upstream_response_time}'; | |
*/ | |
type Line struct { | |
Time string `json:"time"` | |
RemoteAddr string `json:"remote_addr"` | |
RemoteUser string `json:"remote_user"` | |
BodyBytesSent int `json:"body_bytes_sent"` | |
RequestTime float32 `json:"request_time"` | |
Status int `json:"status"` | |
Request string `json:"request"` | |
HttpReferrer string `json:"http_referrer"` | |
HttpUserAgent string `json:"http_user_agent"` | |
UpstreamResponseTime float32 `json:"upstream_response_time"` | |
} | |
type Measurement struct { | |
Count int | |
BodyButesSentTotal int | |
RequestTimeTotal float32 | |
Status2xx int | |
Status3xx int | |
Status4xx int | |
Status5xx int | |
UpstreamResponseTimeTotal float32 | |
} | |
func (m Measurement) BodyButesSentAverage() int { | |
return m.BodyButesSentTotal * 100 / m.Count | |
} | |
func (m Measurement) RequestTimeAverage() float32 { | |
return m.RequestTimeTotal * 100.0 / float32(m.Count) | |
} | |
func (m Measurement) UpstreamResponseTimeAverage() float32 { | |
return m.UpstreamResponseTimeTotal * 100.0 / float32(m.Count) | |
} | |
func main() { | |
scanner := bufio.NewScanner(os.Stdin) | |
total := make(map[string]Measurement) | |
for { | |
var line Line | |
if ok := scanner.Scan(); !ok { | |
break | |
} | |
if err := json.Unmarshal(scanner.Bytes(), &line); err != nil { | |
continue | |
} | |
status2xx, status3xx, status4xx, status5xx := 0, 0, 0, 0 | |
if line.Status >= 200 && line.Status < 300 { | |
status2xx = 1 | |
} | |
if line.Status >= 300 && line.Status < 400 { | |
status3xx = 1 | |
} | |
if line.Status >= 400 && line.Status < 500 { | |
status4xx = 1 | |
} | |
if line.Status >= 500 { | |
status5xx = 1 | |
} | |
if m, ok := total[line.Request]; ok { | |
m.Count += 1 | |
m.BodyButesSentTotal += line.BodyBytesSent | |
m.RequestTimeTotal += line.RequestTime | |
m.Status2xx += status2xx | |
m.Status3xx += status3xx | |
m.Status4xx += status4xx | |
m.Status5xx += status5xx | |
m.UpstreamResponseTimeTotal += line.UpstreamResponseTime | |
total[line.Request] = m | |
} else { | |
total[line.Request] = Measurement{ | |
Count: 1, | |
BodyButesSentTotal: line.BodyBytesSent, | |
RequestTimeTotal: line.RequestTime, | |
Status2xx: status2xx, | |
Status3xx: status3xx, | |
Status4xx: status4xx, | |
Status5xx: status5xx, | |
UpstreamResponseTimeTotal: line.UpstreamResponseTime, | |
} | |
} | |
} | |
fmt.Println("| request | count | 2xx | 3xx | 4xx | 5xx | request time(avg) | upstream response time(avg) |") | |
fmt.Println("|:--------|------:|----:|----:|----:|----:|------------------:|----------------------------:|") | |
for r, m := range total { | |
fmt.Printf( | |
"| %s | %d | %d | %d | %d | %d | %f | %f |\n", | |
r, | |
m.Count, | |
m.Status2xx, | |
m.Status3xx, | |
m.Status4xx, | |
m.Status5xx, | |
m.RequestTimeAverage(), | |
m.UpstreamResponseTimeAverage(), | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment