2013-04-22 23:28:00 +02:00
|
|
|
package main
|
|
|
|
|
2014-02-11 14:41:50 +01:00
|
|
|
import log "github.com/cihub/seelog"
|
|
|
|
|
2013-04-22 23:28:00 +02:00
|
|
|
import (
|
|
|
|
"github.com/gorilla/mux"
|
|
|
|
"labix.org/v2/mgo/bson"
|
|
|
|
"net/http"
|
2013-05-31 23:59:01 +02:00
|
|
|
"strconv"
|
2013-04-22 23:28:00 +02:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2013-09-23 16:27:31 +02:00
|
|
|
type handler struct {
|
|
|
|
w http.ResponseWriter
|
|
|
|
r *http.Request
|
|
|
|
sess *Session
|
|
|
|
db *DB
|
|
|
|
}
|
|
|
|
|
|
|
|
func InitStats(database *DB) {
|
2013-05-03 00:43:26 +02:00
|
|
|
statsChannel = make(chan statsRequest, CHAN_SIZE)
|
2013-09-23 16:27:31 +02:00
|
|
|
go statsWorker(database)
|
2013-04-22 23:28:00 +02:00
|
|
|
}
|
|
|
|
|
2013-09-23 16:27:31 +02:00
|
|
|
func GatherStats(function func(handler), database *DB) 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)
|
|
|
|
|
2013-09-23 16:27:31 +02:00
|
|
|
var h handler
|
|
|
|
h.db = database.Copy()
|
|
|
|
defer h.db.Close()
|
|
|
|
|
|
|
|
h.w = w
|
|
|
|
h.r = r
|
|
|
|
h.sess = GetSession(r, h.db)
|
|
|
|
function(h)
|
|
|
|
|
|
|
|
statsChannel <- statsRequest{bson.Now(), mux.Vars(r), h.sess, r}
|
2013-04-22 23:28:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var statsChannel chan statsRequest
|
|
|
|
|
|
|
|
type statsRequest struct {
|
|
|
|
date time.Time
|
|
|
|
vars map[string]string
|
|
|
|
sess *Session
|
|
|
|
r *http.Request
|
|
|
|
}
|
|
|
|
|
2013-09-23 16:27:31 +02:00
|
|
|
func statsWorker(database *DB) {
|
|
|
|
db := database.Copy()
|
|
|
|
defer db.Close()
|
|
|
|
|
2013-04-22 23:28:00 +02:00
|
|
|
for req := range statsChannel {
|
|
|
|
stats := make(map[string]interface{})
|
|
|
|
appendFiles(req.r, stats)
|
|
|
|
appendMuxVars(req.vars, stats)
|
|
|
|
appendUrl(req.r, stats)
|
|
|
|
appendSession(req.sess, stats)
|
|
|
|
stats["method"] = req.r.Method
|
|
|
|
stats["date"] = req.date
|
|
|
|
db.InsertStats(stats)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-23 16:27:31 +02:00
|
|
|
func statsHandler(h handler) {
|
2013-05-05 01:39:28 +02:00
|
|
|
var data statsData
|
2013-09-23 16:27:31 +02:00
|
|
|
data.S = GetStatus(h)
|
2013-06-01 04:30:52 +02:00
|
|
|
data.S.Stats = true
|
2013-09-24 14:22:53 +02:00
|
|
|
data.HVisits = getHourlyVisits(h.db)
|
|
|
|
data.DVisits = getDailyVisits(h.db)
|
|
|
|
data.MVisits = getMonthlyVisits(h.db)
|
|
|
|
data.HDownloads = getHourlyDownloads(h.db)
|
|
|
|
data.DDownloads = getDailyDownloads(h.db)
|
|
|
|
data.MDownloads = getMonthlyDownloads(h.db)
|
2013-05-31 23:59:01 +02:00
|
|
|
|
2013-09-23 16:27:31 +02:00
|
|
|
loadTemplate(h.w, "stats", data)
|
2013-05-05 01:39:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type statsData struct {
|
2013-09-24 14:22:53 +02:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2013-09-23 16:27:31 +02:00
|
|
|
func getHourlyVisits(db *DB) []visitData {
|
2013-06-01 03:40:06 +02:00
|
|
|
var visits []visitData
|
|
|
|
|
2014-02-09 23:22:45 +01:00
|
|
|
visit, _ := db.GetHourVisits()
|
2013-06-01 03:40:06 +02:00
|
|
|
for _, v := range visit {
|
|
|
|
var elem visitData
|
|
|
|
hour := time.Unix(v.Date/1000, 0).UTC().Hour()
|
|
|
|
elem.Label = strconv.Itoa(hour + 1)
|
|
|
|
elem.Count = v.Count
|
|
|
|
visits = append(visits, elem)
|
|
|
|
}
|
|
|
|
|
|
|
|
return visits
|
|
|
|
}
|
|
|
|
|
2013-09-23 16:27:31 +02:00
|
|
|
func getDailyVisits(db *DB) []visitData {
|
2013-06-01 03:40:06 +02:00
|
|
|
var visits []visitData
|
2013-05-31 23:59:01 +02:00
|
|
|
|
2014-02-09 23:22:45 +01:00
|
|
|
visit, _ := db.GetDayVisits()
|
2013-05-31 23:59:01 +02:00
|
|
|
for _, v := range visit {
|
2013-06-01 03:40:06 +02:00
|
|
|
var elem visitData
|
|
|
|
day := time.Unix(v.Date/1000, 0).UTC().Day()
|
|
|
|
elem.Label = strconv.Itoa(day)
|
|
|
|
elem.Count = v.Count
|
|
|
|
visits = append(visits, elem)
|
|
|
|
}
|
|
|
|
|
|
|
|
return visits
|
|
|
|
}
|
|
|
|
|
2013-09-23 16:27:31 +02:00
|
|
|
func getMonthlyVisits(db *DB) []visitData {
|
2013-06-01 03:40:06 +02:00
|
|
|
var visits []visitData
|
|
|
|
|
2014-02-09 23:22:45 +01:00
|
|
|
visit, _ := db.GetMonthVisits()
|
2013-06-01 03:40:06 +02:00
|
|
|
for _, v := range visit {
|
|
|
|
var elem visitData
|
|
|
|
month := time.Unix(v.Date/1000, 0).UTC().Month()
|
|
|
|
elem.Label = month.String()
|
|
|
|
elem.Count = v.Count
|
|
|
|
visits = append(visits, elem)
|
2013-05-31 23:59:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return visits
|
2013-05-05 01:39:28 +02:00
|
|
|
}
|
|
|
|
|
2013-09-24 14:22:53 +02:00
|
|
|
func getHourlyDownloads(db *DB) []visitData {
|
|
|
|
var visits []visitData
|
|
|
|
|
2014-02-09 23:22:45 +01:00
|
|
|
visit, _ := db.GetHourDownloads()
|
2013-09-24 14:22:53 +02:00
|
|
|
for _, v := range visit {
|
|
|
|
var elem visitData
|
|
|
|
hour := time.Unix(v.Date/1000, 0).UTC().Hour()
|
|
|
|
elem.Label = strconv.Itoa(hour + 1)
|
|
|
|
elem.Count = v.Count
|
|
|
|
visits = append(visits, elem)
|
|
|
|
}
|
|
|
|
|
|
|
|
return visits
|
|
|
|
}
|
|
|
|
|
|
|
|
func getDailyDownloads(db *DB) []visitData {
|
|
|
|
var visits []visitData
|
|
|
|
|
2014-02-09 23:22:45 +01:00
|
|
|
visit, _ := db.GetDayDownloads()
|
2013-09-24 14:22:53 +02:00
|
|
|
for _, v := range visit {
|
|
|
|
var elem visitData
|
|
|
|
day := time.Unix(v.Date/1000, 0).UTC().Day()
|
|
|
|
elem.Label = strconv.Itoa(day)
|
|
|
|
elem.Count = v.Count
|
|
|
|
visits = append(visits, elem)
|
|
|
|
}
|
|
|
|
|
|
|
|
return visits
|
|
|
|
}
|
|
|
|
|
|
|
|
func getMonthlyDownloads(db *DB) []visitData {
|
|
|
|
var visits []visitData
|
|
|
|
|
2014-02-09 23:22:45 +01:00
|
|
|
visit, _ := db.GetMonthDownloads()
|
2013-09-24 14:22:53 +02:00
|
|
|
for _, v := range visit {
|
|
|
|
var elem visitData
|
|
|
|
month := time.Unix(v.Date/1000, 0).UTC().Month()
|
|
|
|
elem.Label = month.String()
|
|
|
|
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{}) {
|
2013-04-23 20:33:21 +02:00
|
|
|
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":
|
2013-05-09 09:42:58 +02:00
|
|
|
if bson.IsObjectIdHex(value) {
|
|
|
|
stats["id"] = bson.ObjectIdHex(value)
|
|
|
|
}
|
2013-04-22 23:28:00 +02:00
|
|
|
case key == "ids":
|
2013-05-02 23:45:52 +02:00
|
|
|
var objectIds []bson.ObjectId
|
2013-04-22 23:28:00 +02:00
|
|
|
ids := strings.Split(value, "/")
|
2013-05-02 23:45:52 +02:00
|
|
|
for _, id := range ids {
|
2013-05-09 09:42:58 +02:00
|
|
|
if bson.IsObjectIdHex(value) {
|
|
|
|
objectIds = append(objectIds, bson.ObjectIdHex(id))
|
2013-05-02 23:45:52 +02:00
|
|
|
}
|
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
|
|
|
|
}
|
|
|
|
}
|