Documentation
¶
Overview ¶
Package monitor watches what a vhost's models are asked and answer. It keeps a sampled, masked log of predictions in the log store, and measures drift: how far each feature's live values have moved from the rows the model version was trained on (the worker's feature_stats), as a population stability index per feature.
Nothing here may slow or fail a prediction. Observe copies what it needs and hands it to a bounded queue without blocking; a full queue drops the observation and counts it. Masking, counting, writing and alerting all run on the one goroutine Run starts.
Drift is counted in memory, per Hermod process, over every prediction that process makes (not only the logged sample), in tumbling windows: at each tick of Config.Window a model's window is judged if it holds at least Config.MinRows rows, and a new one starts. Several Hermod processes each judge their own traffic; their hermod_ml_feature_drift series carry the scrape's instance label, and the drift API answers for the process that serves it. Merging counts across processes through storage was left out: the default deployment runs the API and the workflow engine in one process, where this is all the traffic there is.
Index ¶
- Constants
- type Config
- type Deps
- type FeatureDrift
- type Monitor
- func (m *Monitor) Forget(vhost, model string)
- func (m *Monitor) MinRows() int
- func (m *Monitor) Observe(o Observation)
- func (m *Monitor) OnDrift(fn func(Report))
- func (m *Monitor) Recommendations(vhost, model string) (RecommendationReport, bool)
- func (m *Monitor) Report(vhost, model string) (Report, bool)
- func (m *Monitor) Run(ctx context.Context)
- func (m *Monitor) Window() time.Duration
- type NotifyFunc
- type Observation
- type RecommendationCall
- type RecommendationReport
- type Report
- type StatsFunc
Constants ¶
const ( StatusOK = "ok" StatusWarn = "warn" StatusAlert = "alert" )
Drift statuses, per feature and for a whole report.
const ( DefaultWindow = 5 * time.Minute DefaultMinRows = 100 )
Defaults of Config.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Window is how often drift is judged; MinRows how many predicted rows a
// window needs before it is.
Window time.Duration
MinRows int
// Queue bounds the observations waiting for the monitor's goroutine.
Queue int
// Batch and Flush bound how many logged rows wait to be written, and for
// how long.
Batch int
Flush time.Duration
}
Config sizes the monitor. Zero values are the defaults.
func ConfigFromEnv ¶
func ConfigFromEnv() Config
ConfigFromEnv reads HERMOD_ML_DRIFT_WINDOW (a Go duration) and HERMOD_ML_DRIFT_MIN_ROWS. A value that does not read is left to the default.
type Deps ¶
type Deps struct {
// Logs returns the current log store; one that is not a
// storage.MLPredictionLogStore drops logged rows, counted.
Logs func() any
Stats StatsFunc
Notify NotifyFunc
Logger hermod.Logger
}
Deps are what the monitor reads from and reports to.
type FeatureDrift ¶
type FeatureDrift struct {
Feature string `json:"feature"`
Kind string `json:"kind"`
// PSI is the population stability index of the live values against the
// training split, over the training bins plus one bin for missing values.
PSI float64 `json:"psi"`
Status string `json:"status"`
// NullFraction and TrainingNullFraction are the share of missing values
// live and in training, the commonest drift there is.
NullFraction float64 `json:"null_fraction"`
TrainingNullFraction float64 `json:"training_null_fraction"`
}
FeatureDrift is how far one feature's live values have moved from the values the model was trained on.
type Monitor ¶
type Monitor struct {
// contains filtered or unexported fields
}
Monitor is safe for concurrent use. The zero value is not usable; a nil *Monitor ignores every observation.
func (*Monitor) Observe ¶
func (m *Monitor) Observe(o Observation)
Observe hands one prediction call to the monitor. It never blocks: when the queue is full the call is dropped and counted.
func (*Monitor) OnDrift ¶
OnDrift adds fn to what is called with every drift report, whatever its status, once per judged window. It is the hook a retraining policy uses; fn runs on the monitor's goroutine and must not block.
func (*Monitor) Recommendations ¶
func (m *Monitor) Recommendations(vhost, model string) (RecommendationReport, bool)
Recommendations returns the latest report of a recommendation model.
type NotifyFunc ¶
NotifyFunc raises an alert for a report whose status is StatusAlert.
type Observation ¶
type Observation struct {
// Model is the model as it was called: its live version, features and
// monitoring settings.
Model storage.MLModel
CallerKind string
CallerID string
// Inputs and Outputs are the rows sent and the predictions returned, in
// the same order.
Inputs []map[string]any
Outputs []map[string]any
Latency time.Duration
At time.Time
// Recommendation is set for a call of a recommendation model, which is
// watched by coverage and popular share rather than drift
// (recommendations.go).
Recommendation *RecommendationCall
}
Observation is one prediction call as the caller made it.
type RecommendationCall ¶
type RecommendationCall struct {
// Items are the ids it answered.
Items []string
// Fallback reports that the person or item was unknown, so the answer is
// the popular items.
Fallback bool
// Catalog is how many items the model can recommend.
Catalog int
}
RecommendationCall is one call of a recommendation model, for Observation.
type RecommendationReport ¶
type RecommendationReport struct {
VHost string `json:"vhost"`
Model string `json:"model"`
Version string `json:"version"`
WindowStart time.Time `json:"window_start"`
WindowEnd time.Time `json:"window_end"`
// Calls is how many calls the window holds; Fallbacks how many were
// answered with popular items.
Calls int64 `json:"calls"`
Fallbacks int64 `json:"fallbacks"`
PopularShare float64 `json:"popular_share"`
// Recommended is how many distinct items were recommended, of Catalog;
// Coverage is the share.
Recommended int `json:"recommended"`
Catalog int `json:"catalog"`
Coverage float64 `json:"coverage"`
}
RecommendationReport is one window of a recommendation model's calls.
type Report ¶
type Report struct {
VHost string `json:"vhost"`
Model string `json:"model"`
Version string `json:"version"`
WindowStart time.Time `json:"window_start"`
WindowEnd time.Time `json:"window_end"`
// Rows is how many predicted rows the window holds.
Rows int64 `json:"rows"`
Warn float64 `json:"warn"`
Alert float64 `json:"alert"`
// Status is the worst of the features'.
Status string `json:"status"`
// Features are ordered most drifted first.
Features []FeatureDrift `json:"features"`
}
Report is the drift of one model version over one window of predictions.