Browse Source

access stats

master
Fusl 1 year ago
parent
commit
0ceeadd614
1 changed files with 74 additions and 1 deletions
  1. +74
    -1
      main.go

+ 74
- 1
main.go View File

@@ -12,6 +12,7 @@ import (
_ "net/http/pprof"
"os"
"os/signal"
"strconv"
"strings"
"sync"
"syscall"
@@ -384,6 +385,77 @@ func (that *GlobalBackfeedManager) GetFeed(slug string) *ProjectBackfeedManager
return projectBackfeedManager
}

type LastAccessStatsKey struct {
Project string
Shard string
SubShard string
}

type LastAccessStatsMap map[LastAccessStatsKey]time.Time

func (that LastAccessStatsMap) MarshalJSON() ([]byte, error) {
mapped := map[string]string{}
for key, value := range that {
mapped[fmt.Sprintf("%s:%s:%s", key.Project, key.Shard, key.SubShard)] = value.Format(time.RFC3339)
}
return json.Marshal(mapped)
}

func LastAccessStatsKeyFromString(s string) (LastAccessStatsKey, error) {
parts := strings.SplitN(s, ":", 3)
if len(parts) != 3 {
return LastAccessStatsKey{}, fmt.Errorf("invalid key: %s", s)
}
return LastAccessStatsKey{
Project: parts[0],
Shard: parts[1],
SubShard: parts[2],
}, nil
}

func (that *GlobalBackfeedManager) HandleLastAccessStats(res http.ResponseWriter, req *http.Request) {
defer req.Body.Close()
merge := map[string]bool{}
if vv, ok := req.URL.Query()["merge"]; ok {
for _, v := range vv {
merge[v] = true
}
}
lastTs, err := that.BackfeedRedis.HGetAll(req.Context(), ":last_ts").Result()
if err != nil {
WriteResponse(res, http.StatusInternalServerError, err)
return
}
lastAccessStats := LastAccessStatsMap{}
for key, value := range lastTs {
// value is in unix timestamp format
ts, err := strconv.ParseInt(value, 10, 64)
if err != nil {
WriteResponse(res, http.StatusInternalServerError, err)
return
}
lastAccessStatsKey, err := LastAccessStatsKeyFromString(key)
if err != nil {
WriteResponse(res, http.StatusInternalServerError, err)
return
}
if merge["project"] {
lastAccessStatsKey.Project = "*"
}
if merge["shard"] {
lastAccessStatsKey.Shard = "*"
}
if merge["sub_shard"] {
lastAccessStatsKey.SubShard = "*"
}
parsedTs := time.Unix(ts, 0)
if v, has := lastAccessStats[lastAccessStatsKey]; !has || v.Before(parsedTs) {
lastAccessStats[lastAccessStatsKey] = parsedTs
}
}
WriteResponse(res, http.StatusOK, lastAccessStats)
}

func (that *GlobalBackfeedManager) HandleLegacy(res http.ResponseWriter, req *http.Request) {
defer req.Body.Close()

@@ -422,7 +494,7 @@ func (that *GlobalBackfeedManager) HandleLegacy(res http.ResponseWriter, req *ht
Item: bcopy,
}
if err := projectBackfeedManager.PushItem(req.Context(), item); err != nil {
WriteResponse(res, http.StatusServiceUnavailable, err)
WriteResponse(res, http.StatusInternalServerError, err)
return
}
n++
@@ -520,6 +592,7 @@ func main() {
r.Methods(http.MethodPost).Path("/legacy/{slug}").HandlerFunc(globalBackfeedManager.HandleLegacy)
r.Methods(http.MethodGet).Path("/ping").HandlerFunc(globalBackfeedManager.HandlePing)
r.Methods(http.MethodGet).Path("/health").HandlerFunc(globalBackfeedManager.HandleHealth)
r.Methods(http.MethodGet).Path("/lastaccessstats").HandlerFunc(globalBackfeedManager.HandleLastAccessStats)
rMetrics := mux.NewRouter()
rMetrics.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux)
rMetrics.Path("/metrics").Handler(promhttp.Handler())


Loading…
Cancel
Save