148 lines
3.1 KiB
Go
148 lines
3.1 KiB
Go
package trantor
|
|
|
|
import (
|
|
log "github.com/cihub/seelog"
|
|
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gorilla/mux"
|
|
"gitlab.com/trantor/trantor/lib/database"
|
|
"gitlab.com/trantor/trantor/lib/storage"
|
|
)
|
|
|
|
const (
|
|
stats_version = 2
|
|
statsChanSize = 100
|
|
)
|
|
|
|
type handler struct {
|
|
w http.ResponseWriter
|
|
r *http.Request
|
|
sess *Session
|
|
db database.DB
|
|
store storage.Store
|
|
template *Template
|
|
hostname string
|
|
ro bool
|
|
}
|
|
|
|
type StatsGatherer struct {
|
|
db database.DB
|
|
store storage.Store
|
|
template *Template
|
|
hostname string
|
|
channel chan statsRequest
|
|
ro bool
|
|
}
|
|
|
|
func InitStats(database database.DB, store storage.Store, hostname string, template *Template, ro bool) *StatsGatherer {
|
|
sg := StatsGatherer{
|
|
channel: make(chan statsRequest, statsChanSize),
|
|
db: database,
|
|
store: store,
|
|
template: template,
|
|
hostname: hostname,
|
|
ro: ro,
|
|
}
|
|
|
|
go sg.worker()
|
|
return &sg
|
|
}
|
|
|
|
func (sg StatsGatherer) Gather(function func(handler)) func(http.ResponseWriter, *http.Request) {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
log.Info("Query ", r.Method, " ", r.RequestURI)
|
|
|
|
h := handler{
|
|
store: sg.store,
|
|
db: sg.db,
|
|
template: sg.template,
|
|
hostname: sg.hostname,
|
|
w: w,
|
|
r: r,
|
|
sess: GetSession(r, sg.db),
|
|
ro: sg.ro,
|
|
}
|
|
|
|
function(h)
|
|
sg.channel <- statsRequest{time.Now(), mux.Vars(r), h.sess, r}
|
|
}
|
|
}
|
|
|
|
type statsRequest struct {
|
|
date time.Time
|
|
vars map[string]string
|
|
sess *Session
|
|
r *http.Request
|
|
}
|
|
|
|
func (sg StatsGatherer) worker() {
|
|
for req := range sg.channel {
|
|
stats := make(map[string]interface{})
|
|
appendFiles(req.r, stats)
|
|
appendMuxVars(req.vars, stats)
|
|
appendUrl(req.r, stats)
|
|
appendSession(req.sess, stats)
|
|
stats["version"] = stats_version
|
|
stats["method"] = req.r.Method
|
|
stats["date"] = req.date
|
|
sg.db.AddStats(stats)
|
|
}
|
|
}
|
|
|
|
func appendFiles(r *http.Request, stats map[string]interface{}) {
|
|
if r.Method == "POST" && r.MultipartForm != nil {
|
|
files := r.MultipartForm.File
|
|
for key := range files {
|
|
list := make([]string, len(files[key]))
|
|
for i, f := range files[key] {
|
|
list[i] = f.Filename
|
|
}
|
|
stats[key] = list
|
|
}
|
|
}
|
|
}
|
|
|
|
func appendMuxVars(vars map[string]string, stats map[string]interface{}) {
|
|
for key, value := range vars {
|
|
switch {
|
|
case key == "id":
|
|
stats["id"] = value
|
|
case key == "ids":
|
|
var objectIds []string
|
|
ids := strings.Split(value, "/")
|
|
for _, id := range ids {
|
|
objectIds = append(objectIds, id)
|
|
}
|
|
if len(objectIds) > 0 {
|
|
stats["ids"] = objectIds
|
|
stats["id"] = objectIds[0]
|
|
}
|
|
default:
|
|
stats[key] = value
|
|
}
|
|
}
|
|
}
|
|
|
|
func appendUrl(r *http.Request, stats map[string]interface{}) {
|
|
for key, value := range r.URL.Query() {
|
|
stats[key] = value
|
|
}
|
|
stats["host"] = r.Host
|
|
stats["path"] = r.URL.Path
|
|
pattern := strings.Split(r.URL.Path, "/")
|
|
if len(pattern) > 1 && pattern[1] != "" {
|
|
stats["section"] = pattern[1]
|
|
} else {
|
|
stats["section"] = "/"
|
|
}
|
|
}
|
|
|
|
func appendSession(sess *Session, stats map[string]interface{}) {
|
|
stats["session"] = sess.Id()
|
|
if sess.User != "" {
|
|
stats["user"] = sess.User
|
|
}
|
|
}
|