|
|
|
package stats
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/chubin/wttr.in/internal/routing"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Stats holds processed requests statistics.
|
|
|
|
type Stats struct {
|
|
|
|
m sync.Mutex
|
|
|
|
v map[string]int
|
|
|
|
startTime time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
// New returns new Stats.
|
|
|
|
func New() *Stats {
|
|
|
|
return &Stats{
|
|
|
|
v: map[string]int{},
|
|
|
|
startTime: time.Now(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Inc key by one.
|
|
|
|
func (c *Stats) Inc(key string) {
|
|
|
|
c.m.Lock()
|
|
|
|
c.v[key]++
|
|
|
|
c.m.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get current key counter value.
|
|
|
|
func (c *Stats) Get(key string) int {
|
|
|
|
c.m.Lock()
|
|
|
|
defer c.m.Unlock()
|
|
|
|
|
|
|
|
return c.v[key]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset key counter.
|
|
|
|
func (c *Stats) Reset(key string) int {
|
|
|
|
c.m.Lock()
|
|
|
|
defer c.m.Unlock()
|
|
|
|
result := c.v[key]
|
|
|
|
c.v[key] = 0
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show returns current statistics formatted as []byte.
|
|
|
|
func (c *Stats) Show() []byte {
|
|
|
|
var b bytes.Buffer
|
|
|
|
|
|
|
|
c.m.Lock()
|
|
|
|
defer c.m.Unlock()
|
|
|
|
|
|
|
|
uptime := time.Since(c.startTime) / time.Second
|
|
|
|
|
|
|
|
fmt.Fprintf(&b, "%-20s: %v\n", "Running since", c.startTime.Format(time.RFC3339))
|
|
|
|
fmt.Fprintf(&b, "%-20s: %d\n", "Uptime (min)", uptime/60)
|
|
|
|
|
|
|
|
fmt.Fprintf(&b, "%-20s: %d\n", "Total queries", c.v["total"])
|
|
|
|
|
|
|
|
if uptime != 0 {
|
|
|
|
fmt.Fprintf(&b, "%-20s: %d\n", "Throughput (QpM)", c.v["total"]*60/int(uptime))
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Fprintf(&b, "%-20s: %d\n", "Cache L1 queries", c.v["cache1"])
|
|
|
|
|
|
|
|
if c.v["total"] != 0 {
|
|
|
|
fmt.Fprintf(&b, "%-20s: %d\n", "Cache L1 queries (%)", (100*c.v["cache1"])/c.v["total"])
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Fprintf(&b, "%-20s: %d\n", "Upstream queries", c.v["total"]-c.v["cache1"])
|
|
|
|
fmt.Fprintf(&b, "%-20s: %d\n", "Queries with format", c.v["format"])
|
|
|
|
fmt.Fprintf(&b, "%-20s: %d\n", "Queries with format=j1", c.v["format=j1"])
|
|
|
|
fmt.Fprintf(&b, "%-20s: %d\n", "Queries with known IP", c.v["geoip"])
|
|
|
|
|
|
|
|
return b.Bytes()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Stats) Response(*http.Request) *routing.Cadre {
|
|
|
|
return &routing.Cadre{
|
|
|
|
Body: c.Show(),
|
|
|
|
}
|
|
|
|
}
|