Skip to content

Conversation

@flyingsilverfin
Copy link
Member

@flyingsilverfin flyingsilverfin commented Oct 22, 2025

Usage and product changes

Rather than having Python/Java/other wrappers invoke logging initialization explicitly, we now just do it on open of the Rust driver automatically.

This should fix warnings in Python:

Failed to initialize logging: attempted to set a logger after the logging system was already initialized

We also remove uses of the log create in the //c layer, and use tracing instead.

We can now configure logging in the Rust-driver component with the following variables: TYPEDB_DRIVER_LOG=info|debug|warn|trace or using the usual RUST_LOG variable. By default, ffi-based drivers calling init_logging will use INFO logging.

Rust applications should continue set up their own logging subscriber, as usual.

Implementation

Remove C-layer static logging initialization, and rely on just the Rust driver's once lock that is execute on driver open.

@flyingsilverfin flyingsilverfin changed the title Fix c layer init logging Implicitly execute logging initialization Oct 22, 2025
@flyingsilverfin flyingsilverfin changed the title Implicitly execute logging initialization Implicitly init Rust-driver logging Oct 22, 2025
@flyingsilverfin flyingsilverfin marked this pull request as ready for review October 28, 2025 20:41
@flyingsilverfin flyingsilverfin changed the title Implicitly init Rust-driver logging Set up configurable FFI/Rust driver logging Oct 28, 2025
Comment on lines +51 to +64
let clib_level = if let Ok(typedb_driver_clib_log) = std::env::var("TYPEDB_DRIVER_CLIB_LOG") {
typedb_driver_clib_log
} else {
"info".to_owned()
};
// Try to get log level from TYPEDB_DRIVER_LOG first
let env_filter = if let Ok(typedb_log_level) = std::env::var("TYPEDB_DRIVER_LOG") {
EnvFilter::new(&format!("typedb_driver={},typedb_driver_clib={}", typedb_log_level, clib_level))
} else if let Ok(rust_log) = std::env::var("RUST_LOG") {
// If RUST_LOG is set, use it but scope it to typedb_driver only
EnvFilter::new(&format!("typedb_driver={},typedb_driver_clib={}", rust_log, clib_level))
} else {
EnvFilter::new(&format!("typedb_driver=info,typedb_driver_clib={}", clib_level))
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be made simpler.

Suggested change
let clib_level = if let Ok(typedb_driver_clib_log) = std::env::var("TYPEDB_DRIVER_CLIB_LOG") {
typedb_driver_clib_log
} else {
"info".to_owned()
};
// Try to get log level from TYPEDB_DRIVER_LOG first
let env_filter = if let Ok(typedb_log_level) = std::env::var("TYPEDB_DRIVER_LOG") {
EnvFilter::new(&format!("typedb_driver={},typedb_driver_clib={}", typedb_log_level, clib_level))
} else if let Ok(rust_log) = std::env::var("RUST_LOG") {
// If RUST_LOG is set, use it but scope it to typedb_driver only
EnvFilter::new(&format!("typedb_driver={},typedb_driver_clib={}", rust_log, clib_level))
} else {
EnvFilter::new(&format!("typedb_driver=info,typedb_driver_clib={}", clib_level))
};
let clib_level = std::env::var("TYPEDB_DRIVER_CLIB_LOG").unwrap_or_else(|_| "info".to_owned());
let typedb_log_level = std::env::var("TYPEDB_DRIVER_LOG")
.or_else(|_| std::env::var("RUST_LOG"))
.unwrap_or_else(|_| "info".to_owned());
let env_filter = EnvFilter::new(&format!("typedb_driver={},typedb_driver_clib={}", typedb_log_level, clib_level));

Comment on lines +59 to +62
} else if let Ok(rust_log) = std::env::var("RUST_LOG") {
// If RUST_LOG is set, use it but scope it to typedb_driver only
EnvFilter::new(&format!("typedb_driver={},typedb_driver_clib={}", rust_log, clib_level))
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if RUST_LOG is set to e.g. tonic=trace?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should look for TYPEDB_DRIVER_CLIB_LOG_LEVEL and TYPEDB_DRIVER_LOG_LEVEL. We can then use RUST_LOG to initialize the EnvFilter and add the two log levels (if set) as directives. If nothing is set, then we can fall back to info on both our libs.

This way, RUST_LOG=tonic=info,typedb_driver=error will work as expected and will not get overridden to typedb_driver=info by us unnecessarily.

Comment on lines +67 to +68
if let Err(e) =
tracing_subscriber::registry().with(env_filter).with(tracing_fmt::layer().with_target(false)).try_init()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why registry and not Subscriber::buiilder?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants