coredns plugin -- Calculate top for domains, clients and blocked both from querylog and running requests.
This moves the functionality from frontend to coredns plugin.
This commit is contained in:
87
control.go
87
control.go
@@ -417,9 +417,9 @@ func handleStatsReset(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func handleStatsTop(w http.ResponseWriter, r *http.Request) {
|
||||
resp, err := client.Get("http://127.0.0.1:8618/querylog")
|
||||
resp, err := client.Get("http://127.0.0.1:8618/stats_top")
|
||||
if err != nil {
|
||||
errortext := fmt.Sprintf("Couldn't get querylog from coredns: %T %s\n", err, err)
|
||||
errortext := fmt.Sprintf("Couldn't get stats_top from coredns: %T %s\n", err, err)
|
||||
log.Println(errortext)
|
||||
http.Error(w, errortext, http.StatusBadGateway)
|
||||
return
|
||||
@@ -428,7 +428,7 @@ func handleStatsTop(w http.ResponseWriter, r *http.Request) {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
|
||||
// read body
|
||||
// read the body entirely
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
errortext := fmt.Sprintf("Couldn't read response body: %s", err)
|
||||
@@ -436,85 +436,12 @@ func handleStatsTop(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, errortext, http.StatusBadGateway)
|
||||
return
|
||||
}
|
||||
// empty body
|
||||
if len(body) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
values := []interface{}{}
|
||||
err = json.Unmarshal(body, &values)
|
||||
if err != nil {
|
||||
errortext := fmt.Sprintf("Couldn't parse response body: %s", err)
|
||||
log.Println(errortext)
|
||||
http.Error(w, errortext, http.StatusBadGateway)
|
||||
return
|
||||
}
|
||||
|
||||
domains := map[string]int{}
|
||||
blocked := map[string]int{}
|
||||
clients := map[string]int{}
|
||||
now := time.Now()
|
||||
timeWindow := time.Hour * 24
|
||||
notBefore := now.Add(timeWindow * -1)
|
||||
|
||||
for _, value := range values {
|
||||
entry, ok := value.(map[string]interface{})
|
||||
if !ok {
|
||||
// ignore anything else
|
||||
continue
|
||||
}
|
||||
host := getHost(entry)
|
||||
reason := getReason(entry)
|
||||
client := getClient(entry)
|
||||
time := getTime(entry)
|
||||
if time.Before(notBefore) {
|
||||
// skip if the entry is before specified cutoff
|
||||
continue
|
||||
}
|
||||
if len(host) > 0 {
|
||||
domains[host]++
|
||||
}
|
||||
if len(host) > 0 && strings.HasPrefix(reason, "Filtered") {
|
||||
blocked[host]++
|
||||
}
|
||||
if len(client) > 0 {
|
||||
clients[client]++
|
||||
}
|
||||
}
|
||||
|
||||
// use manual json marshalling because we want maps to be sorted by value
|
||||
json := bytes.Buffer{}
|
||||
json.WriteString("{\n")
|
||||
|
||||
gen := func(json *bytes.Buffer, name string, top map[string]int, addComma bool) {
|
||||
json.WriteString(" \"")
|
||||
json.WriteString(name)
|
||||
json.WriteString("\": {\n")
|
||||
sorted := sortByValue(top)
|
||||
for i, key := range sorted {
|
||||
json.WriteString(" \"")
|
||||
json.WriteString(key)
|
||||
json.WriteString("\": ")
|
||||
json.WriteString(strconv.Itoa(top[key]))
|
||||
if i+1 != len(sorted) {
|
||||
json.WriteByte(',')
|
||||
}
|
||||
json.WriteByte('\n')
|
||||
}
|
||||
json.WriteString(" }")
|
||||
if addComma {
|
||||
json.WriteByte(',')
|
||||
}
|
||||
json.WriteByte('\n')
|
||||
}
|
||||
gen(&json, "top_queried_domains", domains, true)
|
||||
gen(&json, "top_blocked_domains", blocked, true)
|
||||
gen(&json, "top_clients", clients, true)
|
||||
json.WriteString(" \"stats_period\": \"24 hours\"\n")
|
||||
json.WriteString("}\n")
|
||||
|
||||
// forward body entirely with status code
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, err = w.Write(json.Bytes())
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(body)))
|
||||
w.WriteHeader(resp.StatusCode)
|
||||
_, err = w.Write(body)
|
||||
if err != nil {
|
||||
errortext := fmt.Sprintf("Couldn't write body: %s", err)
|
||||
log.Println(errortext)
|
||||
|
||||
Reference in New Issue
Block a user