Skip to content

Commit

Permalink
Remove "pageview" counts
Browse files Browse the repository at this point in the history
From now on only "visitor" counts are displayed; the "pageview" counts have
slowly been reduced in significance, and are currently only shown on the
mouseover on the visit count and chart (greyed out).

When is it ever really useful? All it tells you is that someone pressed F5. I
don't really see how this is ever useful.

Removing this allows us to simplify the UI, API, database schema, queries, the
tests, and some logic. i.e. basically everything. It should also make things
slightly faster.
  • Loading branch information
arp242 committed Nov 3, 2022
1 parent 40912a4 commit 26392d1
Show file tree
Hide file tree
Showing 66 changed files with 482 additions and 690 deletions.
10 changes: 3 additions & 7 deletions cron/browser_stat.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
func updateBrowserStats(ctx context.Context, hits []goatcounter.Hit) error {
return errors.Wrap(zdb.TX(ctx, func(ctx context.Context) error {
type gt struct {
count int
countUnique int
day string
browserID int64
Expand All @@ -40,13 +39,12 @@ func updateBrowserStats(ctx context.Context, hits []goatcounter.Hit) error {
day := h.CreatedAt.Format("2006-01-02")
k := day + strconv.FormatInt(h.BrowserID, 10) + strconv.FormatInt(h.PathID, 10)
v := grouped[k]
if v.count == 0 {
if v.countUnique == 0 {
v.day = day
v.browserID = h.BrowserID
v.pathID = h.PathID
}

v.count += 1
if h.FirstVisit {
v.countUnique += 1
}
Expand All @@ -55,19 +53,17 @@ func updateBrowserStats(ctx context.Context, hits []goatcounter.Hit) error {

siteID := goatcounter.MustGetSite(ctx).ID
ins := zdb.NewBulkInsert(ctx, "browser_stats", []string{"site_id", "day",
"path_id", "browser_id", "count", "count_unique"})
"path_id", "browser_id", "count_unique"})
if zdb.SQLDialect(ctx) == zdb.DialectPostgreSQL {
ins.OnConflict(`on conflict on constraint "browser_stats#site_id#path_id#day#browser_id" do update set
count = browser_stats.count + excluded.count,
count_unique = browser_stats.count_unique + excluded.count_unique`)
} else {
ins.OnConflict(`on conflict(site_id, path_id, day, browser_id) do update set
count = browser_stats.count + excluded.count,
count_unique = browser_stats.count_unique + excluded.count_unique`)
}

for _, v := range grouped {
ins.Values(siteID, v.day, v.pathID, v.browserID, v.count, v.countUnique)
ins.Values(siteID, v.day, v.pathID, v.browserID, v.countUnique)
}
return ins.Finish()
}), "cron.updateBrowserStats")
Expand Down
6 changes: 3 additions & 3 deletions cron/browser_stat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func TestBrowserStats(t *testing.T) {
t.Fatal(err)
}

want := `{false [{ Firefox 3 1 <nil>} { Chrome 1 0 <nil>}]}`
want := `{false [{ Firefox 1 <nil>} { Chrome 0 <nil>}]}`
out := fmt.Sprintf("%v", stats)
if want != out {
t.Errorf("\nwant: %s\nout: %s", want, out)
Expand All @@ -53,7 +53,7 @@ func TestBrowserStats(t *testing.T) {
t.Fatal(err)
}

want = `{false [{ Firefox 7 2 <nil>} { Chrome 1 0 <nil>}]}`
want = `{false [{ Firefox 2 <nil>} { Chrome 0 <nil>}]}`
out = fmt.Sprintf("%v", stats)
if want != out {
t.Errorf("\nwant: %s\nout: %s", want, out)
Expand All @@ -66,7 +66,7 @@ func TestBrowserStats(t *testing.T) {
t.Fatal(err)
}

want = `{false [{ Firefox 68 1 1 <nil>} { Firefox 69 4 1 <nil>} { Firefox 70 2 0 <nil>}]}`
want = `{false [{ Firefox 68 1 <nil>} { Firefox 69 1 <nil>} { Firefox 70 0 <nil>}]}`
out = fmt.Sprintf("%v", stats)
if want != out {
t.Errorf("\nwant: %s\nout: %s", want, out)
Expand Down
10 changes: 3 additions & 7 deletions cron/campaign_stat.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
func updateCampaignStats(ctx context.Context, hits []goatcounter.Hit) error {
return errors.Wrap(zdb.TX(ctx, func(ctx context.Context) error {
type gt struct {
count int
countUnique int
day string
campaignID int64
Expand All @@ -32,14 +31,13 @@ func updateCampaignStats(ctx context.Context, hits []goatcounter.Hit) error {
day := h.CreatedAt.Format("2006-01-02")
k := day + strconv.FormatInt(*h.CampaignID, 10) + h.Ref + strconv.FormatInt(h.PathID, 10)
v := grouped[k]
if v.count == 0 {
if v.countUnique == 0 {
v.day = day
v.campaignID = *h.CampaignID
v.ref = h.Ref
v.pathID = h.PathID
}

v.count += 1
if h.FirstVisit {
v.countUnique += 1
}
Expand All @@ -48,19 +46,17 @@ func updateCampaignStats(ctx context.Context, hits []goatcounter.Hit) error {

siteID := goatcounter.MustGetSite(ctx).ID
ins := zdb.NewBulkInsert(ctx, "campaign_stats", []string{"site_id", "day",
"path_id", "campaign_id", "ref", "count", "count_unique"})
"path_id", "campaign_id", "ref", "count_unique"})
if zdb.SQLDialect(ctx) == zdb.DialectPostgreSQL {
ins.OnConflict(`on conflict on constraint "campaign_stats#site_id#path_id#campaign_id#ref#day" do update set
count = campaign_stats.count + excluded.count,
count_unique = campaign_stats.count_unique + excluded.count_unique`)
} else {
ins.OnConflict(`on conflict(site_id, path_id, campaign_id, ref, day) do update set
count = campaign_stats.count + excluded.count,
count_unique = campaign_stats.count_unique + excluded.count_unique`)
}

for _, v := range grouped {
ins.Values(siteID, v.day, v.pathID, v.campaignID, v.ref, v.count, v.countUnique)
ins.Values(siteID, v.day, v.pathID, v.campaignID, v.ref, v.countUnique)
}
return ins.Finish()
}), "cron.updateCampaignStats")
Expand Down
2 changes: 1 addition & 1 deletion cron/email_reports.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func reportText(ctx context.Context, site goatcounter.Site, user goatcounter.Use
subject = fmt.Sprintf("Your GoatCounter report for %s", args.DisplayDate)

{ // Get overview of paths.
_, _, _, err := args.Pages.List(ctx, rng, nil, nil, 10, true)
_, _, err := args.Pages.List(ctx, rng, nil, nil, 10, true)
if err != nil {
return nil, nil, "", err
}
Expand Down
10 changes: 3 additions & 7 deletions cron/hit_count.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ func updateHitCounts(ctx context.Context, hits []goatcounter.Hit) error {
return errors.Wrap(zdb.TX(ctx, func(ctx context.Context) error {
// Group by day + pathID
type gt struct {
total int
totalUnique int
hour string
pathID int64
Expand All @@ -31,12 +30,11 @@ func updateHitCounts(ctx context.Context, hits []goatcounter.Hit) error {
hour := h.CreatedAt.Format("2006-01-02 15:00:00")
k := hour + strconv.FormatInt(h.PathID, 10)
v := grouped[k]
if v.total == 0 {
if v.totalUnique == 0 {
v.hour = hour
v.pathID = h.PathID
}

v.total += 1
if h.FirstVisit {
v.totalUnique += 1
}
Expand All @@ -45,19 +43,17 @@ func updateHitCounts(ctx context.Context, hits []goatcounter.Hit) error {

siteID := goatcounter.MustGetSite(ctx).ID
ins := zdb.NewBulkInsert(ctx, "hit_counts", []string{"site_id", "path_id",
"hour", "total", "total_unique"})
"hour", "total_unique"})
if zdb.SQLDialect(ctx) == zdb.DialectPostgreSQL {
ins.OnConflict(`on conflict on constraint "hit_counts#site_id#path_id#hour" do update set
total = hit_counts.total + excluded.total,
total_unique = hit_counts.total_unique + excluded.total_unique`)
} else {
ins.OnConflict(`on conflict(site_id, path_id, hour) do update set
total = hit_counts.total + excluded.total,
total_unique = hit_counts.total_unique + excluded.total_unique`)
}

for _, v := range grouped {
ins.Values(siteID, v.pathID, v.hour, v.total, v.totalUnique)
ins.Values(siteID, v.pathID, v.hour, v.totalUnique)
}
return ins.Finish()
}), "cron.updateHitCounts")
Expand Down
41 changes: 12 additions & 29 deletions cron/hit_stat.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
func updateHitStats(ctx context.Context, hits []goatcounter.Hit) error {
return errors.Wrap(zdb.TX(ctx, func(ctx context.Context) error {
type gt struct {
count []int
countUnique []int
day string
hour string
Expand All @@ -33,43 +32,32 @@ func updateHitStats(ctx context.Context, hits []goatcounter.Hit) error {
dayHour := h.CreatedAt.Format("2006-01-02 15:00:00")
k := day + strconv.FormatInt(h.PathID, 10)
v := grouped[k]
if len(v.count) == 0 {
if len(v.countUnique) == 0 {
v.day = day
v.hour = dayHour
v.pathID = h.PathID
v.count = make([]int, 24)
v.countUnique = make([]int, 24)

if zdb.SQLDialect(ctx) == zdb.DialectSQLite {
var err error
v.count, v.countUnique, err = existingHitStats(ctx, h.Site, day, v.pathID)
v.countUnique, err = existingHitStats(ctx, h.Site, day, v.pathID)
if err != nil {
return err
}
}
}

hour, _ := strconv.ParseInt(h.CreatedAt.Format("15"), 10, 8)
v.count[hour] += 1
if h.FirstVisit {
v.countUnique[hour] += 1
}
grouped[k] = v
}

siteID := goatcounter.MustGetSite(ctx).ID
ins := zdb.NewBulkInsert(ctx, "hit_stats", []string{"site_id", "day", "path_id",
"stats", "stats_unique"})
ins := zdb.NewBulkInsert(ctx, "hit_stats", []string{"site_id", "day", "path_id", "stats_unique"})
if zdb.SQLDialect(ctx) == zdb.DialectPostgreSQL {
ins.OnConflict(`on conflict on constraint "hit_stats#site_id#path_id#day" do update set
stats = (
with x as (
select
unnest(string_to_array(trim(hit_stats.stats, '[]'), ',')::int[]) as orig,
unnest(string_to_array(trim(excluded.stats, '[]'), ',')::int[]) as new
)
select '[' || array_to_string(array_agg(orig + new), ',') || ']' from x
),
stats_unique = (
with x as (
select
Expand All @@ -84,49 +72,44 @@ func updateHitStats(ctx context.Context, hits []goatcounter.Hit) error {
// it's kinda tricky with SQLite :-/
//
// ins.OnConflict(`on conflict(site_id, path_id, day) do update set
// stats = excluded.stats,
// stats_unique = excluded.stats_unique
// `)
// }

for _, v := range grouped {
ins.Values(siteID, v.day, v.pathID,
zjson.MustMarshal(v.count),
zjson.MustMarshal(v.countUnique))
ins.Values(siteID, v.day, v.pathID, zjson.MustMarshal(v.countUnique))
}
return errors.Wrap(ins.Finish(), "updateHitStats hit_stats")
}), "cron.updateHitStats")
}

func existingHitStats(ctx context.Context, siteID int64, day string, pathID int64) ([]int, []int, error) {
func existingHitStats(ctx context.Context, siteID int64, day string, pathID int64) ([]int, error) {

var ex []struct {
Stats []byte `db:"stats"`
StatsUnique []byte `db:"stats_unique"`
}
err := zdb.Select(ctx, &ex, `/* existingHitStats */
select stats, stats_unique from hit_stats
select stats_unique from hit_stats
where site_id=$1 and day=$2 and path_id=$3 limit 1`,
siteID, day, pathID)
if err != nil {
return nil, nil, errors.Wrap(err, "existingHitStats")
return nil, errors.Wrap(err, "existingHitStats")
}
if len(ex) == 0 {
return make([]int, 24), make([]int, 24), nil
return make([]int, 24), nil
}

err = zdb.Exec(ctx, `delete from hit_stats where
site_id=$1 and day=$2 and path_id=$3`,
siteID, day, pathID)
if err != nil {
return nil, nil, errors.Wrap(err, "delete")
return nil, errors.Wrap(err, "delete")
}

var r, ru []int
if ex[0].Stats != nil {
zjson.MustUnmarshal(ex[0].Stats, &r)
var ru []int
if ex[0].StatsUnique != nil {
zjson.MustUnmarshal(ex[0].StatsUnique, &ru)
}

return r, ru, nil
return ru, nil
}
Loading

0 comments on commit 26392d1

Please sign in to comment.