data layer
This commit is contained in:
132
data-layer/api/internal/handler/analytics_handler.go
Normal file
132
data-layer/api/internal/handler/analytics_handler.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/dbiz/cdp/data-layer/api/internal/middleware"
|
||||
"github.com/dbiz/cdp/data-layer/api/internal/repo"
|
||||
"github.com/dbiz/cdp/data-layer/api/internal/service"
|
||||
)
|
||||
|
||||
type AnalyticsHandler struct {
|
||||
svc *service.QueryService
|
||||
log *zap.Logger
|
||||
}
|
||||
|
||||
func NewAnalyticsHandler(svc *service.QueryService, log *zap.Logger) *AnalyticsHandler {
|
||||
return &AnalyticsHandler{svc: svc, log: log}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Funnel
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type funnelRequest struct {
|
||||
Steps []string `json:"steps" validate:"required,min=2,max=10,dive,min=1"`
|
||||
From *time.Time `json:"from" validate:"required"`
|
||||
To *time.Time `json:"to" validate:"required,gtfield=From"`
|
||||
WindowSeconds uint32 `json:"window_seconds" validate:"required,min=1,max=2592000"` // up to 30d
|
||||
}
|
||||
|
||||
func (h *AnalyticsHandler) Funnel(w http.ResponseWriter, r *http.Request) {
|
||||
var req funnelRequest
|
||||
if err := decodeAndValidate(r, &req); err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
ws := middleware.WorkspaceFromCtx(r.Context())
|
||||
res, err := h.svc.Funnel(r.Context(), repo.FunnelQuery{
|
||||
WorkspaceID: ws,
|
||||
Steps: req.Steps,
|
||||
From: *req.From,
|
||||
To: *req.To,
|
||||
WindowSeconds: req.WindowSeconds,
|
||||
})
|
||||
if err != nil {
|
||||
h.log.Error("funnel", zap.String("workspace_id", ws), zap.Error(err))
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, res)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Retention
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type retentionRequest struct {
|
||||
InitialEvent string `json:"initial_event" validate:"required,min=1"`
|
||||
ReturnEvent string `json:"return_event" validate:"required,min=1"`
|
||||
From *time.Time `json:"from" validate:"required"`
|
||||
To *time.Time `json:"to" validate:"required,gtfield=From"`
|
||||
Periods int `json:"periods" validate:"omitempty,min=1,max=90"`
|
||||
}
|
||||
|
||||
func (h *AnalyticsHandler) Retention(w http.ResponseWriter, r *http.Request) {
|
||||
var req retentionRequest
|
||||
if err := decodeAndValidate(r, &req); err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
ws := middleware.WorkspaceFromCtx(r.Context())
|
||||
res, err := h.svc.Retention(r.Context(), repo.RetentionQuery{
|
||||
WorkspaceID: ws,
|
||||
InitialEvent: req.InitialEvent,
|
||||
ReturnEvent: req.ReturnEvent,
|
||||
From: *req.From,
|
||||
To: *req.To,
|
||||
Periods: req.Periods,
|
||||
})
|
||||
if err != nil {
|
||||
h.log.Error("retention", zap.String("workspace_id", ws), zap.Error(err))
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, res)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Session
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type sessionRequest struct {
|
||||
From *time.Time `json:"from" validate:"required"`
|
||||
To *time.Time `json:"to" validate:"required,gtfield=From"`
|
||||
TimeoutSeconds uint32 `json:"timeout_seconds" validate:"omitempty,min=60,max=86400"`
|
||||
UserID string `json:"user_id"`
|
||||
Limit int `json:"limit" validate:"omitempty,min=1,max=1000"`
|
||||
Offset int `json:"offset" validate:"omitempty,min=0"`
|
||||
}
|
||||
|
||||
func (h *AnalyticsHandler) Session(w http.ResponseWriter, r *http.Request) {
|
||||
var req sessionRequest
|
||||
if err := decodeAndValidate(r, &req); err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
if req.TimeoutSeconds == 0 {
|
||||
req.TimeoutSeconds = 30 * 60
|
||||
}
|
||||
if req.Limit == 0 {
|
||||
req.Limit = 100
|
||||
}
|
||||
ws := middleware.WorkspaceFromCtx(r.Context())
|
||||
res, err := h.svc.Sessions(r.Context(), repo.SessionQuery{
|
||||
WorkspaceID: ws,
|
||||
UserID: req.UserID,
|
||||
From: *req.From,
|
||||
To: *req.To,
|
||||
TimeoutSeconds: req.TimeoutSeconds,
|
||||
Limit: req.Limit,
|
||||
Offset: req.Offset,
|
||||
})
|
||||
if err != nil {
|
||||
h.log.Error("session", zap.String("workspace_id", ws), zap.Error(err))
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, res)
|
||||
}
|
||||
Reference in New Issue
Block a user