Documentation
¶
Overview ¶
Package drain computes the fleet's parked-drain metrics from the persisted vehicle_state history and exposes them to Prometheus (D1, the instrument for the battery-drain experiment's Gate A).
Everything is derived from rows the recorder already writes; nothing here talks to Rivian, so computing it can't wake a car. The definitions match the ones already in use, so the gauges, the analysis queries and the Sleep chart agree:
- Parked drain (%/day): SoC lost over consecutive sample pairs where the car is parked (gear P or unknown, under 1 mph, not charging) at both ends, less than 24 h apart, with the odometer still (< 0.2 mi) and SoC moving less than 3 points (a bigger jump is an unrecorded charge or a calibration step, not drain). 24 × ΣΔSoC / Σhours. This is devils-advocate's D3 query.
- Idle-awake (h/day): hours awake while parked and not charging, per 24 h of recorded power state. Intervals are capped at 20 min and attributed to the state at their start, as in samples.SleepActivity.
- Sleeps: a sleep runs from the first 'sleep' sample after a non-sleep one to the next non-sleep sample. A quick re-wake is a sleep that lasted under 60 s (the sleep gate's failed sleep). A sleep counts in the window it ended in; one whose start is before the window, or which hasn't ended, isn't counted.
Index ¶
Constants ¶
const ( Window24h = "24h" Window7d = "7d" )
Windows the metrics are computed over.
const DefaultInterval = 15 * time.Minute
DefaultInterval is how often Run recomputes. The windows are 24 h and 7 d, so a quarter hour of lag is invisible; one fleet query per interval is cheap.
Variables ¶
This section is empty.
Functions ¶
func ParseInterval ¶
ParseInterval reads RIVOLT_DRAIN_METRICS_INTERVAL: empty means DefaultInterval; "0", "off" or "false" disable the metrics (ok = false); anything else is a Go duration, at least a minute. An unparsable value falls back to the default and returns the error for the caller to log.
Types ¶
type Collector ¶
type Collector struct {
// contains filtered or unexported fields
}
Collector serves the last computed snapshot to Prometheus. Run refreshes it; scrapes never touch the database. Series for a vehicle with no rows in the last 7 days disappear on the next refresh.
func NewCollector ¶
func NewCollector() *Collector
NewCollector returns a Collector with no data yet.
func (*Collector) Collect ¶
func (c *Collector) Collect(ch chan<- prometheus.Metric)
Collect implements prometheus.Collector.
func (*Collector) Describe ¶
func (c *Collector) Describe(ch chan<- *prometheus.Desc)
Describe implements prometheus.Collector.
func (*Collector) Run ¶
func (c *Collector) Run(ctx context.Context, db *sql.DB, interval time.Duration, logger *slog.Logger)
Run recomputes now and then every interval until ctx is done. A failed recompute keeps the previous snapshot (its last-success timestamp ages, which is what to alert on) and logs a warning.
type Stat ¶
type Stat struct {
VehicleID string // Rivian vehicle id, as in the logs
Window string // Window24h | Window7d
// ParkedHours is the parked time the drain rate is measured over.
ParkedHours float64
// DrainPctPerDay is nil when ParkedHours is under the window's
// minimum.
DrainPctPerDay *float64
// ObservedHours is the time with a recorded power state.
ObservedHours float64
// IdleAwakeHPerDay is nil when ObservedHours is under the minimum.
IdleAwakeHPerDay *float64
Sleeps int
QuickRewakes int
// MedianSleep is nil when no sleep ended in the window.
MedianSleep *time.Duration
}
Stat is one vehicle's metrics over one window.