Files
learngo/x-tba/2-methods/xxx-log-parser-methods/packaged/metrics/report.go
2019-04-26 10:11:17 +03:00

90 lines
2.1 KiB
Go

// For more tutorials: https://blog.learngoprogramming.com
//
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
package metrics
import (
"encoding/json"
"sort"
)
// Report aggregates the final report
type Report struct {
sum map[string]result // metrics per domain
domains []string // unique domain names
total result // total visits for all domains
}
// NewReport constructs and initializes a new report
func NewReport() *Report {
return &Report{sum: make(map[string]result)}
}
// Update updates the report for the given parsing result
func (r *Report) Update(parsed Parsed) {
// do not update the report if the result has an error
if parsed.err != nil {
return
}
domain := parsed.Domain
if _, ok := r.sum[domain]; !ok {
r.domains = append(r.domains, domain)
}
// let the result handle the addition
// this allows us to manage the result in once place
// and this way it becomes easily extendable
r.total = r.total.add(parsed.result)
r.sum[domain] = parsed.add(r.sum[domain])
}
// Iterator returns `next()` to detect when the iteration ends,
// and a `cur()` to return the current result.
// iterator iterates sorted by domains.
func (r *Report) Iterator() (next func() bool, cur func() result) {
sort.Strings(r.domains)
// remember the last iterated result
var last int
next = func() bool {
defer func() { last++ }()
return len(r.domains) > last
}
cur = func() result {
// returns a copy so the caller cannot change it
name := r.domains[last-1]
return r.sum[name]
}
return
}
// Total returns the total metrics
func (r *Report) Total() Parsed {
return Parsed{result: r.total}
}
// MarshalJSON marshals a report to JSON
// Alternative: unexported embedding
func (r *Report) MarshalJSON() ([]byte, error) {
type total struct {
*result
IgnoreDomain *string `json:"Domain,omitempty"`
}
return json.Marshal(struct {
Sum map[string]result
Domains []string
Total total
}{
Sum: r.sum, Domains: r.domains, Total: total{result: &r.total},
})
}