drain

package
v0.32.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: MIT Imports: 8 Imported by: 0

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

View Source
const (
	Window24h = "24h"
	Window7d  = "7d"
)

Windows the metrics are computed over.

View Source
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

func ParseInterval(v string) (d time.Duration, ok bool, err error)

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.

func (*Collector) Set

func (c *Collector) Set(stats []Stat, at time.Time, took time.Duration)

Set replaces the snapshot. Run calls it; tests use it directly.

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.

func Compute

func Compute(ctx context.Context, db *sql.DB, now time.Time) ([]Stat, error)

Compute returns every vehicle's stats for the 24 h and 7 d windows ending at now, two per vehicle with any rows in the last 7 days. It reads across all users (the app role owns the tables).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL