pub struct EmbeddedAnalytics { /* private fields */ }Expand description
The embedded analytics store (DW-043): SQLite file + bounded
channel + background writer. Rollup/retention workers are spawned
by EmbeddedAnalytics::spawn_workers.
Implementations§
Source§impl EmbeddedAnalytics
impl EmbeddedAnalytics
Sourcepub fn open(
path: &str,
retention_ms: [i64; 5],
flush_ms: u64,
prompt_log_retention_ms: i64,
sampled_degradation: Option<SampledDegradation>,
) -> Result<Arc<Self>>
pub fn open( path: &str, retention_ms: [i64; 5], flush_ms: u64, prompt_log_retention_ms: i64, sampled_degradation: Option<SampledDegradation>, ) -> Result<Arc<Self>>
Open (or create) the analytics database at path, apply
migrations, and return the store with its channel wired. The
writer is NOT started here — see
EmbeddedAnalytics::spawn_workers. prompt_log_retention_ms
is the DW-081 prompt log retention window (0 = no sweep).
Sourcepub fn spawn_workers(
self: &Arc<Self>,
shutdown: Receiver<()>,
) -> Vec<JoinHandle<()>>
pub fn spawn_workers( self: &Arc<Self>, shutdown: Receiver<()>, ) -> Vec<JoinHandle<()>>
Spawn the writer and rollup/retention workers. Exactly one set
per store (the receiver is taken once; a second call returns an
empty set and logs). Both stop on shutdown; the writer drains
what is already queued first, then performs a final rollup and
retention pass so a clean restart loses nothing.
Sourcepub fn dropped_records(&self) -> u64
pub fn dropped_records(&self) -> u64
Records accepted by record but dropped (channel full). The
honest loss counter for the never-block posture.
Sourcepub fn dropped_sampled_records(&self) -> u64
pub fn dropped_sampled_records(&self) -> u64
REL-10 (#221): records dropped by sampled degradation (the
probabilistic pre-full drop). Counted separately from
Self::dropped_records so an operator can distinguish “channel
was full” from “sampling kicked in to avoid filling the channel”.
Sourcepub fn query<T>(&self, f: impl FnOnce(&Connection) -> Result<T>) -> Result<T>
pub fn query<T>(&self, f: impl FnOnce(&Connection) -> Result<T>) -> Result<T>
Run a short locked access against the store’s connection (the admin read path, and the exports ledger’s single-row record writes). The connection is shared with the writer behind one mutex; access is sized for the “week under 100 ms” contract, so contention is short and rare.
Sourcepub fn backup_to(&self, dest_path: &str) -> Result<()>
pub fn backup_to(&self, dest_path: &str) -> Result<()>
REL-13 (#224): back up the analytics database to dest_path
using SQLite’s online backup API. The backup is a consistent
snapshot taken under the connection mutex (the writer is
briefly blocked). The destination file is created or
overwritten.
Sourcepub fn restore_from(&self, src_path: &str) -> Result<()>
pub fn restore_from(&self, src_path: &str) -> Result<()>
REL-13 (#224): restore the analytics database from src_path.
The source file is opened and its contents are copied into the
live connection via the online backup API. The writer is
briefly blocked under the connection mutex. After restore, the
in-memory state (live sketches, insights) is NOT reset — they
continue from their current window.
Sourcepub fn record(&self, rec: &AccessRecord)
pub fn record(&self, rec: &AccessRecord)
The request-completion hot path (DW-043): fire-and-forget record
of one finished request. NEVER blocks — a bounded-channel
try_send that drops and counts on full. DW-092: also feeds the
live in-process sketches (synchronous, lock-free counts + a
short mutex over a capped sample vector) when attached.
Sourcepub fn set_live_sketches(&self, sketches: Arc<LiveSketches>)
pub fn set_live_sketches(&self, sketches: Arc<LiveSketches>)
Attach the live sketches (DW-092). Called once during startup
wiring (dwara-bin) when analytics.live_sketches.enabled. The
insights engine, when also configured, is attached to the
sketches so window rotations feed it.
Sourcepub fn set_insights(&self, engine: Arc<InsightsEngine>)
pub fn set_insights(&self, engine: Arc<InsightsEngine>)
Attach the insights engine (DW-092). Called once during startup
wiring when analytics.insights.forecast or
analytics.insights.anomaly_baseline. Also wired into the live
sketches so window rotations feed the engine.
Sourcepub fn live_sketches(&self) -> Option<Arc<LiveSketches>>
pub fn live_sketches(&self) -> Option<Arc<LiveSketches>>
The live sketches store when attached (DW-092; None = the
GET /analytics/live endpoint answers
analytics_not_configured).
Sourcepub fn insights_engine(&self) -> Option<Arc<InsightsEngine>>
pub fn insights_engine(&self) -> Option<Arc<InsightsEngine>>
The insights engine when attached (DW-092; None = the
GET /analytics/forecast and GET /analytics/anomalies
endpoints answer analytics_not_configured).
Sourcepub fn live_snapshot(&self) -> Option<LiveSnapshot>
pub fn live_snapshot(&self) -> Option<LiveSnapshot>
Snapshot the current live window (DW-092). Returns None when live sketches are not attached.
Sourcepub fn insights_forecast(&self) -> Option<ForecastResult>
pub fn insights_forecast(&self) -> Option<ForecastResult>
Forecast the next window (DW-092). Returns None when the insights engine is not attached or forecasting is disabled.
Sourcepub fn insights_detect_anomaly(&self) -> Option<AnomalyResult>
pub fn insights_detect_anomaly(&self) -> Option<AnomalyResult>
Detect whether the current live window is anomalous (DW-092).
Builds a BaselineWindow from the current live snapshot and
hands it to the insights engine. Returns None when the insights
engine is not attached or anomaly detection is disabled.
Sourcepub fn offer_ai_spend(&self, rec: AiSpendRecord)
pub fn offer_ai_spend(&self, rec: AiSpendRecord)
The AI spend hot path (DW-079): fire-and-forget record of one
completed AI request’s spend dimensions. NEVER blocks — a
bounded-channel try_send that drops and counts on full (the
same never-block posture as Self::record).
Sourcepub fn dropped_spend_records(&self) -> u64
pub fn dropped_spend_records(&self) -> u64
AI spend records accepted by Self::offer_ai_spend but dropped
(channel full). The honest loss counter for the DW-079 path.
Sourcepub fn offer_ai_governance_event(&self, rec: AiGovernanceEvent)
pub fn offer_ai_governance_event(&self, rec: AiGovernanceEvent)
The AI governance event hot path (DW-084): fire-and-forget
record of one governance check outcome. NEVER blocks — a
bounded-channel try_send that drops and counts on full (the
same never-block posture as Self::offer_ai_spend).
Sourcepub fn dropped_governance_events(&self) -> u64
pub fn dropped_governance_events(&self) -> u64
AI governance events accepted by
Self::offer_ai_governance_event but dropped (channel full).
The honest loss counter for the DW-084 path.
Sourcepub fn offer_ai_prompt_log(&self, rec: AiPromptLogRecord)
pub fn offer_ai_prompt_log(&self, rec: AiPromptLogRecord)
The AI prompt log hot path (DW-081): fire-and-forget record of
one captured prompt/response pair (already redacted). NEVER
blocks — a bounded-channel try_send that drops and counts on
full (the same never-block posture as
Self::offer_ai_governance_event).
Sourcepub fn dropped_prompt_log_records(&self) -> u64
pub fn dropped_prompt_log_records(&self) -> u64
AI prompt log records accepted by Self::offer_ai_prompt_log
but dropped (channel full). The honest loss counter for the
DW-081 path.
Sourcepub fn set_prompt_log_retention_ms(&self, retention_ms: i64)
pub fn set_prompt_log_retention_ms(&self, retention_ms: i64)
Update the prompt log retention window (DW-081). Called on reload when the logging config changes. A retention of 0 disables the sweep.
Sourcepub fn offer_ai_experiment_assignment(&self, rec: AiExperimentAssignment)
pub fn offer_ai_experiment_assignment(&self, rec: AiExperimentAssignment)
The experiment assignment hot path (DW-086): fire-and-forget
record of one A/B test variant selection. NEVER blocks — a
bounded-channel try_send that drops and counts on full.
Sourcepub fn dropped_exp_assign_records(&self) -> u64
pub fn dropped_exp_assign_records(&self) -> u64
Experiment assignment records accepted but dropped (channel full). The honest loss counter for the DW-086 assignment path.
Sourcepub fn offer_ai_eval_result(&self, rec: AiEvalResultRecord)
pub fn offer_ai_eval_result(&self, rec: AiEvalResultRecord)
The eval result path (DW-086): fire-and-forget record of one
eval case result. NEVER blocks — a bounded-channel try_send
that drops and counts on full.
Sourcepub fn dropped_eval_result_records(&self) -> u64
pub fn dropped_eval_result_records(&self) -> u64
Eval result records accepted but dropped (channel full).
Sourcepub fn offer_ai_feedback(&self, rec: AiFeedbackRecord)
pub fn offer_ai_feedback(&self, rec: AiFeedbackRecord)
The feedback path (DW-086): fire-and-forget record of one
feedback entry. NEVER blocks — a bounded-channel try_send
that drops and counts on full.
Sourcepub fn dropped_feedback_records(&self) -> u64
pub fn dropped_feedback_records(&self) -> u64
Feedback records accepted but dropped (channel full).
Sourcepub fn offer_mcp_tool_call(&self, rec: McpToolCallRecord)
pub fn offer_mcp_tool_call(&self, rec: McpToolCallRecord)
The MCP tool call hot path (DW-087): fire-and-forget record of
one proxied tool call. NEVER blocks — a bounded-channel
try_send that drops and counts on full.
Sourcepub fn dropped_mcp_tool_call_records(&self) -> u64
pub fn dropped_mcp_tool_call_records(&self) -> u64
MCP tool call records accepted but dropped (channel full). The honest loss counter for the DW-087 path.
Trait Implementations§
Source§impl AnalyticsSink for EmbeddedAnalytics
The M1 extension contract (feature analysis 11.4): the embedded
store IS an extensions::analytics::AnalyticsSink. The trait’s
failure model allows perpetual Ok — “accepted”, not “persisted” —
which is exactly the drop-and-count policy here (a full channel is
the sink’s own overload to absorb, not the caller’s problem).
impl AnalyticsSink for EmbeddedAnalytics
The M1 extension contract (feature analysis 11.4): the embedded
store IS an extensions::analytics::AnalyticsSink. The trait’s
failure model allows perpetual Ok — “accepted”, not “persisted” —
which is exactly the drop-and-count policy here (a full channel is
the sink’s own overload to absorb, not the caller’s problem).
Auto Trait Implementations§
impl !Freeze for EmbeddedAnalytics
impl RefUnwindSafe for EmbeddedAnalytics
impl Send for EmbeddedAnalytics
impl Sync for EmbeddedAnalytics
impl Unpin for EmbeddedAnalytics
impl UnwindSafe for EmbeddedAnalytics
Blanket Implementations§
§impl<T> AnyExt for T
impl<T> AnyExt for T
§fn downcast_ref<T>(this: &Self) -> Option<&T>where
T: Any,
fn downcast_ref<T>(this: &Self) -> Option<&T>where
T: Any,
T behind reference§fn downcast_mut<T>(this: &mut Self) -> Option<&mut T>where
T: Any,
fn downcast_mut<T>(this: &mut Self) -> Option<&mut T>where
T: Any,
T behind mutable reference§fn downcast_rc<T>(this: Rc<Self>) -> Result<Rc<T>, Rc<Self>>where
T: Any,
fn downcast_rc<T>(this: Rc<Self>) -> Result<Rc<T>, Rc<Self>>where
T: Any,
T behind Rc pointer§fn downcast_arc<T>(this: Arc<Self>) -> Result<Arc<T>, Arc<Self>>where
T: Any,
fn downcast_arc<T>(this: Arc<Self>) -> Result<Arc<T>, Arc<Self>>where
T: Any,
T behind Arc pointer§fn downcast_box<T>(this: Box<Self>) -> Result<Box<T>, Box<Self>>where
T: Any,
fn downcast_box<T>(this: Box<Self>) -> Result<Box<T>, Box<Self>>where
T: Any,
T behind Box pointer§fn downcast_move<T>(this: Self) -> Option<T>
fn downcast_move<T>(this: Self) -> Option<T>
Self to T,
useful only in generic context as a workaround for specializationSource§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T, X> CoerceTo<T> for Xwhere
T: CoerceFrom<X> + ?Sized,
impl<T, X> CoerceTo<T> for Xwhere
T: CoerceFrom<X> + ?Sized,
fn coerce_rc_to(self: Rc<X>) -> Rc<T>
fn coerce_box_to(self: Box<X>) -> Box<T>
fn coerce_ref_to(&self) -> &T
fn coerce_mut_to(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more