Documentation
¶
Overview ¶
Package deploytimeline folds the sources that describe one deploy (the attempt row, pipeline trace, gate events, probes, hook runs, build log and request metrics) into one ordered list of events, the same shape for a live stream and for a frozen replay.
Index ¶
- Constants
- func CutoverAt(gate []store.DeployGateEvent, trace []store.DeployTraceStep) (time.Time, bool)
- func Settled(in Inputs) bool
- type Comparison
- type Config
- type Event
- type Impact
- type ImpactDelta
- type Inputs
- type Kind
- type LogLine
- type Phase
- type PhaseDelta
- type PhaseSpan
- type Status
- type Timeline
- type TriggerInfo
- type Verdict
- type Window
Constants ¶
const ( EnvRetention = "APP_DEPLOY_TIMELINE_RETENTION" EnvMaxLogLines = "APP_DEPLOY_TIMELINE_MAX_LOG_LINES" EnvImpactWindow = "APP_DEPLOY_TIMELINE_IMPACT_WINDOW" EnvActorWindow = "APP_DEPLOY_TIMELINE_ACTOR_WINDOW" EnvSettleIdle = "APP_DEPLOY_TIMELINE_SETTLE_IDLE" )
Environment variables that tune the timeline. Each has a fallback so an unset variable never disables the feature.
Variables ¶
This section is empty.
Functions ¶
func CutoverAt ¶
func CutoverAt(gate []store.DeployGateEvent, trace []store.DeployTraceStep) (time.Time, bool)
CutoverAt returns when traffic moved to the new release, from the gate timeline first and the pipeline trace otherwise.
Types ¶
type Comparison ¶
type Comparison struct {
A Timeline `json:"a"`
B Timeline `json:"b"`
Phases []PhaseDelta `json:"phases"`
// OnlyA and OnlyB list event codes seen in one deploy and not the other,
// which is where a crashloop or a rollback shows up.
OnlyA []string `json:"only_a"`
OnlyB []string `json:"only_b"`
Impact *ImpactDelta `json:"impact,omitempty"`
}
Comparison puts two timelines next to each other. Delta is B minus A.
type Config ¶
type Config struct {
Retention time.Duration
MaxLogLines int
ImpactWindow time.Duration
ActorWindow time.Duration
SettleIdle time.Duration
}
Config is the resolved tuning for one process.
type Event ¶
type Event struct {
ID string `json:"id"`
At time.Time `json:"at"`
Kind Kind `json:"kind"`
Phase Phase `json:"phase"`
Status Status `json:"status"`
Code string `json:"code"`
Title string `json:"title"`
Detail string `json:"detail,omitempty"`
Reason string `json:"reason,omitempty"`
Service string `json:"service,omitempty"`
Stream string `json:"stream,omitempty"`
DurationMS int64 `json:"duration_ms,omitempty"`
Trigger *TriggerInfo `json:"trigger,omitempty"`
Impact *Impact `json:"impact,omitempty"`
}
Event is one entry on the timeline. ID is stable for the same underlying fact, so a stream can send an event again only when its content changed.
type Impact ¶
type Impact struct {
CutoverAt time.Time `json:"cutover_at"`
WindowMS int64 `json:"window_ms"`
Complete bool `json:"complete"`
Before Window `json:"before"`
After Window `json:"after"`
}
Impact compares request health just before and just after cutover.
type ImpactDelta ¶
type ImpactDelta struct {
ErrorRate5xx float64 `json:"error_rate_5xx"`
P95Ms float64 `json:"p95_ms"`
RatePerSec float64 `json:"rate_per_sec"`
}
ImpactDelta is how the traffic shift differs between the two deploys.
type Inputs ¶
type Inputs struct {
Attempt store.DeployAttempt
Trace []store.DeployTraceStep
Gate []store.DeployGateEvent
Probes []store.ProbeAttempt
Hooks []store.HookRun
Logs []LogLine
// Actor and ActorKind come from the audit trail when it matched.
Actor string
ActorKind string
Impact *Impact
// WatchOpen is true while the post-deploy watch can still trip.
WatchOpen bool
Now time.Time
Config Config
}
Inputs are the raw sources for one deploy. Any of them may be empty: a deploy that never built has no log, one without a safety gate has no gate events.
type Kind ¶
type Kind string
Kind groups events for rendering. The UI picks an icon per kind.
const ( KindTrigger Kind = "trigger" KindBuild Kind = "build" KindLog Kind = "log" KindPush Kind = "image_push" KindHook Kind = "hook" KindStep Kind = "step" KindProbe Kind = "readiness" KindCutover Kind = "cutover" KindWatch Kind = "watch" KindRollback Kind = "rollback" KindOutcome Kind = "outcome" KindTraffic Kind = "traffic_impact" )
Event kinds.
type Phase ¶
type Phase string
Phase is the coarse stage an event belongs to; compare aligns on it.
const ( PhaseTrigger Phase = "trigger" PhaseBuild Phase = "build" PhasePush Phase = "push" PhaseHooks Phase = "hooks" PhaseDeploy Phase = "deploy" PhaseReadiness Phase = "readiness" PhaseCutover Phase = "cutover" PhaseWatch Phase = "watch" PhaseOutcome Phase = "outcome" )
Phases, in the order a deploy moves through them.
type PhaseDelta ¶
type PhaseDelta struct {
Phase Phase `json:"phase"`
AMS *int64 `json:"a_ms,omitempty"`
BMS *int64 `json:"b_ms,omitempty"`
DeltaMS *int64 `json:"delta_ms,omitempty"`
}
PhaseDelta lines up one phase of two deploys. A side is nil when that deploy never reached the phase.
type PhaseSpan ¶
type PhaseSpan struct {
Phase Phase `json:"phase"`
StartedAt time.Time `json:"started_at"`
EndedAt time.Time `json:"ended_at"`
DurationMS int64 `json:"duration_ms"`
}
PhaseSpan is the time one phase took.
type Timeline ¶
type Timeline struct {
DeployID string `json:"deploy_id"`
App string `json:"app"`
Verdict Verdict `json:"verdict"`
Live bool `json:"live"`
Frozen bool `json:"frozen"`
FrozenAt *time.Time `json:"frozen_at,omitempty"`
StartedAt time.Time `json:"started_at"`
FinishedAt *time.Time `json:"finished_at,omitempty"`
Trigger TriggerInfo `json:"trigger"`
Events []Event `json:"events"`
Phases []PhaseSpan `json:"phases"`
Impact *Impact `json:"impact,omitempty"`
// LogsDropped counts build log lines left out to respect the line cap.
LogsDropped int `json:"logs_dropped,omitempty"`
}
Timeline is the whole story of one deploy.
type TriggerInfo ¶
type TriggerInfo struct {
Source string `json:"source"`
Actor string `json:"actor,omitempty"`
ActorKind string `json:"actor_kind,omitempty"`
Branch string `json:"branch,omitempty"`
CommitSHA string `json:"commit_sha,omitempty"`
CommitMessage string `json:"commit_message,omitempty"`
Author string `json:"author,omitempty"`
RerunOf string `json:"rerun_of,omitempty"`
}
TriggerInfo says who or what started the deploy.
type Window ¶
type Window struct {
From time.Time `json:"from"`
To time.Time `json:"to"`
HasTraffic bool `json:"has_traffic"`
Requests float64 `json:"requests"`
RatePerSec float64 `json:"rate_per_sec"`
ErrorRate5xx float64 `json:"error_rate_5xx"`
P95Ms float64 `json:"p95_ms"`
}
Window is request health over one slice of time.