Documentation
¶
Index ¶
- Constants
- Variables
- func DefaultLocale() *z18n.Locale
- func HorizontalChart(ctx context.Context, stats HitStats, total int, link, paginate bool) template.HTML
- func ImportCSV(ctx context.Context, fp io.Reader, replace, email bool, ...) (*time.Time, error)
- func ImportGA(ctx context.Context, fp io.Reader) error
- func Interval(ctx context.Context, days int) string
- func ListCache(ctx context.Context) map[string]struct{ ... }
- func LoadBufferKey(ctx context.Context) ([]byte, error)
- func NewBufferKey(ctx context.Context) (string, error)
- func NewCache(ctx context.Context) context.Context
- func NewConfig(ctx context.Context) context.Context
- func NewContext(ctx context.Context, db zdb.DB) context.Context
- func NewValidate(ctx context.Context) zvalidate.Validator
- func UUID() zint.Uint128
- func WithSite(ctx context.Context, s *Site) context.Context
- func WithUser(ctx context.Context, u *User) context.Context
- type APIToken
- func (t *APIToken) ByID(ctx context.Context, id APITokenID) error
- func (t *APIToken) ByToken(ctx context.Context, token string) error
- func (t *APIToken) Defaults(ctx context.Context)
- func (t *APIToken) Delete(ctx context.Context) error
- func (t APIToken) FormatPermissions() string
- func (t *APIToken) Insert(ctx context.Context) error
- func (t APIToken) PermissionFlags(only ...zint.Bitflag64) []PermissionFlag
- func (t *APIToken) Update(ctx context.Context) error
- func (t *APIToken) UpdateLastUsed(ctx context.Context) error
- func (t *APIToken) Validate(ctx context.Context) error
- type APITokenID
- type APITokens
- type Browser
- type BrowserID
- type Campaign
- type CampaignID
- type CollectFlag
- type EmailReport
- type Export
- type ExportCSVRow
- type ExportCSVRows
- type ExportID
- type Exports
- type Floats
- type GlobalConfig
- type Group
- type Hit
- type HitID
- type HitList
- type HitListStat
- type HitLists
- func (h HitLists) Diff(ctx context.Context, rng, prev ztime.Range) ([]float64, error)
- func (h *HitLists) List(ctx context.Context, rng ztime.Range, pathFilter, exclude []PathID, limit int, ...) (int, bool, error)
- func (h *HitLists) ListPathsLike(ctx context.Context, search string, matchTitle, matchCase bool) error
- type HitStat
- type HitStats
- func (h *HitStats) ListBrowser(ctx context.Context, browser string, rng ztime.Range, pathFilter []PathID, ...) error
- func (h *HitStats) ListBrowsers(ctx context.Context, rng ztime.Range, pathFilter []PathID, limit, offset int) error
- func (h *HitStats) ListCampaign(ctx context.Context, campaign CampaignID, rng ztime.Range, pathFilter []PathID, ...) error
- func (h *HitStats) ListCampaigns(ctx context.Context, rng ztime.Range, pathFilter []PathID, limit, offset int) error
- func (h *HitStats) ListLanguages(ctx context.Context, rng ztime.Range, pathFilter []PathID, limit, offset int) error
- func (h *HitStats) ListLocation(ctx context.Context, country string, rng ztime.Range, pathFilter []PathID, ...) error
- func (h *HitStats) ListLocations(ctx context.Context, rng ztime.Range, pathFilter []PathID, limit, offset int) error
- func (h *HitStats) ListRefsByPathID(ctx context.Context, pathID PathID, rng ztime.Range, limit, offset int) error
- func (h *HitStats) ListSize(ctx context.Context, id string, rng ztime.Range, pathFilter []PathID, ...) error
- func (h *HitStats) ListSizes(ctx context.Context, rng ztime.Range, pathFilter []PathID) error
- func (h *HitStats) ListSystem(ctx context.Context, system string, rng ztime.Range, pathFilter []PathID, ...) error
- func (h *HitStats) ListSystems(ctx context.Context, rng ztime.Range, pathFilter []PathID, limit, offset int) error
- func (h *HitStats) ListTopRef(ctx context.Context, ref string, rng ztime.Range, pathFilter []PathID, ...) error
- func (h *HitStats) ListTopRefs(ctx context.Context, rng ztime.Range, pathFilter []PathID, limit, offset int) error
- type Hits
- type Ints
- type Location
- type LocationID
- type Locations
- type Path
- func (p *Path) ByID(ctx context.Context, id PathID) error
- func (p *Path) ByPath(ctx context.Context, path string) error
- func (p *Path) Defaults(ctx context.Context)
- func (p *Path) GetOrInsert(ctx context.Context) error
- func (p Path) Merge(ctx context.Context, paths Paths) error
- func (p *Path) Validate(ctx context.Context) error
- type PathID
- type Paths
- type PermissionFlag
- type Ref
- type RefID
- type Site
- func (s *Site) ByCode(ctx context.Context, code string) error
- func (s *Site) ByHost(ctx context.Context, host string) error
- func (s *Site) ByID(ctx context.Context, id SiteID) error
- func (s *Site) ByIDState(ctx context.Context, id SiteID, state string) error
- func (s Site) ClearCache(ctx context.Context, full bool)
- func (s *Site) Defaults(ctx context.Context)
- func (s *Site) Delete(ctx context.Context, deleteChildren bool) error
- func (s Site) DeleteAll(ctx context.Context) error
- func (s Site) DeleteOlderThan(ctx context.Context, days int) error
- func (s Site) Display(ctx context.Context) string
- func (s Site) Domain(ctx context.Context) string
- func (s Site) Exists(ctx context.Context) (SiteID, error)
- func (s *Site) Find(ctx context.Context, ident string) error
- func (s Site) IDOrParent() SiteID
- func (s *Site) Insert(ctx context.Context) error
- func (s Site) LinkDomainURL(withProto bool, paths ...string) string
- func (s *Site) ListSubs(ctx context.Context) ([]string, error)
- func (s Site) SchemelessURL(ctx context.Context) string
- func (s Site) URL(ctx context.Context) string
- func (s Site) Undelete(ctx context.Context, id SiteID) error
- func (s *Site) Update(ctx context.Context) error
- func (s *Site) UpdateCnameSetupAt(ctx context.Context) error
- func (s *Site) UpdateCode(ctx context.Context, code string) error
- func (s *Site) UpdateFirstHitAt(ctx context.Context, f time.Time) error
- func (s *Site) UpdateParent(ctx context.Context, newParent *SiteID) error
- func (s *Site) UpdateReceivedData(ctx context.Context) error
- func (s *Site) Validate(ctx context.Context) error
- type SiteID
- type SiteIDs
- type SiteSettings
- func (ss SiteSettings) CanView(token string) bool
- func (ss SiteSettings) CollectFlags(ctx context.Context) []CollectFlag
- func (ss *SiteSettings) Defaults(ctx context.Context)
- func (ss SiteSettings) IsPublic() bool
- func (ss *SiteSettings) Scan(v any) error
- func (ss SiteSettings) String() string
- func (ss *SiteSettings) Validate(ctx context.Context) error
- func (ss SiteSettings) Value() (driver.Value, error)
- type Sites
- func (s *Sites) ContainsCNAME(ctx context.Context, cname string) (bool, error)
- func (s *Sites) Delete(ctx context.Context, deleteChildren bool) error
- func (s *Sites) Find(ctx context.Context, ident []string) error
- func (s *Sites) ForAccount(ctx context.Context, accountID SiteID) error
- func (s *Sites) ForThisAccount(ctx context.Context, excludeCurrent bool) error
- func (s *Sites) IDs() []int32
- func (s *Sites) ListSubs(ctx context.Context) error
- func (s *Sites) OldSoftDeleted(ctx context.Context) error
- func (s *Sites) UnscopedList(ctx context.Context) error
- func (s *Sites) UnscopedListCnames(ctx context.Context) error
- type Strings
- type System
- type SystemID
- type TotalCount
- type TplEmailAddUser
- type TplEmailExportDone
- type TplEmailForgotSite
- type TplEmailImportDone
- type TplEmailImportError
- type TplEmailPasswordReset
- type TplEmailVerify
- type TplEmailWelcome
- type Translation
- type Translations
- type User
- func (u User) AccessAdmin() bool
- func (u User) AccessSettings() bool
- func (u User) AccessSuperuser() bool
- func (u *User) ByEmail(ctx context.Context, email string) error
- func (u *User) ByEmailToken(ctx context.Context, key string) error
- func (u *User) ByID(ctx context.Context, id UserID) error
- func (u *User) ByResetToken(ctx context.Context, key string) error
- func (u *User) BySiteAndEmail(ctx context.Context, siteID SiteID, email string) error
- func (u *User) ByToken(ctx context.Context, token string) error
- func (u *User) ByTokenAndSite(ctx context.Context, token string) error
- func (u *User) CSRFToken() string
- func (u User) CorrectPassword(pwd string) (bool, error)
- func (u *User) Defaults(ctx context.Context)
- func (u *User) Delete(ctx context.Context, lastAdmin bool) error
- func (u *User) DisableTOTP(ctx context.Context) error
- func (u User) EmailReportRange(ctx context.Context) ztime.Range
- func (u User) EmailShort() string
- func (u *User) EnableTOTP(ctx context.Context) error
- func (u *User) Find(ctx context.Context, ident string) error
- func (u User) HasAccess(check UserAccess) bool
- func (u *User) Insert(ctx context.Context, allowBlankPassword bool) error
- func (u *User) InviteToken(ctx context.Context) error
- func (u *User) Login(ctx context.Context) error
- func (u *User) Logout(ctx context.Context) error
- func (u *User) RequestReset(ctx context.Context) error
- func (u *User) Update(ctx context.Context, emailChanged bool) error
- func (u *User) UpdateOpenAt(ctx context.Context) error
- func (u *User) UpdatePassword(ctx context.Context, pwd string) error
- func (u *User) UpdateSite(ctx context.Context) error
- func (u *User) Validate(ctx context.Context, validatePassword bool) error
- func (u *User) VerifyEmail(ctx context.Context) error
- type UserAccess
- type UserAccesses
- type UserAgent
- type UserID
- type UserSettings
- type Users
- func (u Users) Admins() Users
- func (u *Users) ByEmail(ctx context.Context, email string) error
- func (u *Users) BySite(ctx context.Context, siteID SiteID) error
- func (u *Users) Delete(ctx context.Context, force bool) error
- func (u *Users) Find(ctx context.Context, ident []string) error
- func (u *Users) IDs() []int32
- func (u *Users) List(ctx context.Context, siteID SiteID) error
- type View
- type Views
- type Widget
- type WidgetSetting
- type WidgetSettings
- type Widgets
Constants ¶
const ( APIPermNothing zint.Bitflag64 = 1 << iota APIPermCount // 2 APIPermExport // 4 APIPermSiteRead // 8 APIPermSiteCreate // 16 APIPermSiteUpdate // 32 APIPermStats // 64 )
APIToken permissions.
DO NOT change the values of these constants; they're stored in the database.
const ( StateActive = "a" StateRequest = "r" StateDeleted = "d" )
State column values.
const ( GroupHourly = Group(iota) GroupDaily )
const ( CollectNothing zint.Bitflag16 = 1 << iota CollectReferrer // 2 CollectUserAgent // 4 CollectScreenSize // 8 CollectLocation // 16 CollectLocationRegion // 32 CollectLanguage // 64 CollectSession // 128 CollectHits // 256 )
Settings.Collect values (bitmask)
DO NOT change the values of these constants; they're stored in the database.
Note: also update CollectFlags() method below.
Nothing is 1 and 0 is "unset". This is so we can distinguish between "this field was never sent in the form" vs. "user unchecked all boxes".
const ( EmailReportNever = EmailReport(iota) // Email once after 2 weeks; for new sites. EmailReportDaily EmailReportWeekly EmailReportBiWeekly EmailReportMonthly )
UserSettings.EmailReport values.
const ExportCSVVersion = "2"
const PathTotals = "TOTAL "
PathTotals is a special path to indicate this is the "total" overview.
Trailing whitespace is trimmed on paths, so this should never conflict.
Variables ¶
var ( // Valid UUID for testing: 00112233-4455-6677-8899-aabbccddeeff TestSession = zint.Uint128{0x11223344556677, 0x8899aabbccddeeff} TestSeqSession = zint.Uint128{TestSession[0], TestSession[1] + 1} )
var ( RefSchemeHTTP = "h" RefSchemeOther = "o" RefSchemeGenerated = "g" RefSchemeCampaign = "c" )
ref_scheme column
var Bundle = func() *z18n.Bundle { b, err := newBundle(TranslationFiles) if err != nil { panic(err) } return b }()
var DB embed.FS
DB contains all files in db/*
var EmailReports = []EmailReport{EmailReportNever, EmailReportDaily, EmailReportWeekly, EmailReportBiWeekly, EmailReportMonthly}
var Groups = []Group{GroupHourly, GroupDaily}
var Memstore ms
var SQLiteHook = func(c *sqlite3.SQLiteConn) error { return c.RegisterFunc("percent_diff", func(start, final int) float64 { if start == 0 { return math.Inf(0) } return (float64(final - start)) / float64(start) * 100.0 }, true) }
var SessionTime = 8 * time.Hour
SessionTime is the maximum length of sessions; exported here for tests.
var States = []string{StateActive, StateRequest, StateDeleted}
var Static embed.FS
Static contains all the static files to serve.
var Tables = struct { HitCounts, RefCounts, HitStats tbl BrowserStats, SystemStats, SizeStats tbl LocationStats, LanguageStats, CampaignStats tbl }{ HitCounts: tbl{ Table: "hit_counts", Columns: []string{"site_id", "path_id", "hour", "total"}, Constraint: "site_id#path_id#hour", Update: `total = hit_counts.total + excluded.total`, }, RefCounts: tbl{ Table: "ref_counts", Columns: []string{"site_id", "path_id", "hour", "ref_id", "total"}, Constraint: "site_id#path_id#ref_id#hour", Update: `total = ref_counts.total + excluded.total`, }, BrowserStats: tbl{ Table: "browser_stats", Columns: []string{"site_id", "path_id", "day", "browser_id", "count"}, Constraint: "site_id#path_id#day#browser_id", Update: `count = browser_stats.count + excluded.count`, }, SystemStats: tbl{ Table: "system_stats", Columns: []string{"site_id", "path_id", "day", "system_id", "count"}, Constraint: "site_id#path_id#day#system_id", Update: `count = system_stats.count + excluded.count`, }, LocationStats: tbl{ Table: "location_stats", Columns: []string{"site_id", "path_id", "day", "location", "count"}, Constraint: "site_id#path_id#day#location", Update: `count = location_stats.count + excluded.count`, }, SizeStats: tbl{ Table: "size_stats", Columns: []string{"site_id", "path_id", "day", "width", "count"}, Constraint: "site_id#path_id#day#width", Update: `count = size_stats.count + excluded.count`, }, LanguageStats: tbl{ Table: "language_stats", Columns: []string{"site_id", "path_id", "day", "language", "count"}, Constraint: "site_id#path_id#day#language", Update: `count = language_stats.count + excluded.count`, }, CampaignStats: tbl{ Table: "campaign_stats", Columns: []string{"site_id", "path_id", "day", "campaign_id", "ref", "count"}, Constraint: "site_id#path_id#campaign_id#ref#day", Update: `count = campaign_stats.count + excluded.count`, }, HitStats: tbl{ Table: "hit_stats", Columns: []string{"site_id", "path_id", "day", "stats"}, Constraint: "site_id#path_id#day", Update: ` 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 ) `, }, }
var Templates embed.FS
Templates contains all templates.
var TranslationFiles = func() fs.FS { fsys, _ := fs.Sub(translations, "i18n") return fsys }()
TranslationFiles gets the translation messages.
var Version = "dev"
Version of GoatCounter; set at compile-time with:
-ldflags="-X zgo.at/goatcounter/v2.Version=…"
Functions ¶
func DefaultLocale ¶ added in v2.5.0
func HorizontalChart ¶
func ImportCSV ¶ added in v2.7.0
func ImportCSV( ctx context.Context, fp io.Reader, replace, email bool, persist func(Hit, bool), ) (*time.Time, error)
ImportCSV imports data from a CSV export.
The persist() callback will be called for every hit; you usually want to collect a bunch of them and then persist them.
After everything is done, this will be called once more with an empty hit and final set to true, to persist the last batch.
func NewContext ¶
NewContext creates a new context with all values set.
Types ¶
type APIToken ¶
type APIToken struct {
ID APITokenID `db:"api_token_id" json:"-"`
SiteID SiteID `db:"site_id" json:"-"`
UserID UserID `db:"user_id" json:"-"`
Name string `db:"name" json:"name"`
Token string `db:"token" json:"-"`
Permissions zint.Bitflag64 `db:"permissions" json:"permissions"`
Sites SiteIDs `db:"sites" json:"sites"`
CreatedAt time.Time `db:"created_at" json:"-"`
LastUsedAt *time.Time `db:"last_used_at" json:"-"`
}
func (APIToken) FormatPermissions ¶
func (APIToken) PermissionFlags ¶
func (t APIToken) PermissionFlags(only ...zint.Bitflag64) []PermissionFlag
PermissionFlags returns a list of all flags we know for the Permissions settings.
func (*APIToken) UpdateLastUsed ¶ added in v2.4.0
UpdateLastUsed sets the last used time to the current time.
type APITokenID ¶ added in v2.7.0
type APITokenID int32
type APITokens ¶
type APITokens []APIToken
type Browser ¶
type Campaign ¶ added in v2.3.0
type Campaign struct {
ID CampaignID `db:"campaign_id" json:"campaign_id"`
SiteID SiteID `db:"site_id" json:"site_id"`
Name string `db:"name" json:"name"`
}
type CampaignID ¶ added in v2.7.0
type CampaignID int32
type CollectFlag ¶
type EmailReport ¶ added in v2.7.0
type EmailReport uint8
type Export ¶
type Export struct {
ID ExportID `db:"export_id" json:"id,readonly"`
SiteID SiteID `db:"site_id" json:"site_id,readonly"`
// The hit ID this export was started from.
StartFromHitID HitID `db:"start_from_hit_id" json:"start_from_hit_id"`
// Last hit ID that was exported; can be used as start_from_hit_id.
LastHitID *HitID `db:"last_hit_id" json:"last_hit_id,readonly"`
Path string `db:"path" json:"path,readonly"` // {omitdoc}
CreatedAt time.Time `db:"created_at" json:"created_at,readonly"`
FinishedAt *time.Time `db:"finished_at" json:"finished_at,readonly"`
NumRows *int `db:"num_rows" json:"num_rows,readonly"`
// File size in MB.
Size *string `db:"size" json:"size,readonly"`
// SHA256 hash.
Hash *string `db:"hash" json:"hash,readonly"`
// Any errors that may have occured.
Error *string `db:"error" json:"error,readonly"`
}
func (*Export) CreateCSV ¶ added in v2.7.0
CreateCSV creates a new CSV export.
Inserts a row in exports table and returns open file pointer to the destination file.
type ExportCSVRow ¶ added in v2.7.0
type ExportCSVRow struct {
ID HitID `db:"hit_id"`
SiteID SiteID `db:"site_id"`
Path string `db:"path"`
Title string `db:"title"`
Event string `db:"event"`
UserAgent string `db:"ua"`
Browser string `db:"browser"`
System string `db:"system"`
Session zint.Uint128 `db:"session"`
Bot string `db:"bot"`
Ref string `db:"ref"`
RefScheme string `db:"ref_s"`
Size string `db:"size"`
Location string `db:"loc"`
FirstVisit string `db:"first"`
CreatedAt string `db:"created_at"`
}
func (*ExportCSVRow) Read ¶ added in v2.7.0
func (row *ExportCSVRow) Read(line []string) error
type ExportCSVRows ¶ added in v2.7.0
type ExportCSVRows []ExportCSVRow
type Floats ¶
type Floats []float64
Floats stores a slice of []float64 as a comma-separated string.
func (Floats) MarshalText ¶
func (*Floats) UnmarshalText ¶
type GlobalConfig ¶
type GlobalConfig struct {
Domain string
DomainStatic string
DomainCount string
BasePath string
URLStatic string
Dev bool
GoatcounterCom bool
Port string
EmailFrom string
BcryptMinCost bool
}
func Config ¶
func Config(ctx context.Context) *GlobalConfig
type Group ¶ added in v2.7.0
type Group uint8
func (*Group) UnmarshalJSON ¶ added in v2.7.0
func (*Group) UnmarshalText ¶ added in v2.7.0
type Hit ¶
type Hit struct {
ID HitID `db:"hit_id" json:"-"`
Site SiteID `db:"site_id" json:"-"`
PathID PathID `db:"path_id" json:"-"`
RefID RefID `db:"ref_id" json:"-"`
BrowserID BrowserID `db:"browser_id" json:"-"`
SystemID SystemID `db:"system_id" json:"-"`
CampaignID *CampaignID `db:"campaign" json:"-"`
Session zint.Uint128 `db:"session" json:"-"`
Width *int16 `db:"width" json:"width"`
Path string `db:"-" json:"p,omitempty"`
Title string `db:"-" json:"t,omitempty"`
Ref string `db:"-" json:"r,omitempty"`
Event zbool.Bool `db:"-" json:"e,omitempty"`
Size Floats `db:"-" json:"s,omitempty"`
Query string `db:"-" json:"q,omitempty"`
Bot int `db:"-" json:"b,omitempty"`
RefScheme string `db:"ref_scheme" json:"-"`
UserAgentHeader string `db:"-" json:"-"`
Location string `db:"location" json:"-"`
Language *string `db:"language" json:"-"`
FirstVisit zbool.Bool `db:"first_visit" json:"-"`
CreatedAt time.Time `db:"created_at" json:"-"`
RefURL *url.URL `db:"-" json:"-"` // Parsed Ref
Random string `db:"-" json:"rnd"` // Browser cache buster, as they don't always listen to Cache-Control
// Some values we need to pass from the HTTP handler to memstore
RemoteAddr string `db:"-" json:"-"`
UserSessionID string `db:"-" json:"-"`
NoStore bool `db:"-" json:"-"` // Don't store in hits (still store in stats).
// contains filtered or unexported fields
}
type HitList ¶
type HitList struct {
// Number of visitors for the selected date range.
Count int `db:"count" json:"count"`
// Path ID
PathID PathID `db:"path_id" json:"path_id"`
// Path name (e.g. /hello.html).
Path string `db:"path" json:"path"`
// Is this an event?
Event zbool.Bool `db:"event" json:"event"`
// Page title.
Title string `db:"title" json:"title"`
// Highest visitors per hour or day (depending on daily being set).
Max int `json:"max"`
// Statistics by day and hour.
Stats []HitListStat `json:"stats"`
// What kind of referral this is; only set when retrieving referrals {enum: h g c o}.
//
// h HTTP Referal header.
// g Generated; for example are Google domains (google.com, google.nl,
// google.co.nz, etc.) are grouped as the generated referral "Google".
// c Campaign (via query parameter)
// o Other
RefScheme *string `db:"ref_scheme" json:"ref_scheme,omitempty"`
}
func (*HitList) SiteTotalUTC ¶
SiteTotal gets the total counts for all paths. This always uses UTC.
type HitListStat ¶
type HitLists ¶
type HitLists []HitList
func (HitLists) Diff ¶ added in v2.3.0
Diff gets the difference in percentage of all paths in this HitList.
e.g. if called with start=2020-01-20; end=2020-01-2020-01-27, then it will compare this to start=2020-01-12; end=2020-01-19
The return value is in the same order as paths.
type HitStat ¶
type HitStat struct {
// ID for selecting more details; not present in the detail view.
ID string `db:"id" json:"id,omitempty"`
Name string `db:"name" json:"name"` // Display name.
Count int `db:"count" json:"count"` // Number of visitors.
// What kind of referral this is; only set when retrieving referrals {enum: h g c o}.
//
// h HTTP Referal header.
// g Generated; for example are Google domains (google.com, google.nl,
// google.co.nz, etc.) are grouped as the generated referral "Google".
// c Campaign (via query parameter)
// o Other
RefScheme *string `db:"ref_scheme" json:"ref_scheme,omitempty"`
}
type HitStats ¶
func (*HitStats) ListBrowser ¶
func (h *HitStats) ListBrowser(ctx context.Context, browser string, rng ztime.Range, pathFilter []PathID, limit, offset int) error
ListBrowser lists all the versions for one browser.
func (*HitStats) ListBrowsers ¶
func (h *HitStats) ListBrowsers(ctx context.Context, rng ztime.Range, pathFilter []PathID, limit, offset int) error
ListBrowsers lists all browser statistics for the given time period.
func (*HitStats) ListCampaign ¶ added in v2.3.0
func (h *HitStats) ListCampaign(ctx context.Context, campaign CampaignID, rng ztime.Range, pathFilter []PathID, limit, offset int) error
ListCampaign lists all statistics for a campaign.
func (*HitStats) ListCampaigns ¶ added in v2.3.0
func (h *HitStats) ListCampaigns(ctx context.Context, rng ztime.Range, pathFilter []PathID, limit, offset int) error
ListCampaigns lists all campaigns statistics for the given time period.
func (*HitStats) ListLanguages ¶ added in v2.2.0
func (h *HitStats) ListLanguages(ctx context.Context, rng ztime.Range, pathFilter []PathID, limit, offset int) error
ListLanguages lists all language statistics for the given time period.
func (*HitStats) ListLocation ¶
func (h *HitStats) ListLocation(ctx context.Context, country string, rng ztime.Range, pathFilter []PathID, limit, offset int) error
ListLocation lists all divisions for a location
func (*HitStats) ListLocations ¶
func (h *HitStats) ListLocations(ctx context.Context, rng ztime.Range, pathFilter []PathID, limit, offset int) error
ListLocations lists all location statistics for the given time period.
func (*HitStats) ListRefsByPathID ¶ added in v2.4.0
func (h *HitStats) ListRefsByPathID(ctx context.Context, pathID PathID, rng ztime.Range, limit, offset int) error
ListRefsByPath lists all references for a pathID.
func (*HitStats) ListSize ¶
func (h *HitStats) ListSize(ctx context.Context, id string, rng ztime.Range, pathFilter []PathID, limit, offset int) error
ListSize lists all sizes for one grouping.
func (*HitStats) ListSystem ¶
func (h *HitStats) ListSystem(ctx context.Context, system string, rng ztime.Range, pathFilter []PathID, limit, offset int) error
ListSystem lists all the versions for one system.
func (*HitStats) ListSystems ¶
func (h *HitStats) ListSystems(ctx context.Context, rng ztime.Range, pathFilter []PathID, limit, offset int) error
ListSystems lists OS statistics for the given time period.
func (*HitStats) ListTopRef ¶
func (h *HitStats) ListTopRef(ctx context.Context, ref string, rng ztime.Range, pathFilter []PathID, limit, offset int) error
ListTopRef lists all paths by referrer.
func (*HitStats) ListTopRefs ¶
func (h *HitStats) ListTopRefs(ctx context.Context, rng ztime.Range, pathFilter []PathID, limit, offset int) error
ListTopRefs lists all ref statistics for the given time period, excluding referrals from the configured LinkDomain.
The returned count is the count without LinkDomain, and is different from the total number of hits.
type Ints ¶
type Ints []int64
Ints stores a slice of []int64 as a comma-separated string.
func (Ints) MarshalText ¶
func (*Ints) UnmarshalText ¶
type Location ¶
type Location struct {
ID LocationID `db:"location_id"`
Country string `db:"country"`
Region string `db:"region"`
CountryName string `db:"country_name"`
RegionName string `db:"region_name"`
// TODO: send patch to staticcheck to deal with this better. This shouldn't
// errror since "ISO" is an initialism.
ISO3166_2 string `db:"iso_3166_2"` //lint:ignore ST1003 staticcheck bug
}
type LocationID ¶ added in v2.7.0
type LocationID int32
type Path ¶
type Path struct {
ID PathID `db:"path_id" json:"id"` // Path ID
Site SiteID `db:"site_id" json:"-"`
Path string `db:"path" json:"path"` // Path name
Title string `db:"title" json:"title"` // Page title
Event zbool.Bool `db:"event" json:"event"` // Is this an event?
}
type PathID ¶ added in v2.7.0
type PathID int32
func FindPathIDs ¶ added in v2.7.0
FindPathsIDs finds path IDs by exact matches on the name.
type PermissionFlag ¶
type Site ¶
type Site struct {
ID SiteID `db:"site_id" json:"id,readonly"`
Parent *SiteID `db:"parent" json:"parent,readonly"`
// Custom domain, e.g. "stats.example.com".
//
// When self-hosting this is the domain/vhost your site is accessible at.
Cname *string `db:"cname" json:"cname"`
// When the CNAME was verified.
CnameSetupAt *time.Time `db:"cname_setup_at" json:"cname_setup_at,readonly"`
// Domain code (e.g. "arp242", which makes arp242.goatcounter.com). Only
// used for goatcounter.com and not when self-hosting.
Code string `db:"code" json:"code"`
// Site domain for linking (www.arp242.net). Note this can be a full URL and
// is a bit misnamed.
LinkDomain string `db:"link_domain" json:"link_domain"`
Settings SiteSettings `db:"settings" json:"setttings"`
UserDefaults UserSettings `db:"user_defaults" json:"user_defaults"`
// Whether this site has received any data; will be true after the first
// pageview.
ReceivedData bool `db:"received_data" json:"received_data"`
// {omitdoc}
Notes string `db:"notes" json:"-"`
State string `db:"state" json:"state"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt *time.Time `db:"updated_at" json:"updated_at"`
FirstHitAt time.Time `db:"first_hit_at" json:"first_hit_at"`
}
func GetAccount ¶
GetAccount gets this site's "account site" on which the users, etc. are stored.
func MustGetAccount ¶
func MustGetSite ¶
MustGetSite behaves as GetSite(), panicking if this fails.
func (Site) ClearCache ¶
ClearCache clears the cache for this site.
func (Site) DeleteAll ¶
DeleteAll deletes all pageviews for this site, keeping the site itself and user intact.
func (Site) Domain ¶
Domain gets the global default domain, or this site's configured custom domain.
func (Site) Exists ¶
Exists checks if this site already exists, based on either the Cname or Code field.
func (Site) IDOrParent ¶
IDOrParent gets this site's ID or the parent ID if that's set.
func (Site) LinkDomainURL ¶
LinkDomainURL creates a valid url to the configured LinkDomain.
func (Site) SchemelessURL ¶ added in v2.6.0
URL to this site, without the scheme.
func (*Site) UpdateCnameSetupAt ¶
UpdateCnameSetupAt confirms the custom domain was setup correct.
func (*Site) UpdateCode ¶
UpdateCode changes the site's domain code (e.g. "test" in "test.goatcounter.com").
func (*Site) UpdateFirstHitAt ¶
func (*Site) UpdateParent ¶
type SiteIDs ¶ added in v2.7.0
type SiteIDs []SiteID
func (*SiteIDs) UnmarshalJSON ¶ added in v2.7.0
func (*SiteIDs) UnmarshalText ¶ added in v2.7.0
func (s SiteIDs) MarshalText() ([]byte, error) { return json.Marshal(s) }
type SiteSettings ¶
type SiteSettings struct {
Public string `json:"public"`
Secret string `json:"secret"`
AllowCounter bool `json:"allow_counter"`
AllowBosmang bool `json:"allow_bosmang"`
DataRetention int `json:"data_retention"`
Campaigns Strings `json:"-"`
IgnoreIPs Strings `json:"ignore_ips"`
Collect zint.Bitflag16 `json:"collect"`
CollectRegions Strings `json:"collect_regions"`
AllowEmbed Strings `json:"allow_embed"`
}
SiteSettings contains all the user-configurable settings for a site, with the exception of the domain settings.
This is stored as JSON in the database.
func (SiteSettings) CanView ¶
func (ss SiteSettings) CanView(token string) bool
func (SiteSettings) CollectFlags ¶
func (ss SiteSettings) CollectFlags(ctx context.Context) []CollectFlag
CollectFlags returns a list of all flags we know for the Collect settings.
func (*SiteSettings) Defaults ¶
func (ss *SiteSettings) Defaults(ctx context.Context)
func (SiteSettings) IsPublic ¶
func (ss SiteSettings) IsPublic() bool
func (*SiteSettings) Scan ¶
func (ss *SiteSettings) Scan(v any) error
func (SiteSettings) String ¶
func (ss SiteSettings) String() string
type Sites ¶
type Sites []Site
Sites is a list of sites.
func (*Sites) ContainsCNAME ¶
ContainsCNAME reports if there is a site with this CNAME set.
func (*Sites) ForAccount ¶ added in v2.7.0
ForAccount gets all sites associated with an account.
func (*Sites) ForThisAccount ¶
ForThisAccount gets all sites associated with this account.
func (*Sites) OldSoftDeleted ¶
OldSoftDeleted finds all sites which have been soft-deleted more than a week ago.
func (*Sites) UnscopedList ¶
UnscopedList lists all sites, not scoped to the current user.
type Strings ¶
type Strings []string
Strings stores a slice of []string as a comma-separated string.
func (Strings) MarshalText ¶
func (*Strings) UnmarshalText ¶
type System ¶
type TotalCount ¶
type TotalCount struct {
// Total number of visitors (including events).
Total int `db:"total" json:"total"`
// Total number of visitors for events.
TotalEvents int `db:"total_events" json:"total_events"`
// Total number of visitors in UTC. The browser, system, etc, stats are
// always in UTC.
TotalUTC int `db:"total_utc" json:"total_utc"`
}
func GetTotalCount ¶
func GetTotalCount(ctx context.Context, rng ztime.Range, pathFilter []PathID, noEvents bool) (TotalCount, error)
GetTotalCount gets the total number of pageviews for the selected timeview in the timezone the user configured.
This also gets the total number of pageviews for the selected time period in UTC. This is needed since the _stats tables are per day, rather than per-hour, so we need to use the correct totals to make sure the percentage calculations are accurate.
type TplEmailAddUser ¶
func (TplEmailAddUser) Render ¶
func (t TplEmailAddUser) Render() ([]byte, error)
type TplEmailExportDone ¶
func (TplEmailExportDone) Render ¶
func (t TplEmailExportDone) Render() ([]byte, error)
type TplEmailForgotSite ¶
func (TplEmailForgotSite) Render ¶
func (t TplEmailForgotSite) Render() ([]byte, error)
type TplEmailImportDone ¶
func (TplEmailImportDone) Render ¶
func (t TplEmailImportDone) Render() ([]byte, error)
type TplEmailImportError ¶
func (TplEmailImportError) Render ¶
func (t TplEmailImportError) Render() ([]byte, error)
type TplEmailPasswordReset ¶
func (TplEmailPasswordReset) Render ¶
func (t TplEmailPasswordReset) Render() ([]byte, error)
type TplEmailVerify ¶
func (TplEmailVerify) Render ¶
func (t TplEmailVerify) Render() ([]byte, error)
type TplEmailWelcome ¶
func (TplEmailWelcome) Render ¶
func (t TplEmailWelcome) Render() ([]byte, error)
type Translation ¶ added in v2.7.0
func (*Translation) ByFilename ¶ added in v2.7.0
func (t *Translation) ByFilename(ctx context.Context, filename string) error
type Translations ¶
type Translations []Translation
type User ¶
type User struct {
ID UserID `db:"user_id" json:"id,readonly"`
Site SiteID `db:"site_id" json:"site,readonly"`
Email string `db:"email" json:"email"`
EmailVerified zbool.Bool `db:"email_verified" json:"email_verified,readonly"`
Password []byte `db:"password" json:"-"`
TOTPEnabled zbool.Bool `db:"totp_enabled" json:"totp_enabled,readonly"`
TOTPSecret []byte `db:"totp_secret" json:"-"`
Access UserAccesses `db:"access" json:"access,readonly"`
LoginAt *time.Time `db:"login_at" json:"login_at,readonly"`
OpenAt *time.Time `db:"open_at" json:"open_at,readonly"`
ResetAt *time.Time `db:"reset_at" json:"reset_at,readonly"`
LoginRequest *string `db:"login_request" json:"-"`
LoginToken *string `db:"login_token" json:"-"`
Token *string `db:"csrf_token" json:"-"`
EmailToken *string `db:"email_token" json:"-"`
Settings UserSettings `db:"settings" json:"settings"`
// Keep track when the last email report was sent, so we don't double-send them.
LastReportAt time.Time `db:"last_report_at" json:"last_report_at"`
CreatedAt time.Time `db:"created_at" json:"created_at,readonly"`
UpdatedAt *time.Time `db:"updated_at" json:"updated_at,readonly"`
}
User entry.
func MustGetUser ¶
MustGetUser behaves as GetUser(), panicking if this fails.
func (User) AccessAdmin ¶
func (User) AccessSettings ¶
func (User) AccessSuperuser ¶ added in v2.2.0
func (*User) ByEmailToken ¶
ByEmailToken gets a user by email verification token.
func (*User) ByResetToken ¶
ByResetToken gets a user by login request key.
This can be used in two contexts: the user requested a password reset, or the user was invited to create a new account.
func (*User) BySiteAndEmail ¶ added in v2.7.0
ByEmail gets a user by email address for the current account.
func (*User) ByTokenAndSite ¶
ByTokenAndSite gets a user by login token.
func (User) CorrectPassword ¶
CorrectPassword verifies that this password is correct.
func (User) EmailReportRange ¶ added in v2.2.0
EmailReportRange gets the time range of the next report to send out.
user.LastReportAt is set when a report is sent; to get the range for the new report we take LastReportAt, go to the start and end of the period, and if the endDate > now then send out a new report and set LastReportAt.
The cronjob will send the report if the current date is after the end date.
func (User) EmailShort ¶ added in v2.4.0
func (User) HasAccess ¶
func (u User) HasAccess(check UserAccess) bool
HasAccess checks if this user has access to this site for the permission.
func (*User) RequestReset ¶
RequestReset generates a new password reset key.
func (*User) UpdatePassword ¶
UpdatePassword updates this user's password.
func (*User) UpdateSite ¶
UpdateSite updates this user's siteID (i.e. moves it to another site).
type UserAccess ¶
type UserAccess string
const ( AccessReadOnly UserAccess = "r" AccessSettings UserAccess = "s" AccessAdmin UserAccess = "a" AccessSuperuser UserAccess = "*" )
type UserAccesses ¶
type UserAccesses map[string]UserAccess
func (*UserAccesses) Scan ¶
func (u *UserAccesses) Scan(v any) error
Scan converts the data returned from the DB into the struct.
type UserSettings ¶
type UserSettings struct {
TwentyFourHours bool `json:"twenty_four_hours"`
SundayStartsWeek bool `json:"sunday_starts_week"`
Language string `json:"language"`
DateFormat string `json:"date_format"`
NumberFormat rune `json:"number_format"`
Timezone *tz.Zone `json:"timezone"`
Widgets Widgets `json:"widgets"`
Views Views `json:"views"`
EmailReports EmailReport `json:"email_reports"`
FewerNumbers bool `json:"fewer_numbers"`
FewerNumbersLockUntil time.Time `json:"fewer_numbers_lock_until"`
Theme string `json:"theme"`
Datepicker bool `json:"datepicker"`
}
UserSettings are all user preferences.
func (*UserSettings) Defaults ¶
func (ss *UserSettings) Defaults(ctx context.Context)
func (*UserSettings) Scan ¶
func (ss *UserSettings) Scan(v any) error
func (UserSettings) String ¶
func (ss UserSettings) String() string
type Users ¶
type Users []User
type View ¶
type View struct {
Name string `json:"name"`
Filter string `json:"filter"`
Group Group `json:"group"`
Period string `json:"period"` // "week", "week-cur", or n days: "8"
}
Views for the dashboard; these settings apply to all widget and are configurable in the yellow box at the top.
type Widget ¶
Widgets is a list of widgets to be printed, in order.
func (Widget) GetSettings ¶
func (w Widget) GetSettings(ctx context.Context) WidgetSettings
GetSettings gets all setting for this widget.
type WidgetSetting ¶
type WidgetSettings ¶
type WidgetSettings map[string]WidgetSetting
func (WidgetSettings) Display ¶
func (s WidgetSettings) Display(ctx context.Context, wname string) string
Display all values that are different from the default.
func (WidgetSettings) HasSettings ¶
func (s WidgetSettings) HasSettings() bool
HasSettings reports if there are any non-hidden settings.
func (*WidgetSettings) Set ¶
func (s *WidgetSettings) Set(k string, v any)
type Widgets ¶
type Widgets []Widget
func (*Widgets) UnmarshalJSON ¶ added in v2.2.3
This exists as a work-around because a migration set this column wrong >_<
https://github.com/arp242/goatcounter/issues/569#issuecomment-1042013488
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
goatcounter
command
|
|
|
Package cron schedules jobs.
|
Package cron schedules jobs. |
|
db
|
|
|
Package gctest contains testing helpers.
|
Package gctest contains testing helpers. |
|
pkg
|
|
|
bgrun
Package bgrun runs jobs in the background.
|
Package bgrun runs jobs in the background. |
|
geo/geoip2
Package geoip2 provides an easy-to-use API for the MaxMind GeoIP2 and GeoLite2 databases; this package does not support GeoIP Legacy databases.
|
Package geoip2 provides an easy-to-use API for the MaxMind GeoIP2 and GeoLite2 databases; this package does not support GeoIP Legacy databases. |
|
geo/maxminddb
Package maxminddb provides a reader for the MaxMind DB file format.
|
Package maxminddb provides a reader for the MaxMind DB file format. |
|
log
Package log wraps slog.
|
Package log wraps slog. |
|
metrics
Package metrics collects performance metrics.
|
Package metrics collects performance metrics. |