move remaining queries to datastore pkg & bubble up errors to http handlers

This commit is contained in:
Danny van Kooten 2018-04-27 17:28:03 +02:00
parent b0d16b648b
commit a20e2b1227
16 changed files with 159 additions and 157 deletions

View File

@ -8,6 +8,9 @@ import (
// URL: /api/browsers // URL: /api/browsers
var GetBrowsersHandler = HandlerFunc(func(w http.ResponseWriter, r *http.Request) error { var GetBrowsersHandler = HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
before, after := getRequestedPeriods(r) before, after := getRequestedPeriods(r)
results := count.Browsers(before, after, getRequestedLimit(r)) results, err := count.Browsers(before, after, getRequestedLimit(r))
if err != nil {
return err
}
return respond(w, envelope{Data: results}) return respond(w, envelope{Data: results})
}) })

View File

@ -9,6 +9,10 @@ import (
// URL: /api/languages // URL: /api/languages
var GetLanguagesHandler = HandlerFunc(func(w http.ResponseWriter, r *http.Request) error { var GetLanguagesHandler = HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
before, after := getRequestedPeriods(r) before, after := getRequestedPeriods(r)
results := count.Languages(before, after, getRequestedLimit(r)) results, err := count.Languages(before, after, getRequestedLimit(r))
if err != nil {
return err
}
return respond(w, envelope{Data: results}) return respond(w, envelope{Data: results})
}) })

View File

@ -10,8 +10,8 @@ import (
const defaultPeriod = 7 const defaultPeriod = 7
const defaultLimit = 10 const defaultLimit = 10
func getRequestedLimit(r *http.Request) int { func getRequestedLimit(r *http.Request) int64 {
limit, err := strconv.Atoi(r.URL.Query().Get("limit")) limit, err := strconv.ParseInt(r.URL.Query().Get("limit"), 10, 64)
if err != nil || limit == 0 { if err != nil || limit == 0 {
limit = 10 limit = 10
} }

View File

@ -9,6 +9,9 @@ import (
// URL: /api/referrers // URL: /api/referrers
var GetReferrersHandler = HandlerFunc(func(w http.ResponseWriter, r *http.Request) error { var GetReferrersHandler = HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
before, after := getRequestedPeriods(r) before, after := getRequestedPeriods(r)
results := count.Referrers(before, after, getRequestedLimit(r)) results, err := count.Referrers(before, after, getRequestedLimit(r))
if err != nil {
return err
}
return respond(w, envelope{Data: results}) return respond(w, envelope{Data: results})
}) })

View File

@ -9,6 +9,9 @@ import (
// URL: /api/screen-resolutions // URL: /api/screen-resolutions
var GetScreenResolutionsHandler = HandlerFunc(func(w http.ResponseWriter, r *http.Request) error { var GetScreenResolutionsHandler = HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
before, after := getRequestedPeriods(r) before, after := getRequestedPeriods(r)
results := count.Screens(before, after, getRequestedLimit(r)) results, err := count.Screens(before, after, getRequestedLimit(r))
if err != nil {
return err
}
return respond(w, envelope{Data: results}) return respond(w, envelope{Data: results})
}) })

View File

@ -5,32 +5,23 @@ import (
"time" "time"
"github.com/usefathom/fathom/pkg/datastore" "github.com/usefathom/fathom/pkg/datastore"
"github.com/usefathom/fathom/pkg/models"
) )
// Browsers returns a point slice containing browser data per browser name // Browsers returns a point slice containing browser data per browser name
func Browsers(before int64, after int64, limit int) []Point { func Browsers(before int64, after int64, limit int64) ([]*models.Point, error) {
stmt, err := datastore.DB.Prepare(` points, err := datastore.TotalsPerBrowser(before, after, limit)
SELECT if err != nil {
t.value, return nil, err
SUM(t.count_unique) AS count }
FROM total_browser_names t
WHERE UNIX_TIMESTAMP(t.date) <= ? AND UNIX_TIMESTAMP(t.date) >= ?
GROUP BY t.value
ORDER BY count DESC
LIMIT ?`)
checkError(err)
defer stmt.Close()
rows, err := stmt.Query(before, after, limit)
checkError(err)
points := newPointSlice(rows)
total, err := datastore.TotalUniqueBrowsers(before, after) total, err := datastore.TotalUniqueBrowsers(before, after)
checkError(err) if err != nil {
return nil, err
}
points = calculatePointPercentages(points, total) points = calculatePointPercentages(points, total)
return points, nil
return points
} }
// CreateBrowserTotals aggregates screen data into daily totals // CreateBrowserTotals aggregates screen data into daily totals

