Documentation
¶
Overview ¶
Package requestlog persists a queryable record of every outbound request forge-dashboard makes to GitHub or Forgejo (#482), so a rate-limit or connectivity incident can be debugged from what actually happened on the wire instead of from stdout logs alone. internal/github and internal/forgejo each depend on this package's Recorder — the one interface both clients need identically, so it lives here rather than being duplicated per client, the same way internal/dashboard already holds RateLimiter/RepoRefresher for the equivalent shared-dependency shape.
Index ¶
Constants ¶
const MaxEntries = 10000
MaxEntries is the row-count retention cap SQLiteRecorder enforces on every write — trimmed on insert rather than swept on a schedule, so storage never grows past this regardless of how bursty traffic gets.
const OutcomeSuccess = "success"
OutcomeSuccess is Entry.Outcome's value for a request that completed successfully. Any other value is a dashboard.ForgeErrorKind string.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Entry ¶
type Entry struct {
ID int64
LoggedAt time.Time
Forge dashboard.Forge
AccountID string // "" when no per-account credential made this request
Method string
Endpoint string
// StatusCode is 0 when the request never got a response at all.
StatusCode int
// Outcome is OutcomeSuccess or a dashboard.ForgeErrorKind string.
Outcome string
// RateLimitLimit/RateLimitRemaining/RateLimitResetsAt/RateLimitCost
// are all nil when the response carried no rate-limit fields —
// not every request reports these.
RateLimitLimit *int
RateLimitRemaining *int
RateLimitResetsAt *time.Time
RateLimitCost *int
}
Entry is one outbound request's own record.
type Filter ¶
Filter narrows a listing to entries matching every set field — a zero Filter (both fields empty) matches everything.
type NoopRecorder ¶
type NoopRecorder struct{}
NoopRecorder discards every Entry — what a forge client falls back to when constructed with no Recorder at all, so every existing caller and test keeps compiling and passing unchanged.
type Option ¶ added in v0.132.5
type Option func(*SQLiteRecorder)
Option configures a SQLiteRecorder.
func WithWriter ¶ added in v0.132.5
WithWriter sends Record's rows through w's bounded queue and single writer instead of writing inline (#902). Record then never waits on the database and never fails; a full queue drops the row and counts it.
type Recorder ¶
Recorder is what internal/github and internal/forgejo depend on to persist an Entry for every outbound request they make. A Record error never changes the outbound request's own result — see NoopRecorder and each client's own call site, which logs it via slog.Warn and otherwise ignores it: logging a request is diagnostic, not part of what the request itself promises to do.
type RowStore ¶ added in v0.132.5
type RowStore interface {
RecordRequest(ctx context.Context, row auth.RequestLogRow, maxEntries int) error
}
RowStore is what the Writer persists rows into. *auth.Store satisfies it.
type SQLiteRecorder ¶
type SQLiteRecorder struct {
// contains filtered or unexported fields
}
SQLiteRecorder is the concrete Recorder every forge client is wired up with — it persists into internal/auth.Store's own request_log table (the same SQLite database auth/session data already lives in, per design.md's "reuse what's already there" decision) rather than standing up a second storage mechanism for one more record type.
It's scoped to one account: SQLiteRecorder is constructed once per signed-in user (wherever that user's forge clients are built — see cmd/forge-dashboard's buildSourcesForUser), and every Entry it records carries that account's own ID regardless of what the caller set on Entry.AccountID — the account whose credential made a request is a property of *which client made it*, not something each individual client call site needs to know or pass through.
func NewSQLiteRecorder ¶
func NewSQLiteRecorder(store *auth.Store, accountID string, opts ...Option) *SQLiteRecorder
NewSQLiteRecorder returns a SQLiteRecorder that persists into store, stamping every recorded Entry with accountID.
type Writer ¶ added in v0.132.5
type Writer struct {
// contains filtered or unexported fields
}
Writer is the one place request-log rows are written from (#902). Each outbound forge request used to write its own row inline, so a locked database left one goroutine, and one OS thread, waiting per request for up to the busy timeout. Now callers enqueue and move on; a single goroutine does the writing, and a full queue drops the row and counts it rather than blocking a request.