Documentation
¶
Overview ¶
Package stats records owner analytics from observed playback and provider data. It never reconstructs device or bandwidth information from watch counts.
Index ¶
- type Bucket
- type Cost
- type IndexerUsage
- type NewsletterSettings
- type Options
- type Play
- type Service
- func (s *Service) Close(ctx context.Context) error
- func (s *Service) Handler() http.Handler
- func (s *Service) History(ctx context.Context, since, until time.Time, user int64, limit int) ([]Play, error)
- func (s *Service) IndexerMonth(ctx context.Context) ([]IndexerUsage, error)
- func (s *Service) MaybeNewsletter(ctx context.Context) error
- func (s *Service) NewsletterSettings(ctx context.Context) (NewsletterSettings, error)
- func (s *Service) ObserveIndexer(e newznab.Event)
- func (s *Service) ObservePlayback(ev playback.Event)
- func (s *Service) ObserveState(ev state.Event)
- func (s *Service) OutboxStatus() (st store.OutboxStatus, ok bool)
- func (s *Service) Prune(ctx context.Context) (int64, error)
- func (s *Service) Record(ctx context.Context, p *core.PlaySession, ended bool, problem string) error
- func (s *Service) RecordIndexer(ctx context.Context, e newznab.Event) error
- func (s *Service) RenderNewsletter(ctx context.Context, userID int64) (string, error)
- func (s *Service) Run(ctx context.Context)
- func (s *Service) Sample(ctx context.Context)
- func (s *Service) SaveNewsletter(ctx context.Context, v NewsletterSettings) error
- func (s *Service) SetCost(ctx context.Context, c Cost) error
- func (s *Service) SnapshotProviders(ctx context.Context, ps []usenet.ProviderStats) error
- func (s *Service) Summary(ctx context.Context, since, until time.Time, user int64) (Summary, error)
- type Summary
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type IndexerUsage ¶
type IndexerUsage struct {
Indexer string `json:"indexer"`
Searches int64 `json:"searches"`
Successes int64 `json:"successes"`
Grabs int64 `json:"grabs"`
GrabSuccess int64 `json:"grabSuccess"`
Budgets int64 `json:"budgets"`
LatencyMS int64 `json:"latencyMs"`
AgeSeconds int64 `json:"ageSeconds"`
AgeSamples int64 `json:"ageSamples"`
}
type NewsletterSettings ¶
type Options ¶
type Options struct {
Newsletter func(context.Context, string) error
StopSession func(string) error
SessionExists func(string) bool
Playback core.Playback
Providers func() []usenet.ProviderStats
Indexers func(context.Context) ([]newznab.Remaining, error)
Logger *slog.Logger
Now func() time.Time
// NodeID identifies this node in a cluster. Plays are tagged with it and
// New closes only this node's unfinished plays. Empty for a standalone
// server, which therefore closes every unfinished play as before.
NodeID string
// Availability, when set (clustered nodes), holds play records the
// database cannot take through an outage (the latest per play) and
// skips periodic provider snapshots while the database is down; their
// counters are cumulative, so nothing is lost. Nil writes synchronously.
Availability *store.Availability
}
type Play ¶
type Play struct {
ID string `json:"id"`
UserID int64 `json:"userId"`
Key int64 `json:"ratingKey"`
Username string `json:"username"`
Title string `json:"title"`
Platform string `json:"platform"`
Device string `json:"device"`
Decision string `json:"decision"`
Started int64 `json:"started"`
Updated int64 `json:"updated"`
Ended int64 `json:"ended"`
Bytes int64 `json:"bytes"`
WatchedMS int64 `json:"watchedMs"`
DurationMS int64 `json:"durationMs"`
Completed bool `json:"completed"`
Failovers int `json:"failovers"`
Error string `json:"error"`
}
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
func (*Service) Close ¶
Close writes play records still held from a database outage (bounded by ctx); a no-op on a standalone server.
func (*Service) IndexerMonth ¶
func (s *Service) IndexerMonth(ctx context.Context) ([]IndexerUsage, error)
func (*Service) MaybeNewsletter ¶
MaybeNewsletter claims each weekly slot in a durable ledger before enqueueing. Queue errors remain visible and are not retried automatically, preventing duplicates after an ambiguous process interruption.
func (*Service) NewsletterSettings ¶
func (s *Service) NewsletterSettings(ctx context.Context) (NewsletterSettings, error)
func (*Service) ObserveIndexer ¶
func (*Service) ObservePlayback ¶
ObservePlayback is suitable for playback.Manager.Subscribe.
func (*Service) ObserveState ¶
ObserveState correlates timeline data only when exactly one active session matches the user/title. Plex state events do not identify the client.
func (*Service) OutboxStatus ¶
func (s *Service) OutboxStatus() (st store.OutboxStatus, ok bool)
OutboxStatus reports play records held through a database outage; ok is false on a standalone server.
func (*Service) Prune ¶
Prune deletes per-day indexer/provider counters older than dailyRetentionDays. It is meant to be called periodically.
func (*Service) Record ¶
func (s *Service) Record(ctx context.Context, p *core.PlaySession, ended bool, problem string) error
Record upserts a play. On a clustered node a record the database cannot take is held and written when it is back.
func (*Service) RecordIndexer ¶
func (*Service) RenderNewsletter ¶
func (*Service) SaveNewsletter ¶
func (s *Service) SaveNewsletter(ctx context.Context, v NewsletterSettings) error
func (*Service) SnapshotProviders ¶
type Summary ¶
type Summary struct {
Plays int64 `json:"plays"`
WatchedMS int64 `json:"watchedMs"`
Bytes int64 `json:"bytes"`
Completed int64 `json:"completed"`
Daily []Bucket `json:"daily"`
Hourly []Bucket `json:"hourly"`
Platforms []Bucket `json:"platforms"`
Titles []Bucket `json:"titles"`
Users []Bucket `json:"users"`
Since time.Time `json:"since"`
Until time.Time `json:"until"`
}