reqlog.go 1.82 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
package commands

import (
	"strings"
	"sync"
	"time"
)

type ReqLogEntry struct {
	StartTime time.Time
	EndTime   time.Time
	Active    bool
	Command   string
	Options   map[string]interface{}
	Args      []string
	ID        int

	req Request
	log *ReqLog
}

func (r *ReqLogEntry) Finish() {
23 24 25
	log := r.log
	log.lock.Lock()
	defer log.lock.Unlock()
26 27 28 29

	r.Active = false
	r.EndTime = time.Now()
	r.log.maybeCleanup()
30 31 32 33 34

	// remove references to save memory
	r.req = nil
	r.log = nil

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
}

func (r *ReqLogEntry) Copy() *ReqLogEntry {
	out := *r
	out.log = nil
	return &out
}

type ReqLog struct {
	Requests []*ReqLogEntry
	nextID   int
	lock     sync.Mutex
}

func (rl *ReqLog) Add(req Request) *ReqLogEntry {
	rl.lock.Lock()
	defer rl.lock.Unlock()

	rle := &ReqLogEntry{
		StartTime: time.Now(),
		Active:    true,
		Command:   strings.Join(req.Path(), "/"),
		Options:   req.Options(),
		Args:      req.Arguments(),
		ID:        rl.nextID,
		req:       req,
		log:       rl,
	}

	rl.nextID++
	rl.Requests = append(rl.Requests, rle)
	return rle
}

func (rl *ReqLog) maybeCleanup() {
	// only do it every so often or it might
	// become a perf issue
	if len(rl.Requests) == 0 {
		rl.cleanup()
	}
}

func (rl *ReqLog) cleanup() {
	var i int
Jeromy's avatar
Jeromy committed
79
	// drop all logs at are inactive and more than an hour old
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
	for ; i < len(rl.Requests); i++ {
		req := rl.Requests[i]
		if req.Active || req.EndTime.Add(time.Hour).After(time.Now()) {
			break
		}
	}

	if i > 0 {
		var j int
		for i < len(rl.Requests) {
			rl.Requests[j] = rl.Requests[i]
			j++
			i++
		}
		rl.Requests = rl.Requests[:len(rl.Requests)-i]
	}
}

Jeromy's avatar
Jeromy committed
98
// Report generates a copy of all the entries in the requestlog
99 100 101 102 103 104 105 106 107 108 109
func (rl *ReqLog) Report() []*ReqLogEntry {
	rl.lock.Lock()
	defer rl.lock.Unlock()
	out := make([]*ReqLogEntry, len(rl.Requests))

	for i, e := range rl.Requests {
		out[i] = e.Copy()
	}

	return out
}