diff --git a/analyticsApi/main.go b/analyticsApi/main.go index ea960a5..c42f357 100644 --- a/analyticsApi/main.go +++ b/analyticsApi/main.go @@ -308,6 +308,90 @@ func initAggregateCount(app *pocketbase.PocketBase, e *core.ServeEvent) { }, apis.ActivityLogger(app)) } +// initDailyAnalyticsAggregates +// +// This endpoint aggregates daily analytics data for a specified date range from `startDate` to `now`. +// It adds the following endpoint to the app: +// GET /api/analytics/dailyAggregates +// +// The endpoint expects the following query parameter: +// +// ?startDate=ISO 8601 formatted date (optional) +// +// - `startDate`: An optional start date in ISO 8601 format (e.g., "2024-11-12T15:04:05Z"). +// If provided, aggregates are calculated from this date onward up to the current date. +// If not provided, all data until today is included. +// +// Response format: +// +// [ +// { +// "date": "", +// "error_count": , +// "page_view_count": , +// "unique_visitor_count": +// }, +// ... +// ] +func initDailyAnalyticsAggregates(app *pocketbase.PocketBase, e *core.ServeEvent) { + e.Router.GET("/api/analytics/dailyAggregates", func(c echo.Context) error { + + // Check if user is in admin group + if err := ldapApi.UserIsInAdminGroup(app, c); err != nil { + return err + } + + // Parse the start date + startDateParam := c.QueryParam("startDate") + var startDate time.Time + var err error + if startDateParam != "" { + startDate, err = time.Parse(time.RFC3339, startDateParam) + if err != nil { + return apis.NewBadRequestError("Invalid start date format, expected ISO 8601", err) + } + } else { + // Default to the beginning of time if not provided + startDate = time.Time{} + } + + // Define the structure for the daily aggregate data + type DailyAggregate struct { + Date string `db:"date" json:"date"` + ErrorCount int `db:"error_count" json:"error_count"` + PageViewCount int `db:"page_view_count" json:"page_view_count"` + UniqueVisitorCount int `db:"unique_visitor_count" json:"unique_visitor_count"` + } + + var results []DailyAggregate + + // Query to aggregate daily data within the specified date range + err = app.Dao().DB(). + NewQuery(` + SELECT + created AS date, + COUNT(id) AS page_view_count, + SUM(CASE WHEN error IS NOT NULL THEN 1 ELSE 0 END) AS error_count, + COUNT(DISTINCT visitor) AS unique_visitor_count + FROM analyticsPageViewsWithSessionDetail + WHERE created >= {:startDate} + GROUP BY date + ORDER BY date ASC + `). + Bind(dbx.Params{ + "startDate": startDate, + }). + All(&results) + + if err != nil { + return apis.NewApiError(500, "Failed to query daily analytics aggregates", err) + } + + // Return the final JSON response + return c.JSON(200, results) + }, apis.ActivityLogger(app)) +} + // InitAnalyticsApi initializes analytics api endpoints func InitAnalyticsApi(app *pocketbase.PocketBase, e *core.ServeEvent) error { @@ -315,6 +399,7 @@ func InitAnalyticsApi(app *pocketbase.PocketBase, e *core.ServeEvent) error { initPageViewCount(app, e) initAggregateCount(app, e) + initDailyAnalyticsAggregates(app, e) return nil }