move: log parser
This commit is contained in:
20
interfaces/log-parser/refactor-notes/refactor-02/changes.md
Normal file
20
interfaces/log-parser/refactor-notes/refactor-02/changes.md
Normal file
@@ -0,0 +1,20 @@
|
||||
### PROBLEM
|
||||
+ `summarize()` knows a lot about the internals of the `parser`.
|
||||
+ coupled to the `parser`.
|
||||
|
||||
## SOLUTION
|
||||
+ remove: `parser.go` `sum` and `domains` fields
|
||||
+ remove: `parser.go/newParser()`
|
||||
+ change: `parser.go/parse(p *parser) error` -> `parse() ([]result, error)`
|
||||
+ initialize: `sum` inside `parse()`
|
||||
+ remove: `update()`
|
||||
+ call: `sum` update in the `parse()`
|
||||
+ collect the grouped results and return them from `parser()`
|
||||
|
||||
+ `summarize(p *parser)` -> `summarize([]result)`
|
||||
+ in `summarize()`
|
||||
+ `sort.Slice`
|
||||
+ range over `[]result`
|
||||
|
||||
+ `main.go`
|
||||
+ just: `res, err := parse()`
|
22
interfaces/log-parser/refactor-notes/refactor-02/main.go
Normal file
22
interfaces/log-parser/refactor-notes/refactor-02/main.go
Normal file
@@ -0,0 +1,22 @@
|
||||
// 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 main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res, err := parse()
|
||||
if err != nil {
|
||||
fmt.Println("> Err:", err)
|
||||
return
|
||||
}
|
||||
|
||||
summarize(res)
|
||||
}
|
48
interfaces/log-parser/refactor-notes/refactor-02/parser.go
Normal file
48
interfaces/log-parser/refactor-notes/refactor-02/parser.go
Normal file
@@ -0,0 +1,48 @@
|
||||
// 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 main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// parser keeps track of the parsing
|
||||
type parser struct {
|
||||
}
|
||||
|
||||
// parse the log lines and return results
|
||||
func parse() ([]result, error) {
|
||||
var (
|
||||
l = 1
|
||||
in = bufio.NewScanner(os.Stdin)
|
||||
sum = make(map[string]result)
|
||||
)
|
||||
|
||||
// parse the log lines
|
||||
for in.Scan() {
|
||||
r, err := parseResult(in.Text())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("line %d: %v", l, err)
|
||||
}
|
||||
|
||||
l++
|
||||
|
||||
// group the log lines by domain
|
||||
sum[r.domain] = addResult(r, sum[r.domain])
|
||||
}
|
||||
|
||||
// collect the grouped results
|
||||
res := make([]result, 0, len(sum))
|
||||
for _, r := range sum {
|
||||
res = append(res, r)
|
||||
}
|
||||
|
||||
return res, in.Err()
|
||||
}
|
53
interfaces/log-parser/refactor-notes/refactor-02/result.go
Normal file
53
interfaces/log-parser/refactor-notes/refactor-02/result.go
Normal file
@@ -0,0 +1,53 @@
|
||||
// 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 main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const fieldsLength = 4
|
||||
|
||||
// result stores the parsed result for a domain
|
||||
type result struct {
|
||||
domain, page string
|
||||
visits, uniques int
|
||||
// add more metrics if needed
|
||||
}
|
||||
|
||||
// parseResult from a log line
|
||||
func parseResult(line string) (r result, err error) {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) != fieldsLength {
|
||||
return r, fmt.Errorf("wrong input: %v", fields)
|
||||
}
|
||||
|
||||
r.domain = fields[0]
|
||||
r.page = fields[1]
|
||||
|
||||
r.visits, err = strconv.Atoi(fields[2])
|
||||
if err != nil || r.visits < 0 {
|
||||
return r, fmt.Errorf("wrong input: %q", fields[2])
|
||||
}
|
||||
|
||||
r.uniques, err = strconv.Atoi(fields[3])
|
||||
if err != nil || r.uniques < 0 {
|
||||
return r, fmt.Errorf("wrong input: %q", fields[3])
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// addResult to another one
|
||||
func addResult(r, other result) result {
|
||||
r.visits += other.visits
|
||||
r.uniques += other.uniques
|
||||
return r
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
// 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 main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// summarize summarizes and prints the parsing result
|
||||
// + violation: accesses the parsing internals: p.domains + p.sum + p.total
|
||||
// + give it the []result only.
|
||||
// + let it calculate the total.
|
||||
const (
|
||||
|
||||
// DOMAINS PAGES VISITS UNIQUES
|
||||
// ^ ^ ^ ^
|
||||
// | | | |
|
||||
header = "%-25s %-10s %10s %10s\n"
|
||||
line = "%-25s %-10s %10d %10d\n"
|
||||
footer = "\n%-36s %10d %10d\n" // -> "" VISITS UNIQUES
|
||||
dash = "-"
|
||||
dashLength = 58
|
||||
)
|
||||
|
||||
// summarize summarizes and prints the parsing result
|
||||
func summarize(res []result) {
|
||||
// sort.Strings(p.domains)
|
||||
sort.Slice(res, func(i, j int) bool {
|
||||
return res[i].domain <= res[j].domain
|
||||
})
|
||||
|
||||
fmt.Printf(header, "DOMAIN", "PAGES", "VISITS", "UNIQUES")
|
||||
fmt.Println(strings.Repeat("-", dashLength))
|
||||
|
||||
var total result
|
||||
|
||||
for _, r := range res {
|
||||
total = addResult(total, r)
|
||||
fmt.Printf(line, r.domain, r.page, r.visits, r.uniques)
|
||||
}
|
||||
fmt.Printf(footer, "TOTAL", total.visits, total.uniques)
|
||||
}
|
Reference in New Issue
Block a user