Browse Source

Add tracking of operating systems

pull/19/head
Jan-Lukas Else 2 years ago
parent
commit
e18e24da46
  1. 4
      README.md
  2. 25
      database.go
  3. 3
      migrations/4_Add_OS.sql
  4. 3
      stats.go

4
README.md

@ -80,7 +80,7 @@ You can request statistics via the `/stats` endpoint and specifying filters via
The following filters are available:
`view`: specify what data (and it's view counts) gets displayed, you have the option between `pages` (tracked URLS), `referrers` (tracked refererrers - only hostnames e.g. google.com), `useragents` (tracked useragents with version - browsers or crawl bots with version), `useragentnames` (tracked useragents without version), `hours` / `days` / `weeks` / `months` (tracks grouped by hours / days / weeks / months), `allhours` / `alldays` (tracks grouped by hours / days including hours or days with zero visits, spanning from first to last track in selection), `count` (count all tracked views where filters apply)
`view`: specify what data (and it's view counts) gets displayed, you have the option between `pages` (tracked URLS), `referrers` (tracked refererrers - only hostnames e.g. google.com), `useragents` (tracked useragents with version - browsers or crawl bots with version), `useragentnames` (tracked useragents without version), `os` (tracked operating systems), `hours` / `days` / `weeks` / `months` (tracks grouped by hours / days / weeks / months), `allhours` / `alldays` (tracks grouped by hours / days including hours or days with zero visits, spanning from first to last track in selection), `count` (count all tracked views where filters apply)
`from`: start time of the selection in the format `YYYY-MM-DD HH:MM`, e.g. `2019-01` or `2019-01-01 01:00`
@ -94,6 +94,8 @@ The following filters are available:
`ua`: filter user agents containing the string provided, so `Firefox` filters out all user agents that don't contain `Firefox`
`os`: filter operating systems containing the string provided, so `Windows` filters out all operating systems that don't contain `Windows`
`bots`: filter out bots (`0`) or show only bots (`1`)
`ordercol`: column to use for ordering, `first` for the data groups, `second` for the view counts

25
database.go

@ -32,7 +32,7 @@ func initDatabase() (e error) {
return
}
e = migrateDatabase(db.sqlDB)
db.trackingStmt, e = db.sqlDB.Prepare("insert into views(url, ref, useragent, bot) values(:url, :ref, :ua, :bot)")
db.trackingStmt, e = db.sqlDB.Prepare("insert into views(url, ref, useragent, bot, os) values(:url, :ref, :ua, :bot, :os)")
if e != nil {
return
}
@ -60,6 +60,7 @@ func trackView(urlString string, ref string, ua string) {
ref = parsedRef.Hostname()
}
bot := 0
osString := ""
if ua != "" {
// Parse Useragent
userAgent := user_agent.New(ua)
@ -68,8 +69,15 @@ func trackView(urlString string, ref string, ua string) {
}
uaName, uaVersion := userAgent.Browser()
ua = uaName + " " + uaVersion
osInfo := userAgent.OSInfo()
if osInfo.FullName != "" {
osString = osInfo.FullName
if osInfo.Version != "" {
osString += " " + osInfo.Version
}
}
}
_, e := db.trackingStmt.Exec(sql.Named("url", urlString), sql.Named("ref", ref), sql.Named("ua", ua), sql.Named("bot", bot))
_, e := db.trackingStmt.Exec(sql.Named("url", urlString), sql.Named("ref", ref), sql.Named("ua", ua), sql.Named("bot", bot), sql.Named("os", osString))
if e != nil {
fmt.Println("Inserting into DB failed:", e)
}
@ -84,6 +92,7 @@ const (
REFERRERS
USERAGENTS
USERAGENTNAMES
OS
HOURS
DAYS
WEEKS
@ -106,6 +115,7 @@ type ViewsRequest struct {
order string
limit string
bots string
os string
}
type RequestResultRow struct {
@ -182,6 +192,8 @@ func (request *ViewsRequest) buildStatement() (statement string, parameters []sq
statement = "SELECT useragent as first, count(*) as second from views" + filters + "group by first" + orderStatement + limitStatement + ";"
case USERAGENTNAMES:
statement = "SELECT substr(useragent, 1, pos-1) as first, COUNT(*) as second from (SELECT *, instr(useragent,' ') AS pos FROM views)" + filters + "group by first" + orderStatement + limitStatement + ";"
case OS:
statement = "SELECT os as first, count(*) as second from views" + filters + "group by first" + orderStatement + limitStatement + ";"
case ALLHOURS:
statement = "WITH RECURSIVE hours(hour) AS ( VALUES (datetime(strftime('%Y-%m-%dT%H:00', (SELECT min(time) from views" + filters + "), 'localtime'))) UNION ALL SELECT datetime(hour, '+1 hour') FROM hours WHERE hour <= strftime('%Y-%m-%d %H', (SELECT max(time) from views" + filters + "), 'localtime') ) SELECT strftime('%Y-%m-%d %H', hours.hour) as first, COUNT(time) as second FROM hours LEFT OUTER JOIN (SELECT time from views" + filters + ") ON strftime('%Y-%m-%d %H', hours.hour) = strftime('%Y-%m-%d %H', time, 'localtime') GROUP BY first" + orderStatement + limitStatement + ";"
case ALLDAYS:
@ -216,6 +228,7 @@ func (request *ViewsRequest) buildFilter() (filters string, parameters []sql.Nam
request.buildRefFilter(&parameters),
request.buildUseragentFilter(&parameters),
request.buildBotFilter(&parameters),
request.buildOSFilter(&parameters),
} {
if len(filter) > 0 {
allFilters = append(allFilters, filter)
@ -288,3 +301,11 @@ func (request *ViewsRequest) buildBotFilter(namedArg *[]sql.NamedArg) (botFilter
}
return
}
func (request *ViewsRequest) buildOSFilter(namedArg *[]sql.NamedArg) (osFilter string) {
if len(request.os) > 0 {
*namedArg = append(*namedArg, sql.Named("os", "%"+request.os+"%"))
osFilter = "os like :os"
}
return
}

3
migrations/4_Add_OS.sql

@ -0,0 +1,3 @@
-- +migrate Up
ALTER TABLE views
ADD COLUMN os TEXT DEFAULT '' NOT NULL;

3
stats.go

@ -55,6 +55,8 @@ func doRequest(queries url.Values) (result []*RequestResultRow, e error) {
view = USERAGENTS
case "useragentnames":
view = USERAGENTNAMES
case "os":
view = OS
case "hours":
view = HOURS
case "days":
@ -83,6 +85,7 @@ func doRequest(queries url.Values) (result []*RequestResultRow, e error) {
order: strings.ToUpper(queries.Get("order")),
limit: queries.Get("limit"),
bots: queries.Get("bots"),
os: queries.Get("os"),
})
return
}

Loading…
Cancel
Save