View File

@ -1,21 +1,14 @@
package count package count
import ( import (
"database/sql"
"time" "time"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/usefathom/fathom/pkg/datastore" "github.com/usefathom/fathom/pkg/datastore"
"github.com/usefathom/fathom/pkg/models"
) )
// Point represents a data point, will always have a Label and Value
type Point struct {
Label string
Value int
PercentageValue float64
}
func getLastArchivedDate() string { func getLastArchivedDate() string {
value, _ := datastore.GetOption("last_archived") value, _ := datastore.GetOption("last_archived")
if value == "" { if value == "" {
@ -42,30 +35,10 @@ func Archive() {
log.Infof("finished aggregating metrics. ran for %dms.", (end.UnixNano()-start.UnixNano())/1000000) log.Infof("finished aggregating metrics. ran for %dms.", (end.UnixNano()-start.UnixNano())/1000000)
} }
func checkError(err error) { func calculatePointPercentages(points []*models.Point, total int) []*models.Point {
if err != nil {
log.Fatal(err)
}
}
func newPointSlice(rows *sql.Rows) []Point {
results := make([]Point, 0)
// append point slices
for rows.Next() {
var d Point
err := rows.Scan(&d.Label, &d.Value)
checkError(err)
results = append(results, d)
}
return results
}
func calculatePointPercentages(points []Point, total int) []Point {
// calculate percentage values for each point // calculate percentage values for each point
for i, d := range points { for _, p := range points {
points[i].PercentageValue = float64(d.Value) / float64(total) * 100 p.PercentageValue = float64(p.Value) / float64(total) * 100.00
} }
return points return points

View File

@ -3,32 +3,13 @@ package count
import ( import (
"testing" "testing"
"time" "time"
"github.com/usefathom/fathom/pkg/models"
) )
func TestFill(t *testing.T) {
start := time.Date(2016, time.January, 1, 0, 0, 0, 0, time.Local)
end := time.Date(2016, time.January, 5, 0, 0, 0, 0, time.Local)
points := []Point{
Point{
Label: start.Format("2006-01-02"),
Value: 1,
},
Point{
Label: end.Format("2006-01-02"),
Value: 1,
},
}
filled := fill(start.Unix(), end.Unix(), points)
if len(filled) != 5 {
t.Error("Length of filled points slice does not match expected length")
}
}
func TestCalculatePointPercentages(t *testing.T) { func TestCalculatePointPercentages(t *testing.T) {
points := []Point{ points := []*models.Point{
Point{ &models.Point{
Label: "Foo", Label: "Foo",
Value: 5, Value: 5,
}, },

View File

@ -5,32 +5,23 @@ import (
"time" "time"
"github.com/usefathom/fathom/pkg/datastore" "github.com/usefathom/fathom/pkg/datastore"
"github.com/usefathom/fathom/pkg/models"
) )
// Languages returns a point slice containing language data per language // Languages returns a point slice containing language data per language
func Languages(before int64, after int64, limit int) []Point { func Languages(before int64, after int64, limit int64) ([]*models.Point, error) {
stmt, err := datastore.DB.Prepare(` points, err := datastore.TotalsPerLanguage(before, after, limit)
SELECT if err != nil {
t.value, return nil, err
SUM(t.count_unique) AS count }
FROM total_browser_languages t
WHERE UNIX_TIMESTAMP(t.date) <= ? AND UNIX_TIMESTAMP(t.date) >= ?
GROUP BY t.value
ORDER BY count DESC
LIMIT ?`)
checkError(err)
defer stmt.Close()
rows, err := stmt.Query(before, after, limit)
checkError(err)
points := newPointSlice(rows)
total, err := datastore.TotalUniqueLanguages(before, after) total, err := datastore.TotalUniqueLanguages(before, after)
checkError(err) if err != nil {
return nil, err
}
points = calculatePointPercentages(points, total) points = calculatePointPercentages(points, total)
return points, nil
return points
} }
// CreateLanguageTotals aggregates screen data into daily totals // CreateLanguageTotals aggregates screen data into daily totals

View File

@ -5,32 +5,23 @@ import (
"time" "time"
"github.com/usefathom/fathom/pkg/datastore" "github.com/usefathom/fathom/pkg/datastore"
"github.com/usefathom/fathom/pkg/models"
) )
// Referrers returns a point slice containing browser data per browser name // Referrers returns a point slice containing browser data per browser name
func Referrers(before int64, after int64, limit int) []Point { func Referrers(before int64, after int64, limit int64) ([]*models.Point, error) {
stmt, err := datastore.DB.Prepare(` points, err := datastore.TotalsPerReferrer(before, after, limit)
SELECT if err != nil {
t.value, return nil, err
SUM(t.count) AS count }
FROM total_referrers t
WHERE UNIX_TIMESTAMP(t.date) <= ? AND UNIX_TIMESTAMP(t.date) >= ?
GROUP BY t.value
ORDER BY count DESC
LIMIT ?`)
checkError(err)
defer stmt.Close()
rows, err := stmt.Query(before, after, limit)
checkError(err)
points := newPointSlice(rows)
total, err := datastore.TotalReferrers(before, after) total, err := datastore.TotalReferrers(before, after)
checkError(err) if err != nil {
return nil, err
}
points = calculatePointPercentages(points, total) points = calculatePointPercentages(points, total)
return points, nil
return points
} }
// CreateReferrerTotals aggregates screen data into daily totals // CreateReferrerTotals aggregates screen data into daily totals

View File

@ -5,32 +5,23 @@ import (
"time" "time"
"github.com/usefathom/fathom/pkg/datastore" "github.com/usefathom/fathom/pkg/datastore"
"github.com/usefathom/fathom/pkg/models"
) )
// Screens returns a point slice containing screen data per size // Screens returns a point slice containing screen data per size
func Screens(before int64, after int64, limit int) []Point { func Screens(before int64, after int64, limit int64) ([]*models.Point, error) {
stmt, err := datastore.DB.Prepare(` points, err := datastore.TotalsPerScreen(before, after, limit)
SELECT if err != nil {
t.value, return nil, err
SUM(t.count_unique) AS count }
FROM total_screens t
WHERE UNIX_TIMESTAMP(t.date) <= ? AND UNIX_TIMESTAMP(t.date) >= ?
GROUP BY t.value
ORDER BY count DESC
LIMIT ?`)
checkError(err)
defer stmt.Close()
rows, err := stmt.Query(before, after, limit)
checkError(err)
points := newPointSlice(rows)
total, err := datastore.TotalUniqueScreens(before, after) total, err := datastore.TotalUniqueScreens(before, after)
checkError(err) if err != nil {
return nil, err
}
points = calculatePointPercentages(points, total) points = calculatePointPercentages(points, total)
return points, nil
return points
} }
// CreateScreenTotals aggregates screen data into daily totals // CreateScreenTotals aggregates screen data into daily totals

View File

@ -1,5 +1,7 @@
package datastore package datastore
import "github.com/usefathom/fathom/pkg/models"
// TotalUniqueBrowsers returns the total # of unique browsers between two given timestamps // TotalUniqueBrowsers returns the total # of unique browsers between two given timestamps
func TotalUniqueBrowsers(before int64, after int64) (int, error) { func TotalUniqueBrowsers(before int64, after int64) (int, error) {
var total int var total int
@ -12,3 +14,20 @@ func TotalUniqueBrowsers(before int64, after int64) (int, error) {
err := dbx.Get(&total, query, before, after) err := dbx.Get(&total, query, before, after)
return total, err return total, err
} }
func TotalsPerBrowser(before int64, after int64, limit int64) ([]*models.Point, error) {
var results []*models.Point
query := dbx.Rebind(`
SELECT
t.value AS label,
SUM(t.count_unique) AS value
FROM total_browser_names t
WHERE UNIX_TIMESTAMP(t.date) <= ? AND UNIX_TIMESTAMP(t.date) >= ?
GROUP BY label
ORDER BY value DESC
LIMIT ?`)
err := dbx.Select(&results, query, before, after, limit)
return results, err
}

View File

@ -1,5 +1,7 @@
package datastore package datastore
import "github.com/usefathom/fathom/pkg/models"
// TotalUniqueLanguages returns the total # of unique browser languages between two given timestamps // TotalUniqueLanguages returns the total # of unique browser languages between two given timestamps
func TotalUniqueLanguages(before int64, after int64) (int, error) { func TotalUniqueLanguages(before int64, after int64) (int, error) {
var total int var total int
@ -13,3 +15,20 @@ func TotalUniqueLanguages(before int64, after int64) (int, error) {
err := dbx.Get(&total, query, before, after) err := dbx.Get(&total, query, before, after)
return total, err return total, err
} }
func TotalsPerLanguage(before int64, after int64, limit int64) ([]*models.Point, error) {
var results []*models.Point
query := dbx.Rebind(`
SELECT
t.value AS label,
SUM(t.count_unique) AS value
FROM total_browser_languages t
WHERE UNIX_TIMESTAMP(t.date) <= ? AND UNIX_TIMESTAMP(t.date) >= ?
GROUP BY label
ORDER BY value DESC
LIMIT ?`)
err := dbx.Select(&results, query, before, after, limit)
return results, err
}

View File

@ -8,7 +8,9 @@ import (
func TotalPageviews(before int64, after int64) (int, error) { func TotalPageviews(before int64, after int64) (int, error) {
var total int var total int
query := dbx.Rebind(`SELECT IFNULL( SUM(t.count), 0 ) FROM total_pageviews t WHERE UNIX_TIMESTAMP(t.date) <= ? AND UNIX_TIMESTAMP(t.date) >= ?`) query := dbx.Rebind(`
SELECT IFNULL( SUM(t.count), 0 )
FROM total_pageviews t WHERE UNIX_TIMESTAMP(t.date) <= ? AND UNIX_TIMESTAMP(t.date) >= ?`)
err := dbx.Get(&total, query, before, after) err := dbx.Get(&total, query, before, after)
if err != nil { if err != nil {
return 0, err return 0, err
@ -73,14 +75,7 @@ func SavePageviewTotals(totals []*models.Total) error {
} }
for _, t := range totals { for _, t := range totals {
_, err = stmt.Exec( _, err = stmt.Exec(t.PageID, t.Count, t.CountUnique, t.Date, t.Count, t.CountUnique)
t.PageID,
t.Count,
t.CountUnique,
t.Date,
t.Count,
t.CountUnique,
)
} }
err = tx.Commit() err = tx.Commit()

View File

@ -1,5 +1,7 @@
package datastore package datastore
import "github.com/usefathom/fathom/pkg/models"
// TotalReferrers returns the total # of referrers between two given timestamps // TotalReferrers returns the total # of referrers between two given timestamps
func TotalReferrers(before int64, after int64) (int, error) { func TotalReferrers(before int64, after int64) (int, error) {
var total int var total int
@ -13,3 +15,20 @@ func TotalReferrers(before int64, after int64) (int, error) {
err := dbx.Get(&total, query, before, after) err := dbx.Get(&total, query, before, after)
return total, err return total, err
} }
func TotalsPerReferrer(before int64, after int64, limit int64) ([]*models.Point, error) {
var results []*models.Point
query := dbx.Rebind(`
SELECT
t.value AS label,
SUM(t.count) AS value
FROM total_referrers t
WHERE UNIX_TIMESTAMP(t.date) <= ? AND UNIX_TIMESTAMP(t.date) >= ?
GROUP BY label
ORDER BY value DESC
LIMIT ?`)
err := dbx.Select(&results, query, before, after, limit)
return results, err
}

View File

@ -1,5 +1,7 @@
package datastore package datastore
import "github.com/usefathom/fathom/pkg/models"
// TotalUniqueScreens returns the total # of screens between two given timestamps // TotalUniqueScreens returns the total # of screens between two given timestamps
func TotalUniqueScreens(before int64, after int64) (int, error) { func TotalUniqueScreens(before int64, after int64) (int, error) {
var total int var total int
@ -12,3 +14,20 @@ func TotalUniqueScreens(before int64, after int64) (int, error) {
err := dbx.Get(&total, query, before, after) err := dbx.Get(&total, query, before, after)
return total, err return total, err
} }
func TotalsPerScreen(before int64, after int64, limit int64) ([]*models.Point, error) {
var results []*models.Point
query := dbx.Rebind(`
SELECT
t.value AS label,
SUM(t.count_unique) AS value
FROM total_screens t
WHERE UNIX_TIMESTAMP(t.date) <= ? AND UNIX_TIMESTAMP(t.date) >= ?
GROUP BY t.value
ORDER BY value DESC
LIMIT ?`)
err := dbx.Select(&results, query, before, after, limit)
return results, err
}