78 lines
1.8 KiB
Go
78 lines
1.8 KiB
Go
|
package routes
|
||
|
|
||
|
import (
|
||
|
"time"
|
||
|
|
||
|
"github.com/gofiber/fiber/v2"
|
||
|
"github.com/ngn13/website/api/database"
|
||
|
"github.com/ngn13/website/api/util"
|
||
|
)
|
||
|
|
||
|
type visitor_cache_entry struct {
|
||
|
Addr string // SHA1 hash of visitor's IP
|
||
|
Number uint64 // number of the visitor
|
||
|
}
|
||
|
|
||
|
const VISITOR_CACHE_MAX = 30 // store 30 visitor data at most
|
||
|
var visitor_cache []visitor_cache_entry // in memory cache for the visitor
|
||
|
|
||
|
func GET_Metrics(c *fiber.Ctx) error {
|
||
|
var (
|
||
|
err error
|
||
|
result map[string]uint64 = map[string]uint64{
|
||
|
"number": 0, // visitor number of the current visitor
|
||
|
"total": 0, // total number of visitors
|
||
|
"since": 0, // metric collection start date (UNIX timestamp)
|
||
|
}
|
||
|
)
|
||
|
|
||
|
db := c.Locals("database").(*database.Type)
|
||
|
new_addr := util.GetSHA1(util.IP(c))
|
||
|
|
||
|
for i := range visitor_cache {
|
||
|
if new_addr == visitor_cache[i].Addr {
|
||
|
result["number"] = visitor_cache[i].Number
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if result["total"], err = db.MetricsGet("visitor_count"); err != nil {
|
||
|
return util.ErrInternal(c, err)
|
||
|
}
|
||
|
|
||
|
if result["number"] == 0 {
|
||
|
result["total"]++
|
||
|
result["number"] = result["total"]
|
||
|
|
||
|
if len(visitor_cache) > VISITOR_CACHE_MAX {
|
||
|
util.Debg("visitor cache is full, removing the oldest entry")
|
||
|
visitor_cache = visitor_cache[1:]
|
||
|
}
|
||
|
|
||
|
visitor_cache = append(visitor_cache, visitor_cache_entry{
|
||
|
Addr: new_addr,
|
||
|
Number: result["number"],
|
||
|
})
|
||
|
|
||
|
if err = db.MetricsSet("visitor_count", result["total"]); err != nil {
|
||
|
return util.ErrInternal(c, err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if result["since"], err = db.MetricsGet("start_date"); err != nil {
|
||
|
return util.ErrInternal(c, err)
|
||
|
}
|
||
|
|
||
|
if result["since"] == 0 {
|
||
|
result["since"] = uint64(time.Now().Truncate(24 * time.Hour).Unix())
|
||
|
|
||
|
if err = db.MetricsSet("since", result["since"]); err != nil {
|
||
|
return util.ErrInternal(c, err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return util.JSON(c, 200, fiber.Map{
|
||
|
"result": result,
|
||
|
})
|
||
|
}
|