This repository has been archived on 2025-03-01. You can view files and clone it, but cannot push or open issues or pull requests.
trantor/stats.go

198 lines
4.2 KiB
Go
Raw Normal View History

2013-04-22 23:28:00 +02:00
package main
import (
2014-08-30 13:17:50 -05:00
log "github.com/cihub/seelog"
2013-04-22 23:28:00 +02:00
"net/http"
2013-05-31 23:59:01 +02:00
"strconv"
2013-04-22 23:28:00 +02:00
"strings"
"time"
"git.gitorious.org/trantor/trantor.git/database"
"git.gitorious.org/trantor/trantor.git/storage"
"github.com/gorilla/mux"
2013-04-22 23:28:00 +02:00
)
2014-08-21 19:24:23 -05:00
const (
stats_version = 2
)
type handler struct {
2014-08-21 19:24:23 -05:00
w http.ResponseWriter
r *http.Request
sess *Session
db *database.DB
store *storage.Store
}
2014-08-21 19:24:23 -05:00
type StatsGatherer struct {
db *database.DB
store *storage.Store
channel chan statsRequest
2013-04-22 23:28:00 +02:00
}
2014-08-21 19:24:23 -05:00
func InitStats(database *database.DB, store *storage.Store) *StatsGatherer {
sg := new(StatsGatherer)
sg.channel = make(chan statsRequest, CHAN_SIZE)
sg.db = database
sg.store = store
go sg.worker()
return sg
}
func (sg StatsGatherer) Gather(function func(handler)) func(http.ResponseWriter, *http.Request) {
2013-04-22 23:28:00 +02:00
return func(w http.ResponseWriter, r *http.Request) {
2014-02-11 14:41:50 +01:00
log.Info("Query ", r.Method, " ", r.RequestURI)
var h handler
2014-08-21 19:24:23 -05:00
h.store = sg.store
h.db = sg.db.Copy()
defer h.db.Close()
h.w = w
h.r = r
h.sess = GetSession(r, h.db)
function(h)
2014-08-21 19:24:23 -05:00
sg.channel <- statsRequest{time.Now(), mux.Vars(r), h.sess, r}
2013-04-22 23:28:00 +02:00
}
}
type statsRequest struct {
date time.Time
vars map[string]string
sess *Session
r *http.Request
}
2014-08-21 19:24:23 -05:00
func (sg StatsGatherer) worker() {
db := sg.db.Copy()
defer db.Close()
2014-08-21 19:24:23 -05:00
for req := range sg.channel {
2013-04-22 23:28:00 +02:00
stats := make(map[string]interface{})
appendFiles(req.r, stats)
appendMuxVars(req.vars, stats)
appendUrl(req.r, stats)
appendSession(req.sess, stats)
2014-08-21 19:24:23 -05:00
stats["version"] = stats_version
2013-04-22 23:28:00 +02:00
stats["method"] = req.r.Method
stats["date"] = req.date
2014-06-29 19:41:29 -05:00
db.AddStats(stats)
2013-04-22 23:28:00 +02:00
}
}
func statsHandler(h handler) {
2013-05-05 01:39:28 +02:00
var data statsData
data.S = GetStatus(h)
2013-06-01 04:30:52 +02:00
data.S.Stats = true
2014-06-29 19:41:29 -05:00
data.HVisits = getVisits(hourlyLabel, h.db, database.Hourly_visits)
data.DVisits = getVisits(dailyLabel, h.db, database.Daily_visits)
data.MVisits = getVisits(monthlyLabel, h.db, database.Monthly_visits)
data.HDownloads = getVisits(hourlyLabel, h.db, database.Hourly_downloads)
data.DDownloads = getVisits(dailyLabel, h.db, database.Daily_downloads)
data.MDownloads = getVisits(monthlyLabel, h.db, database.Monthly_downloads)
2013-05-31 23:59:01 +02:00
loadTemplate(h, "stats", data)
2013-05-05 01:39:28 +02:00
}
type statsData struct {
S Status
HVisits []visitData
DVisits []visitData
MVisits []visitData
HDownloads []visitData
DDownloads []visitData
MDownloads []visitData
2013-05-31 23:59:01 +02:00
}
type visitData struct {
Label string
Count int
}
2014-02-19 00:59:55 +01:00
func hourlyLabel(date time.Time) string {
return strconv.Itoa(date.Hour() + 1)
2013-06-01 03:40:06 +02:00
}
2014-02-19 00:59:55 +01:00
func dailyLabel(date time.Time) string {
return strconv.Itoa(date.Day())
2013-05-05 01:39:28 +02:00
}
2014-02-19 00:59:55 +01:00
func monthlyLabel(date time.Time) string {
return date.Month().String()
}
2014-06-29 19:41:29 -05:00
func getVisits(funcLabel func(time.Time) string, db *database.DB, visitType database.VisitType) []visitData {
var visits []visitData
2014-02-19 00:59:55 +01:00
visit, err := db.GetVisits(visitType)
if err != nil {
log.Warn("GetVisits error (", visitType, "): ", err)
}
for _, v := range visit {
var elem visitData
2014-02-19 00:59:55 +01:00
elem.Label = funcLabel(v.Date.UTC())
elem.Count = v.Count
visits = append(visits, elem)
}
return visits
}
2013-04-22 23:28:00 +02:00
func appendFiles(r *http.Request, stats map[string]interface{}) {
if r.Method == "POST" && r.MultipartForm != nil {
2013-04-22 23:28:00 +02:00
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":
2014-08-21 19:24:23 -05:00
stats["id"] = value
2013-04-22 23:28:00 +02:00
case key == "ids":
2014-08-21 19:24:23 -05:00
var objectIds []string
2013-04-22 23:28:00 +02:00
ids := strings.Split(value, "/")
for _, id := range ids {
2014-08-21 19:24:23 -05:00
objectIds = append(objectIds, id)
2013-04-22 23:28:00 +02:00
}
2013-05-09 09:42:58 +02:00
if len(objectIds) > 0 {
stats["ids"] = objectIds
stats["id"] = objectIds[0]
}
2013-04-22 23:28:00 +02:00
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
}
}