Begin statement execution logging from the frontend. (Corresponds to `Coordinator::begin_statement_execution`, which is used by the old peek sequencing.) This encapsulates all the statement logging setup: - Retrieves system config values - Performs sampling and throttling checks - Creates statement logging records - Attends to metrics. Returns None if the statement should not be logged (due to s
(
&self,
session: &mut Session,
params: &Params,
logging: &Arc<QCell<PreparedStatementLoggingInfo>>,
system_config: &SystemVars,
lifecycle_timestamps: O
| 573 | /// The `Option<PreparedStatementEvent>` is None when we have already logged the prepared |
| 574 | /// statement before, and this is just a subsequent execution. |
| 575 | pub fn begin_statement_execution( |
| 576 | &self, |
| 577 | session: &mut Session, |
| 578 | params: &Params, |
| 579 | logging: &Arc<QCell<PreparedStatementLoggingInfo>>, |
| 580 | system_config: &SystemVars, |
| 581 | lifecycle_timestamps: Option<LifecycleTimestamps>, |
| 582 | ) -> Option<( |
| 583 | StatementLoggingId, |
| 584 | StatementBeganExecutionRecord, |
| 585 | Row, |
| 586 | Option<PreparedStatementEvent>, |
| 587 | )> { |
| 588 | // Skip logging for internal users unless explicitly enabled |
| 589 | let enable_internal_statement_logging = system_config.enable_internal_statement_logging(); |
| 590 | if session.user().is_internal() && !enable_internal_statement_logging { |
| 591 | return None; |
| 592 | } |
| 593 | |
| 594 | let sample_rate = effective_sample_rate(session, system_config); |
| 595 | |
| 596 | let use_reproducible_rng = system_config.statement_logging_use_reproducible_rng(); |
| 597 | let target_data_rate: Option<u64> = system_config |
| 598 | .statement_logging_target_data_rate() |
| 599 | .map(|rate| rate.cast_into()); |
| 600 | let max_data_credit: Option<u64> = system_config |
| 601 | .statement_logging_max_data_credit() |
| 602 | .map(|credit| credit.cast_into()); |
| 603 | |
| 604 | // Only lock the RNG when we actually need reproducible sampling (tests only) |
| 605 | let sample = if use_reproducible_rng { |
| 606 | let mut rng = self.reproducible_rng.lock().expect("rng lock poisoned"); |
| 607 | should_sample_statement(sample_rate, Some(&mut *rng)) |
| 608 | } else { |
| 609 | should_sample_statement(sample_rate, None) |
| 610 | }; |
| 611 | |
| 612 | let sampled_label = sample.then_some("true").unwrap_or("false"); |
| 613 | session |
| 614 | .metrics() |
| 615 | .statement_logging_records(&[sampled_label]) |
| 616 | .inc_by(1); |
| 617 | |
| 618 | // Clone only the metrics needed below, before the mutable borrow of session. |
| 619 | let unsampled_bytes_metric = session |
| 620 | .metrics() |
| 621 | .statement_logging_unsampled_bytes() |
| 622 | .clone(); |
| 623 | let actual_bytes_metric = session.metrics().statement_logging_actual_bytes().clone(); |
| 624 | |
| 625 | // Handle the accounted flag and record byte metrics |
| 626 | let is_new_prepared_statement = if let Some((sql, accounted)) = |
| 627 | match session.qcell_rw(logging) { |
| 628 | PreparedStatementLoggingInfo::AlreadyLogged { .. } => None, |
| 629 | PreparedStatementLoggingInfo::StillToLog { sql, accounted, .. } => { |
| 630 | Some((sql, accounted)) |
| 631 | } |
| 632 | } { |
no test coverage detected