Logging
Learn how to configure logging and tracing in SlateDB
Tracing in SlateDB
Section titled “Tracing in SlateDB”SlateDB uses the tracing library for logging and diagnostics. This provides structured, contextual logging that helps debug and monitor your database operations.
Here’s a basic example showing how to consume tracing logs with tracing_subscriber and SlateDB:
use slatedb::{bytes::Bytes, object_store::memory::InMemory, Db};use std::sync::Arc;
#[tokio::main]async fn main() -> anyhow::Result<()> { // Initialize tracing subscriber to see the logs tracing_subscriber::fmt::init();
// Setup let object_store = Arc::new(InMemory::new()); let db = Db::open("/tmp/slatedb_tracing_subscriber", object_store).await?;
// Put let key = b"test_key"; let value = b"test_value"; db.put(key, value).await?;
// Get assert_eq!(db.get(key).await?, Some(Bytes::from_static(value)));
// Delete db.delete(key).await?; assert!(db.get(key).await?.is_none());
// Close db.close().await?;
Ok(())}Tracing Read Operation
Section titled “Tracing Read Operation”SlateDB provides structured tracing spans for read operations, allowing you to track and measure the performance of individual reads. When enabled, SlateDB creates a hierarchy of spans that wrap different parts of the read path:
| Span | Description | Fields |
|---|---|---|
slatedb.read | Root span for a read operation (get, scan, or scan_prefix_by_recency). | trace_id |
slatedb.read.memtable | Records each memtable lookup. | trace_id |
slatedb.read.read_filters | Records reading filters for an SST. | trace_id, sst_id, sst_level, cached |
slatedb.read.evaluate_filter | Records evaluating a named filter for an SST. | trace_id, sst_id, sst_level, filter_name, result |
slatedb.read.read_index | Records reading the index for an SST. | trace_id, sst_id, sst_level, cached |
All slatedb.read.* spans are child spans of the root slatedb.read span.
Field meanings:
trace_id— The value fromTracingOptions, used to correlate spans from the same read operation.sst_id— The identifier of the SST involved in the span.sst_level: The level that contains the SST isl0orsorted_run:{id}.cached:trueif the filter or index came from the cache or a concurrent cache lookup fetched it. Otherwise, the value isfalse. The field can be absent if the read stops before the filter or index is read.filter_name: The name of the filter policy being evaluated.result— The boolean result of evaluating the filter.
These spans are only created when you provide TracingOptions to the read operation.
All spans listed above are created at tracing level INFO, except for slatedb.read.memtable.
Due to the potential huge number of spans slatedb.read.memtable created during scan operations, slatedb.read.memtable spans are created at tracing level DEBUG.
Configuring TracingOptions
Section titled “Configuring TracingOptions”Read operations (get, scan, scan_prefix_by_recency) can be traced by passing TracingOptions via the corresponding options struct. Use ReadOptions::with_tracing_options() for point reads and ScanOptions::with_tracing_options() for scans.
The trace_id field in TracingOptions allows you to correlate spans of the same read operation.
Here’s an example of enabling tracing for a get operation:
use slatedb::config::{ReadOptions, TracingOptions};use slatedb::{bytes::Bytes, object_store::memory::InMemory, Db};use std::sync::Arc;use tracing_chrome::{ChromeLayerBuilder, TraceStyle};use tracing_subscriber::filter::LevelFilter;use tracing_subscriber::layer::SubscriberExt;use tracing_subscriber::Layer;
#[tokio::main]async fn main() -> anyhow::Result<()> { // Setup let object_store = Arc::new(InMemory::new()); let db = Db::open("/tmp/slatedb_tracing_subscriber", object_store).await?;
// Put let key = b"test_key"; let value = b"test_value"; db.put(key, value).await?;
// Create tracing options with a custom trace ID let tracing_options = TracingOptions::new("my-trace-id");
// Pass it to the read operation let read_options = ReadOptions::default().with_tracing_options(Some(tracing_options));
// Register tracing-chrome subscriber. // Subscriber tracing-chrome outputs traces in Chrome’s trace viewer format. // The generated file `trace-<unix timestamp>` with the traces can be found in // the root directory of the project. Dump that file into // https://ui.perfetto.dev/ to visualize the spans. let (chrome_layer, _chrome_guard) = ChromeLayerBuilder::new() .include_args(true) .trace_style(TraceStyle::Async) .build(); let subscriber = tracing_subscriber::registry().with(chrome_layer.with_filter(LevelFilter::DEBUG)); let _subscriber_guard = tracing::subscriber::set_default(subscriber);
//Get let result = db.get_with_options(key, &read_options).await?; assert_eq!(result, Some(Bytes::from_static(value)));
// Close db.close().await?;
Ok(())}