Documentation
¶
Overview ¶
Package statuspage builds the opt-in public status page: component probing, 90-day uptime bars, operator-authored incidents and the whitelisted public view. Nothing beyond View is ever published.
Index ¶
- Constants
- func OverallStatus(statuses []string) string
- func RenderAtom(v View, baseURL string) ([]byte, error)
- func RenderBadge(label, state string) []byte
- func RenderHTML(v View) ([]byte, error)
- func RenderHistory(v View, tab string, page, size int) ([]byte, error)
- func RenderIncident(v View, id string) (body []byte, ok bool, err error)
- func RenderMarkdownLite(src string) template.HTML
- func RenderRSS(v View, baseURL string) ([]byte, error)
- func StatusText(s string) string
- type AppSource
- type ComponentView
- type Config
- type DayView
- type DomainSource
- type IncidentView
- type Service
- func (s *Service) Enabled(ctx context.Context) (bool, error)
- func (s *Service) History(ctx context.Context) (View, error)
- func (s *Service) Invalidate()
- func (s *Service) PreviewView(ctx context.Context) (View, error)
- func (s *Service) Run(ctx context.Context) error
- func (s *Service) Sample(ctx context.Context) error
- func (s *Service) SetWindows(w WindowSource)
- func (s *Service) View(ctx context.Context) (View, error)
- type Store
- type Tuning
- type UpdateView
- type View
- type WindowSource
Constants ¶
const ( PagePath = "/public/status" SummaryPath = "/public/status.json" FeedPath = "/public/status.rss" AtomPath = "/public/status.atom" HistoryPath = "/public/status/history" BadgePath = "/public/status/badge.svg" IncidentDir = "/public/status/incidents/" )
FeedPath and SummaryPath are the public asset paths, relative to the page.
const ( DefaultSampleInterval = time.Minute DefaultCacheTTL = 30 * time.Second DefaultCheckTimeout = 8 * time.Second )
Defaults for Config, overridable via environment in cmd/levelrail.
const ( Operational = "operational" Degraded = "degraded" Outage = "outage" Maintenance = "maintenance" Unknown = "unknown" NoData = "nodata" )
Component and overall statuses.
const ( KindApp = "app" KindDomain = "domain" KindCheck = "check" )
Component kinds.
const ( IncidentKind = "incident" MaintenanceKind = "maintenance" StatusInvestigating = "investigating" StatusIdentified = "identified" StatusMonitoring = "monitoring" StatusResolved = "resolved" StatusScheduled = "scheduled" StatusInProgress = "in_progress" StatusCompleted = "completed" ImpactNone = "none" ImpactMinor = "minor" ImpactMajor = "major" ImpactCritical = "critical" )
Incident kinds, statuses and impacts.
const UptimeDays = 90
UptimeDays is the number of daily bars on the page.
Variables ¶
This section is empty.
Functions ¶
func OverallStatus ¶
OverallStatus folds component statuses into one headline status.
func RenderAtom ¶
RenderAtom renders incidents and maintenance as an Atom 1.0 feed. baseURL is the page's own origin, e.g. "https://status.example.com".
func RenderBadge ¶
RenderBadge renders a flat two-part SVG badge. Both texts are escaped and only fixed colours are used, so no input reaches the markup raw.
func RenderHistory ¶
RenderHistory renders one page of the incident and maintenance archive. tab is "all", "incidents" or "maintenance"; page counts from 1.
func RenderIncident ¶
RenderIncident renders the permalink page for one incident or maintenance entry. ok is false when the ID is unknown.
func RenderMarkdownLite ¶
RenderMarkdownLite converts operator text to safe HTML. All input is escaped first; only paragraphs, line breaks, "- " lists, **bold**, `code` and http(s) links are then re-introduced.
func RenderRSS ¶
RenderRSS renders incidents and maintenance as an RSS 2.0 feed with plain-text descriptions. baseURL is the page's own origin, e.g. "https://status.example.com".
func StatusText ¶
StatusText is the human headline for an overall status.
Types ¶
type ComponentView ¶
type ComponentView struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Group string `json:"group,omitempty"`
Status string `json:"status"`
Uptime90 *float64 `json:"uptime_90d"`
Days []DayView `json:"days"`
}
ComponentView is one component as the public sees it.
type Config ¶
type Config struct {
SampleInterval time.Duration
CacheTTL time.Duration
CheckTimeout time.Duration
Parallelism int
}
Config tunes sampling and caching; zero values take the defaults.
type DayView ¶
type DayView struct {
Date string `json:"date"`
Status string `json:"status"`
Uptime *float64 `json:"uptime,omitempty"`
// Level scales the bar colour 1..4 by the day's weighted downtime share.
Level int `json:"level,omitempty"`
}
DayView is one uptime bar.
type DomainSource ¶
type DomainSource interface {
CheckDomainStatus(ctx context.Context, domain string) (string, error)
}
DomainSource is the existing DNS domain check.
type IncidentView ¶
type IncidentView struct {
ID string `json:"id"`
Title string `json:"title"`
Status string `json:"status"`
Impact string `json:"impact"`
StartsAt time.Time `json:"starts_at"`
EndsAt *time.Time `json:"ends_at,omitempty"`
ResolvedAt *time.Time `json:"resolved_at,omitempty"`
Components []string `json:"components,omitempty"`
Updates []UpdateView `json:"updates"`
// Ongoing marks maintenance with no end time yet.
Ongoing bool `json:"ongoing,omitempty"`
}
IncidentView is an incident or maintenance announcement.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service samples component health and builds the public View.
func New ¶
New builds a Service. apps and domains may be nil, in which case components of that kind report unknown.
func (*Service) History ¶
History returns the view with the full archive window of incidents and maintenance, cached like View.
func (*Service) Invalidate ¶
func (s *Service) Invalidate()
Invalidate drops the cached view so the next read reflects a management change.
func (*Service) PreviewView ¶
PreviewView builds an uncached view regardless of the enabled flag, for the management UI.
func (*Service) Sample ¶
Sample probes every component once and records the result. It does nothing while the page is disabled.
func (*Service) SetWindows ¶
func (s *Service) SetWindows(w WindowSource)
SetWindows adds scheduled maintenance windows to the public view.
type Store ¶
type Store interface {
GetStatusPageSettings(ctx context.Context) (store.StatusPageSettings, error)
ListStatusComponents(ctx context.Context) ([]store.StatusComponent, error)
ListStatusGroups(ctx context.Context) ([]store.StatusGroup, error)
AddStatusSamples(ctx context.Context, componentID, day string, ok, degraded, down int) error
ListStatusDaily(ctx context.Context, sinceDay string) ([]store.StatusDaily, error)
PruneStatusDaily(ctx context.Context, beforeDay string) error
ListStatusIncidents(ctx context.Context, limit int) ([]store.StatusIncident, error)
ListStatusIncidentUpdates(ctx context.Context) ([]store.StatusIncidentUpdate, error)
}
Store is what Service reads and writes. *store.DB satisfies it.
type Tuning ¶
type Tuning struct {
DegradedWeight float64 // APP_STATUS_DEGRADED_WEIGHT: downtime weight of a degraded sample, 0..1
AboutMax int // APP_STATUS_ABOUT_MAX: about text length cap
DescriptionMax int // APP_STATUS_DESCRIPTION_MAX: component description length cap
GroupNameMax int // APP_STATUS_GROUP_NAME_MAX
GroupsMax int // APP_STATUS_GROUPS_MAX
LogoURLMax int // APP_STATUS_LOGO_URL_MAX
HistoryPage int // APP_STATUS_HISTORY_PAGE_SIZE: entries per history page
HistoryDays int // APP_STATUS_HISTORY_DAYS: archive depth
}
Tuning holds every operator-adjustable limit and weight of the page. Each field reads one APP_STATUS_* variable; the defaults are documented in docs/status-page.md.
func TuningFromEnv ¶
func TuningFromEnv() Tuning
TuningFromEnv reads the knobs, falling back to the defaults for unset or invalid values.
type UpdateView ¶
type UpdateView struct {
Status string `json:"status"`
Body string `json:"body"`
At time.Time `json:"at"`
}
UpdateView is one timeline entry.
type View ¶
type View struct {
Title string `json:"title"`
Description string `json:"description,omitempty"`
Status string `json:"status"`
StatusText string `json:"status_text"`
GeneratedAt time.Time `json:"generated_at"`
Accent string `json:"accent,omitempty"`
LogoURL string `json:"logo_url,omitempty"`
About string `json:"about,omitempty"`
Website string `json:"website,omitempty"`
NoIndex bool `json:"noindex,omitempty"`
PoweredBy bool `json:"powered_by"`
Components []ComponentView `json:"components"`
Incidents []IncidentView `json:"incidents"`
Maintenance []IncidentView `json:"maintenance"`
}
View is the entire public payload. Every field is deliberate: a privacy test fails when one is added without updating its whitelist.
type WindowSource ¶
type WindowSource interface {
ListMaintenanceWindows(ctx context.Context, since time.Time) ([]store.MaintenanceWindow, error)
}
WindowSource lists one-off maintenance windows. *store.DB satisfies it.