1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- package web
- import (
- "encoding/json"
- "net/http"
- "path/filepath"
- "strconv"
- "sync"
- "github.com/gorilla/mux"
- )
- // Stats implement a statistics counter for hits to the FizzBuzz endpoint.
- type Stats struct {
- sync.Mutex
- hits map[string]int
- maxKey string
- maxHits int
- }
- // Incr records a hit in a way that supports reporting in O(1) time and space.
- func (s *Stats) Incr(int1, int2, limit int, str1, str2 string) {
- s.Lock()
- defer s.Unlock()
- key := filepath.Join(strconv.Itoa(int1), strconv.Itoa(int2), strconv.Itoa(limit), str1, str2)
- s.hits[key]++
- if s.hits[key] <= s.maxHits {
- return
- }
- s.maxHits = s.hits[key]
- s.maxKey = key
- }
- // MarshalJSON implements [json.Marshaler].
- func (s *Stats) MarshalJSON() ([]byte, error) {
- raw := map[string]any{
- "key": s.maxKey,
- "hits": s.maxHits,
- }
- return json.Marshal(raw)
- }
- // Handler provides the statistics endpoint.
- func (s *Stats) Handler() http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set(CT, JSON)
- enc := json.NewEncoder(w)
- enc.SetEscapeHTML(true)
- enc.SetIndent("", " ")
- enc.Encode(s)
- }
- }
- // Middleware provides the statistics middleware.
- func (s *Stats) Middleware() mux.MiddlewareFunc {
- return func(h http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- int1, int2, limit, str1, str2, status := argsFromRequest(r)
- if status >= http.StatusBadRequest {
- http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
- return
- }
- s.Incr(int1, int2, limit, str1, str2)
- h.ServeHTTP(w, r)
- })
- }
- }
- func NewStats() *Stats {
- return &Stats{hits: make(map[string]int)}
- }
|