Files

148 lines
3.4 KiB
Go

package middleware
import (
"bytes"
"encoding/json"
"net/http"
"strconv"
"sync"
. "github.com/mickael-kerjean/filestash/server/pkg/config"
. "github.com/mickael-kerjean/filestash/server/pkg/core"
. "github.com/mickael-kerjean/filestash/server/pkg/env"
. "github.com/mickael-kerjean/filestash/server/pkg/utils"
)
var (
telemetry = Telemetry{Data: make([]LogEntry, 0)}
version = APP_VERSION + "." + BUILD_DATE
)
type Telemetry struct {
Data []LogEntry
mu sync.Mutex
}
type LogEntry struct {
Host string `json:"host"`
Method string `json:"method"`
RequestURI string `json:"pathname"`
Proto string `json:"proto"`
Status int `json:"status"`
Scheme string `json:"scheme"`
UserAgent string `json:"userAgent"`
Ip string `json:"ip"`
Referer string `json:"referer"`
Duration int `json:"responseTime"`
Version string `json:"version"`
Backend string `json:"backend"`
Share string `json:"share"`
License string `json:"license"`
Session string `json:"session"`
RequestID string `json:"requestID"`
}
func logger(ctx *App, res *ResponseWriter, req *http.Request) {
if req.RequestURI == "/about" {
return
}
point := LogEntry{
Version: version,
License: LICENSE,
Scheme: req.URL.Scheme,
Host: req.Host,
Method: req.Method,
RequestURI: req.RequestURI,
Proto: req.Proto,
Status: res.status,
UserAgent: req.Header.Get("User-Agent"),
Ip: req.RemoteAddr,
Referer: req.Referer(),
Duration: int((now() - res.start) / (100_000)),
Backend: func() string {
if ctx.Session["type"] == "" {
return "null"
}
return ctx.Session["type"]
}(),
Share: func() string {
if ctx.Share.Id == "" {
return "null"
}
return ctx.Share.Id
}(),
Session: func() string {
if ctx.Session["type"] == "" {
return "null"
}
return GenerateID(ctx.Session)
}(),
RequestID: res.Header().Get("X-Request-Id"),
}
if Config.Get("log.telemetry").Bool() {
telemetry.Record(point)
}
if Config.Get("log.enable").Bool() {
var (
arr [512]byte
num [32]byte
)
buf := bytes.NewBuffer(arr[:0])
buf.WriteString("HTTP ")
buf.Write(strconv.AppendInt(num[:0], int64(point.Status), 10))
buf.WriteByte(' ')
buf.WriteString(point.Method)
buf.WriteByte(' ')
buf.Write(strconv.AppendInt(num[:0], int64(point.Duration/10), 10))
buf.WriteByte('.')
buf.Write(strconv.AppendInt(num[:0], int64(point.Duration%10), 10))
buf.WriteString("ms ")
if uri := point.RequestURI; len(uri) > 200 {
buf.WriteString(uri[:200])
buf.WriteString("...")
} else {
buf.WriteString(uri)
}
buf.WriteByte(' ')
if point.RequestID != "" && Config.Get("log.level").String() == "DEBUG" {
buf.WriteString("trace=")
buf.WriteString(point.RequestID)
}
Log.Raw(buf.Bytes())
}
}
func (this *Telemetry) Record(point LogEntry) {
point.Duration *= 10
this.mu.Lock()
this.Data = append(this.Data, point)
this.mu.Unlock()
}
func (this *Telemetry) Flush() {
if len(this.Data) == 0 {
return
}
this.mu.Lock()
pts := this.Data
this.Data = make([]LogEntry, 0)
this.mu.Unlock()
body, err := json.Marshal(pts)
if err != nil {
return
}
r, err := http.NewRequest("POST", "https://downloads.filestash.app/event", bytes.NewReader(body))
r.Header.Set("Connection", "Close")
r.Header.Set("Content-Type", "application/json")
r.Close = true
if err != nil {
return
}
resp, err := HTTP.Do(r)
if err != nil {
return
}
resp.Body.Close()
}