blob: 070fedd010426fb7c5e056f2015aba761bff86be [file] [log] [blame]
// Package recent tracks the last 20 incoming JSON request.
package recent
import (
"bytes"
"encoding/json"
"sync"
"time"
)
const (
// maxRecent is the largest number of recent requests that will be displayed.
maxRecent = 20
)
// Request is a record of a single POST request.
type Request struct {
TS string
JSON string
Reason string
}
// Recent tracks the last MAX_RECENT Requests.
type Recent struct {
// mutex guards access to recent.
mutex sync.Mutex
// recentGood is just the last MAX_RECENT requests.
recentGood []*Request
// recentBad is just the last MAX_RECENT requests.
recentBad []*Request
}
// New returns a new Recent instance.
func New() *Recent {
return &Recent{
recentGood: []*Request{},
recentBad: []*Request{},
}
}
func (r *Recent) add(recent []*Request, b []byte, msg string) []*Request {
// Store locally.
r.mutex.Lock()
defer r.mutex.Unlock()
recent = append([]*Request{{
TS: time.Now().UTC().String(),
JSON: string(b),
Reason: msg,
}}, recent...)
// Keep track of the last N events.
if len(recent) > maxRecent {
recent = recent[:maxRecent]
}
return recent
}
// AddBad the JSON body that was POST'd to the server.
func (r *Recent) AddBad(b []byte, msg string) {
// Try to pretty print the JSON is possible, otherwise just use the raw bytes.
buf := bytes.NewReader(b)
var i interface{}
if err := json.NewDecoder(buf).Decode(&i); err != nil {
r.recentBad = r.add(r.recentBad, b, msg)
return
}
pretty, err := json.MarshalIndent(i, "", " ")
if err != nil {
r.recentBad = r.add(r.recentBad, b, msg)
return
}
r.recentBad = r.add(r.recentBad, pretty, msg)
}
// AddGood the JSON body that was POST'd to the server.
func (r *Recent) AddGood(b []byte) {
r.recentGood = r.add(r.recentGood, b, "")
}
// List returns the last MAX_RECENT Good and Bad Requests, with the most recent
// Requests first.
func (r *Recent) List() ([]*Request, []*Request) {
r.mutex.Lock()
defer r.mutex.Unlock()
good := make([]*Request, len(r.recentGood), len(r.recentGood))
for i, req := range r.recentGood {
good[i] = req
}
bad := make([]*Request, len(r.recentBad), len(r.recentBad))
for i, req := range r.recentBad {
bad[i] = req
}
return good, bad
}