From 626de69c9562b9d7d66f1cfd5a44148108ad6d26 Mon Sep 17 00:00:00 2001 From: Danny van Kooten Date: Fri, 13 Jan 2017 16:45:17 +0100 Subject: [PATCH] generate unique visitor key from date + ip + user agent --- api/collect.go | 26 +++++++++++++++++++------- db/seed.go | 7 ++++--- models/visitor.go | 7 +++---- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/api/collect.go b/api/collect.go index 567fcac..23a646a 100644 --- a/api/collect.go +++ b/api/collect.go @@ -1,7 +1,9 @@ package api import ( + "database/sql" "encoding/base64" + "log" "net/http" "strings" "time" @@ -42,13 +44,18 @@ func CollectHandler(w http.ResponseWriter, r *http.Request) { defer stmt.Close() err := stmt.QueryRow(page.Hostname, page.Path).Scan(&page.ID) if err != nil { - page.Save(db.Conn) + if err == sql.ErrNoRows { + page.Save(db.Conn) + } else { + log.Fatal(err) + } } // find or insert visitor. - // TODO: Mask IP Address + now := time.Now() + ip := getRequestIp(r) visitor := models.Visitor{ - IpAddress: getRequestIp(r), + IpAddress: ip, BrowserLanguage: q.Get("l"), ScreenResolution: q.Get("sr"), DeviceOS: ua.OS(), @@ -60,21 +67,26 @@ func CollectHandler(w http.ResponseWriter, r *http.Request) { visitor.BrowserName = parseMajorMinor(visitor.BrowserName) // query by unique visitor key - visitor.GenerateKey() + visitor.Key = visitor.GenerateKey(now.Format("2006-01-02"), visitor.IpAddress, r.UserAgent()) + stmt, _ = db.Conn.Prepare("SELECT v.id FROM visitors v WHERE v.visitor_key = ? LIMIT 1") defer stmt.Close() err = stmt.QueryRow(visitor.Key).Scan(&visitor.ID) if err != nil { - visitor.Save(db.Conn) + if err == sql.ErrNoRows { + err = visitor.Save(db.Conn) + checkError(err) + } else { + log.Fatal(err) + } } - now := time.Now().Format("2006-01-02 15:04:05") pageview := models.Pageview{ PageID: page.ID, VisitorID: visitor.ID, ReferrerUrl: q.Get("ru"), ReferrerKeyword: q.Get("rk"), - Timestamp: now, + Timestamp: now.Format("2006-01-02 15:04:05"), } // only store referrer URL if not coming from own site diff --git a/db/seed.go b/db/seed.go index 1b52ec0..95cfe17 100644 --- a/db/seed.go +++ b/db/seed.go @@ -99,6 +99,7 @@ func Seed(n int) { // print a dot as progress indicator fmt.Print(".") + date := randomDateBeforeNow() // create or find visitor visitor := models.Visitor{ @@ -110,7 +111,8 @@ func Seed(n int) { ScreenResolution: randSliceElement(screenResolutions), Country: randomdata.Country(randomdata.TwoCharCountry), } - visitor.Key = visitor.GenerateKey() + dummyUserAgent := visitor.BrowserName + visitor.BrowserVersion + visitor.DeviceOS + visitor.Key = visitor.GenerateKey(date.Format("2006-01-02"), visitor.IpAddress, dummyUserAgent) err := stmtVisitor.QueryRow(visitor.Key).Scan(&visitor.ID) if err != nil { @@ -118,7 +120,6 @@ func Seed(n int) { } // generate random timestamp - date := randomDateBeforeNow() timestamp := fmt.Sprintf("%s %d:%d:%d", date.Format("2006-01-02"), randInt(10, 24), randInt(10, 60), randInt(10, 60)) pv := models.Pageview{ @@ -144,7 +145,7 @@ func Seed(n int) { func randomDate() time.Time { now := time.Now() month := months[randInt(0, len(months))] - t := time.Date(now.Year(), month, randInt(1, 31), randInt(0, 23), randInt(0, 59), randInt(0, 59), 0, time.UTC) + t := time.Date(randInt(now.Year()-1, now.Year()), month, randInt(1, 31), randInt(0, 23), randInt(0, 59), randInt(0, 59), 0, time.UTC) return t } diff --git a/models/visitor.go b/models/visitor.go index 0b84494..61ed3d1 100644 --- a/models/visitor.go +++ b/models/visitor.go @@ -34,7 +34,6 @@ func (v *Visitor) Save(conn *sql.DB) error { return err } defer stmt.Close() - result, err := stmt.Exec( v.Key, v.IpAddress, @@ -53,8 +52,8 @@ func (v *Visitor) Save(conn *sql.DB) error { return err } -// GenerateKey generates the "unique" visitor key -func (v *Visitor) GenerateKey() string { - byteKey := md5.Sum([]byte(v.IpAddress + v.DeviceOS + v.BrowserName + v.ScreenResolution)) +// GenerateKey generates the "unique" visitor key from date, user agent + screen resolution +func (v *Visitor) GenerateKey(date string, ipAddress string, userAgent string) string { + byteKey := md5.Sum([]byte(date + ipAddress + userAgent)) return hex.EncodeToString(byteKey[:]) }