Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions crates/core/src/host/instance_env.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::scheduler::{get_schedule_from_row, ScheduleError, Scheduler};
use crate::database_logger::{BacktraceProvider, LogLevel, Record};
use crate::database_logger::{BacktraceFrame, BacktraceProvider, LogLevel, ModuleBacktrace, Record};
use crate::db::relational_db::{MutTx, RelationalDB};
use crate::error::{DBError, DatastoreError, IndexError, NodesError};
use crate::host::wasm_common::TimingSpan;
Expand Down Expand Up @@ -191,10 +191,23 @@ impl InstanceEnv {
}

/// End a console timer by logging the span at INFO level.
pub(crate) fn console_timer_end(&self, span: &TimingSpan, function: Option<&str>, bt: &dyn BacktraceProvider) {
pub(crate) fn console_timer_end(&self, span: &TimingSpan, function: Option<&str>) {
let elapsed = span.start.elapsed();
let message = format!("Timing span {:?}: {:?}", &span.name, elapsed);

/// A backtrace provider that provides nothing.
struct Noop;
impl BacktraceProvider for Noop {
fn capture(&self) -> Box<dyn ModuleBacktrace> {
Box::new(Noop)
}
}
impl ModuleBacktrace for Noop {
fn frames(&self) -> Vec<BacktraceFrame<'_>> {
Vec::new()
}
}

let record = Record {
ts: chrono::Utc::now(),
target: None,
Expand All @@ -203,7 +216,7 @@ impl InstanceEnv {
function,
message: &message,
};
self.console_log(LogLevel::Info, &record, bt);
self.console_log(LogLevel::Info, &record, &Noop);
}

/// Project `cols` in `row_ref` encoded in BSATN to `buffer`
Expand Down
13 changes: 13 additions & 0 deletions crates/core/src/host/wasm_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ impl TimingSpan {
decl_index!(TimingSpanIdx => TimingSpan);
pub(super) type TimingSpanSet = ResourceSlab<TimingSpanIdx>;

/// Converts a [`NodesError`] to an error code, if possible.
pub fn err_to_errno(err: &NodesError) -> Option<NonZeroU16> {
match err {
NodesError::NotInTransaction => Some(errno::NOT_IN_TRANSACTION),
Expand All @@ -362,6 +363,18 @@ pub fn err_to_errno(err: &NodesError) -> Option<NonZeroU16> {
}
}

/// Converts a [`NodesError`] to an error code and logs, if possible.
pub fn err_to_errno_and_log<C: From<u16>>(func: AbiCall, err: NodesError) -> anyhow::Result<C> {
let Some(errno) = err_to_errno(&err) else {
return Err(AbiRuntimeError { func, err }.into());
};
log::debug!(
"abi call to {func} returned an errno: {errno} ({})",
errno::strerror(errno).unwrap_or("<unknown>")
);
Ok(errno.get().into())
}

#[derive(Debug, thiserror::Error)]
#[error("runtime error calling {func}: {err}")]
pub struct AbiRuntimeError {
Expand Down
5 changes: 5 additions & 0 deletions crates/core/src/host/wasm_common/instrumentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,8 @@ impl CallTimes {
std::mem::replace(self, Self::new())
}
}

#[cfg(not(feature = "spacetimedb-wasm-instance-env-times"))]
pub use noop as span;
#[cfg(feature = "spacetimedb-wasm-instance-env-times")]
pub use op as span;
45 changes: 11 additions & 34 deletions crates/core/src/host/wasmtime/wasm_instance_env.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,20 @@
#![allow(clippy::too_many_arguments)]

use std::num::NonZeroU32;
use std::time::Instant;

use super::{Mem, MemView, NullableMemOp, WasmError, WasmPointee, WasmPtr};
use crate::database_logger::{BacktraceFrame, BacktraceProvider, ModuleBacktrace, Record};
use crate::host::instance_env::{ChunkPool, InstanceEnv};
use crate::host::wasm_common::instrumentation;
use crate::host::wasm_common::instrumentation::{span, CallTimes};
use crate::host::wasm_common::module_host_actor::ExecutionTimings;
use crate::host::wasm_common::{
err_to_errno, instrumentation::CallTimes, AbiRuntimeError, RowIterIdx, RowIters, TimingSpan, TimingSpanIdx,
TimingSpanSet,
};
use crate::host::wasm_common::{err_to_errno_and_log, RowIterIdx, RowIters, TimingSpan, TimingSpanIdx, TimingSpanSet};
use crate::host::AbiCall;
use anyhow::Context as _;
use spacetimedb_data_structures::map::IntMap;
use spacetimedb_lib::Timestamp;
use spacetimedb_primitives::{errno, ColId};
use std::num::NonZeroU32;
use std::time::Instant;
use wasmtime::{AsContext, Caller, StoreContextMut};

use super::{Mem, MemView, NullableMemOp, WasmError, WasmPointee, WasmPtr};

#[cfg(not(feature = "spacetimedb-wasm-instance-env-times"))]
use instrumentation::noop as span;
#[cfg(feature = "spacetimedb-wasm-instance-env-times")]
use instrumentation::op as span;

/// A stream of bytes which the WASM module can read from
/// using [`WasmInstanceEnv::bytes_source_read`].
///
Expand Down Expand Up @@ -301,20 +291,11 @@ impl WasmInstanceEnv {
}

fn convert_wasm_result<T: From<u16>>(func: AbiCall, err: WasmError) -> RtResult<T> {
Err(match err {
WasmError::Db(err) => match err_to_errno(&err) {
Some(errno) => {
log::debug!(
"abi call to {func} returned an errno: {errno} ({})",
errno::strerror(errno).unwrap_or("<unknown>")
);
return Ok(errno.get().into());
}
None => anyhow::Error::from(AbiRuntimeError { func, err }),
},
WasmError::BufferTooSmall => return Ok(errno::BUFFER_TOO_SMALL.get().into()),
WasmError::Wasm(err) => err,
})
match err {
WasmError::Db(err) => err_to_errno_and_log(func, err),
WasmError::BufferTooSmall => Ok(errno::BUFFER_TOO_SMALL.get().into()),
WasmError::Wasm(err) => Err(err),
}
}

/// Call the function `run` with the name `func`.
Expand Down Expand Up @@ -1332,12 +1313,8 @@ impl WasmInstanceEnv {
let Some(span) = caller.data_mut().timing_spans.take(TimingSpanIdx(span_id)) else {
return Ok(errno::NO_SUCH_CONSOLE_TIMER.get().into());
};

let function = caller.data().log_record_function();
caller
.data()
.instance_env
.console_timer_end(&span, function, &caller.as_context());
caller.data().instance_env.console_timer_end(&span, function);
Ok(0)
})
}
Expand Down
Loading