123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- package analytic
- import (
- "encoding/csv"
- "encoding/json"
- "log"
- "net/http"
- "strconv"
- "strings"
- "time"
- "imuslab.com/zoraxy/mod/statistic"
- "imuslab.com/zoraxy/mod/utils"
- )
- func (d *DataLoader) HandleSummaryList(w http.ResponseWriter, r *http.Request) {
- entries, err := d.Database.ListTable("stats")
- if err != nil {
- utils.SendErrorResponse(w, "unable to load data from database")
- return
- }
- entryDates := []string{}
- for _, keypairs := range entries {
- entryDates = append(entryDates, string(keypairs[0]))
- }
- js, _ := json.MarshalIndent(entryDates, "", " ")
- utils.SendJSONResponse(w, string(js))
- }
- func (d *DataLoader) HandleLoadTargetDaySummary(w http.ResponseWriter, r *http.Request) {
- day, err := utils.GetPara(r, "id")
- if err != nil {
- utils.SendErrorResponse(w, "id cannot be empty")
- return
- }
- if strings.Contains(day, "-") {
- //Must be underscore
- day = strings.ReplaceAll(day, "-", "_")
- }
- if !statistic.IsBeforeToday(day) {
- utils.SendErrorResponse(w, "given date is in the future")
- return
- }
- var targetDailySummary statistic.DailySummaryExport
- if day == time.Now().Format("2006_01_02") {
- targetDailySummary = *d.StatisticCollector.GetExportSummary()
- } else {
- //Not today data
- err = d.Database.Read("stats", day, &targetDailySummary)
- if err != nil {
- utils.SendErrorResponse(w, "target day data not found")
- return
- }
- }
- js, _ := json.Marshal(targetDailySummary)
- utils.SendJSONResponse(w, string(js))
- }
- func (d *DataLoader) HandleLoadTargetRangeSummary(w http.ResponseWriter, r *http.Request) {
- start, end, err := d.GetStartAndEndDatesFromRequest(r)
- if err != nil {
- utils.SendErrorResponse(w, err.Error())
- return
- }
- dailySummaries, _, err := d.GetAllStatisticSummaryInRange(start, end)
- if err != nil {
- utils.SendErrorResponse(w, err.Error())
- return
- }
- //Merge the summaries into one
- mergedSummary := mergeDailySummaryExports(dailySummaries)
- js, _ := json.Marshal(struct {
- Summary *statistic.DailySummaryExport
- Records []*statistic.DailySummaryExport
- }{
- Summary: mergedSummary,
- Records: dailySummaries,
- })
- utils.SendJSONResponse(w, string(js))
- }
- // Handle exporting of a given range statistics
- func (d *DataLoader) HandleRangeExport(w http.ResponseWriter, r *http.Request) {
- start, end, err := d.GetStartAndEndDatesFromRequest(r)
- if err != nil {
- utils.SendErrorResponse(w, err.Error())
- return
- }
- dailySummaries, dates, err := d.GetAllStatisticSummaryInRange(start, end)
- if err != nil {
- utils.SendErrorResponse(w, err.Error())
- return
- }
- format, err := utils.GetPara(r, "format")
- if err != nil {
- format = "json"
- }
- if format == "csv" {
- // Create a buffer to store CSV content
- var csvContent strings.Builder
- // Create a CSV writer
- writer := csv.NewWriter(&csvContent)
- // Write the header row
- header := []string{"Date", "TotalRequest", "ErrorRequest", "ValidRequest", "ForwardTypes", "RequestOrigin", "RequestClientIp", "Referer", "UserAgent", "RequestURL"}
- err := writer.Write(header)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- // Write each data row
- for i, item := range dailySummaries {
- row := []string{
- dates[i],
- strconv.FormatInt(item.TotalRequest, 10),
- strconv.FormatInt(item.ErrorRequest, 10),
- strconv.FormatInt(item.ValidRequest, 10),
- // Convert map values to a comma-separated string
- strings.Join(mapToStringSlice(item.ForwardTypes), ","),
- strings.Join(mapToStringSlice(item.RequestOrigin), ","),
- strings.Join(mapToStringSlice(item.RequestClientIp), ","),
- strings.Join(mapToStringSlice(item.Referer), ","),
- strings.Join(mapToStringSlice(item.UserAgent), ","),
- strings.Join(mapToStringSlice(item.RequestURL), ","),
- }
- err = writer.Write(row)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- }
- // Flush the CSV writer
- writer.Flush()
- // Check for any errors during writing
- if err := writer.Error(); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- // Set the response headers
- w.Header().Set("Content-Type", "text/csv")
- w.Header().Set("Content-Disposition", "attachment; filename=analytics_"+start+"_to_"+end+".csv")
- // Write the CSV content to the response writer
- _, err = w.Write([]byte(csvContent.String()))
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- } else if format == "json" {
- type exportData struct {
- Stats []*statistic.DailySummaryExport
- Dates []string
- }
- results := exportData{
- Stats: dailySummaries,
- Dates: dates,
- }
- js, _ := json.MarshalIndent(results, "", " ")
- w.Header().Set("Content-Disposition", "attachment; filename=analytics_"+start+"_to_"+end+".json")
- utils.SendJSONResponse(w, string(js))
- } else {
- utils.SendErrorResponse(w, "Unsupported export format")
- }
- }
- // Reset all the keys within the given time period
- func (d *DataLoader) HandleRangeReset(w http.ResponseWriter, r *http.Request) {
- start, end, err := d.GetStartAndEndDatesFromRequest(r)
- if err != nil {
- utils.SendErrorResponse(w, err.Error())
- return
- }
- if r.Method != http.MethodDelete {
- http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
- return
- }
- keys, err := generateDateRange(start, end)
- if err != nil {
- utils.SendErrorResponse(w, err.Error())
- return
- }
- for _, key := range keys {
- log.Println("DELETING statistics " + key)
- d.Database.Delete("stats", key)
- if isTodayDate(key) {
- //It is today's date. Also reset statistic collector value
- log.Println("RESETING today's in-memory statistics")
- d.StatisticCollector.ResetSummaryOfDay()
- }
- }
- utils.SendOK(w)
- }
|