diff --git a/cmd/fathom/main.go b/cmd/fathom/main.go index 18184ed..85909a8 100644 --- a/cmd/fathom/main.go +++ b/cmd/fathom/main.go @@ -39,6 +39,7 @@ func main() { app.Commands = []cli.Command{ serverCmd, registerCmd, + statsCmd, } if len(os.Args) < 2 || os.Args[1] != "--version" { @@ -50,6 +51,8 @@ func main() { log.Fatal(err) os.Exit(1) } + + os.Exit(0) } func before(c *cli.Context) error { diff --git a/cmd/fathom/stats.go b/cmd/fathom/stats.go new file mode 100644 index 0000000..1a3a6bb --- /dev/null +++ b/cmd/fathom/stats.go @@ -0,0 +1,50 @@ +package main + +import ( + "errors" + "fmt" + "github.com/urfave/cli" + "time" +) + +var statsCmd = cli.Command{ + Name: "stats", + Usage: "view stats", + Action: stats, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "start-date", + Usage: "start date, expects a date in format 2006-01-02", + }, + cli.StringFlag{ + Name: "end-date", + Usage: "end date, expects a date in format 2006-01-02", + }, + }, +} + +func stats(c *cli.Context) error { + start, _ := time.Parse("2006-01-02", c.String("start-date")) + if start.IsZero() { + return errors.New("Invalid argument: supply a valid --start-date") + } + + end, _ := time.Parse("2006-01-02", c.String("end-date")) + if end.IsZero() { + return errors.New("Invalid argument: supply a valid --end-date") + } + + result, err := app.database.GetAggregatedSiteStats(start, end) + if err != nil { + return err + } + + fmt.Printf("%s - %s\n", start.Format("Jan 01, 2006"), end.Format("Jan 01, 2006")) + fmt.Printf("===========================\n") + fmt.Printf("Visitors: \t%d\n", result.Visitors) + fmt.Printf("Pageviews: \t%d\n", result.Pageviews) + fmt.Printf("Sessions: \t%d\n", result.Sessions) + fmt.Printf("Avg duration: \t%s\n", result.FormattedDuration()) + fmt.Printf("Bounce rate: \t%.0f%%\n", result.BounceRate*100.00) + return nil +} diff --git a/pkg/models/site_stats.go b/pkg/models/site_stats.go index 21b8a24..ff2cdfc 100644 --- a/pkg/models/site_stats.go +++ b/pkg/models/site_stats.go @@ -1,6 +1,7 @@ package models import ( + "fmt" "time" ) @@ -13,3 +14,7 @@ type SiteStats struct { KnownDurations int64 `db:"known_durations" json:",omitempty"` Date time.Time `db:"date" json:",omitempty"` } + +func (s *SiteStats) FormattedDuration() string { + return fmt.Sprintf("%d:%d", int(s.AvgDuration/60.00), (int(s.AvgDuration) % 60)) +} diff --git a/pkg/models/site_stats_test.go b/pkg/models/site_stats_test.go new file mode 100644 index 0000000..4a15e8f --- /dev/null +++ b/pkg/models/site_stats_test.go @@ -0,0 +1,21 @@ +package models + +import ( + "testing" +) + +func TestSiteStatsFormattedDuration(t *testing.T) { + s := SiteStats{ + AvgDuration: 100.00, + } + e := "1:40" + if v := s.FormattedDuration(); v != e { + t.Errorf("FormattedDuration: expected %s, got %s", e, v) + } + + s.AvgDuration = 1040.22 + e = "17:20" + if v := s.FormattedDuration(); v != e { + t.Errorf("FormattedDuration: expected %s, got %s", e, v) + } +}