Skip to content

Commit 562f840

Browse files
committed
Add JSON export
The old CSV export works only if you have collection of individual pageviews enabled in the settings, which is disabled by default now. So directly export the data and stats tables, and insert them directly. TODO: kind of works, but needs some work to not be ugly and fragile. Ideally a lot of this can/should be merged with how cron works.
1 parent 9f2bfb8 commit 562f840

File tree

8 files changed

+813
-19
lines changed

8 files changed

+813
-19
lines changed

e.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package goatcounter
2+
3+
import (
4+
"time"
5+
6+
"zgo.at/json"
7+
)
8+
9+
type (
10+
ExportInfo struct {
11+
CreatedAt time.Time `json:"created_at"`
12+
Version int `json:"version"`
13+
Site string `json:"site"`
14+
}
15+
ExportLanguage struct {
16+
ISO6393 string `db:"iso_639_3" json:"iso_639_3"`
17+
Name string `db:"name" json:"name"`
18+
}
19+
ExportBrowserStat struct {
20+
Day string `db:"day" json:"day"`
21+
PathID PathID `db:"path_id" json:"path_id"`
22+
BrowserID BrowserID `db:"browser_id" json:"browser_id"`
23+
Count int `db:"count" json:"count"`
24+
}
25+
ExportSystemStat struct {
26+
Day string `db:"day" json:"day"`
27+
PathID PathID `db:"path_id" json:"path_id"`
28+
SystemID SystemID `db:"system_id" json:"system_id"`
29+
Count int `db:"count" json:"count"`
30+
}
31+
ExportLocationStat struct {
32+
Day string `db:"day" json:"day"`
33+
PathID PathID `db:"path_id" json:"path_id"`
34+
Location string `db:"location" json:"location"`
35+
Count int `db:"count" json:"count"`
36+
}
37+
ExportSizeStat struct {
38+
Day string `db:"day" json:"day"`
39+
PathID PathID `db:"path_id" json:"path_id"`
40+
Width int `db:"width" json:"width"`
41+
Count int `db:"count" json:"count"`
42+
}
43+
ExportLanguageStat struct {
44+
Day string `db:"day" json:"day"`
45+
PathID PathID `db:"path_id" json:"path_id"`
46+
Language string `db:"language" json:"language"`
47+
Count int `db:"count" json:"count"`
48+
}
49+
ExportCampaignStat struct {
50+
Day string `db:"day" json:"day"`
51+
PathID PathID `db:"path_id" json:"path_id"`
52+
CampaignID CampaignID `db:"campaign_id" json:"campaign_id"`
53+
Ref string `db:"ref" json:"ref"`
54+
Count int `db:"count" json:"count"`
55+
}
56+
ExportHitStat struct {
57+
Day string `db:"day" json:"day"`
58+
PathID PathID `db:"path_id" json:"path_id"`
59+
//Stats Stat `db:"stats" json:"stats"`
60+
Stats json.RawMessage `db:"stats" json:"stats"`
61+
}
62+
ExportRefStat struct {
63+
Hour string `db:"hour" json:"hour"`
64+
PathID PathID `db:"path_id" json:"path_id"`
65+
RefID RefID `db:"ref_id" json:"ref_id"`
66+
Count int `db:"total" json:"count"`
67+
}
68+
)

export.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ func (e Export) Exists() bool {
6868
if e.Path == "" {
6969
return false
7070
}
71-
7271
_, err := os.Stat(e.Path)
7372
return err == nil
7473
}

exportcsv.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,23 @@ func (e *Export) CreateCSV(ctx context.Context, startFrom HitID) (*os.File, erro
3939

4040
err := zdb.Insert(ctx, e)
4141
if err != nil {
42-
return nil, errors.Wrap(err, "Export.Create")
42+
return nil, errors.Wrap(err, "Export.CreateCSV")
4343
}
4444

4545
fp, err := os.Create(e.Path)
46-
return fp, errors.Wrap(err, "Export.Create")
46+
return fp, errors.Wrap(err, "Export.CreateCSV")
4747
}
4848

4949
// Export all data to a CSV file.
5050
func (e *Export) RunCSV(ctx context.Context, fp *os.File, mailUser bool) {
5151
l := log.Module("export").With("id", e.ID)
52-
l.Info(ctx, "export started")
52+
l.Info(ctx, "CSV export started")
5353

5454
gzfp := gzip.NewWriter(fp)
55-
defer fp.Close() // No need to error-check; just for safety.
56-
defer gzfp.Close()
55+
defer func() {
56+
gzfp.Close()
57+
fp.Close()
58+
}()
5759

5860
c := csv.NewWriter(gzfp)
5961
c.Write([]string{ExportCSVVersion + "Path", "Title", "Event", "UserAgent",
@@ -104,7 +106,7 @@ func (e *Export) RunCSV(ctx context.Context, fp *os.File, mailUser bool) {
104106
e.Error = new(exportErr.Error())
105107
err := zdb.Update(ctx, e, "error")
106108
if err != nil {
107-
log.Error(ctx, err)
109+
l.Error(ctx, err)
108110
}
109111

110112
_ = gzfp.Close()
@@ -118,12 +120,12 @@ func (e *Export) RunCSV(ctx context.Context, fp *os.File, mailUser bool) {
118120
l.Error(ctx, err)
119121
return
120122
}
123+
121124
err = fp.Sync() // Ensure stat is correct.
122125
if err != nil {
123126
l.Error(ctx, err)
124127
return
125128
}
126-
127129
stat, err := fp.Stat()
128130
size := "0"
129131
if err == nil {
@@ -150,7 +152,7 @@ func (e *Export) RunCSV(ctx context.Context, fp *os.File, mailUser bool) {
150152
e.FinishedAt = new(ztime.Now(ctx))
151153
zdb.Update(ctx, e, "finished_at", "num_rows", "size", "hash", "last_hit_id")
152154
if err != nil {
153-
log.Error(ctx, err)
155+
l.Error(ctx, err)
154156
}
155157

156158
if mailUser {

0 commit comments

Comments
 (0)