Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support dynamic updates of the log level #139

Merged
merged 2 commits into from
Jan 10, 2025

Conversation

DavisVaughan
Copy link
Collaborator

Closes #134

dynamic.mov

Comment on lines +165 to +211
/// Log state managed by the LSP
///
/// This state allows for dynamically updating the log level at runtime using [`reload`].
///
/// It works using an `RwLock` that's only ever locked by us inside `self.handle.reload()`,
/// this seems to be fast enough even though atomics are checked at every log call site.
/// Notably we only lock if the new log levels are actually different, which is important
/// since we call [`reload`] when ANY configuration changes.
pub(crate) struct LogState {
handle: LogReloadHandle,

/// The log level as provided by the client, before any extra processing is done.
/// Used to check if an update is required.
log_level: Option<LogLevel>,

/// The dependency log levels as provided by the client, before any extra processing is done
/// Used to check if an update is required.
dependency_log_levels: Option<String>,
}

impl LogState {
pub(crate) fn reload(
&mut self,
log_level: Option<LogLevel>,
dependency_log_levels: Option<String>,
) {
if (self.log_level == log_level) && (self.dependency_log_levels == dependency_log_levels) {
// Nothing changed
return;
}

let (filter, message) = log_filter(log_level, dependency_log_levels.clone());

match self.handle.reload(filter) {
Ok(()) => {
// Update to match the new filter
tracing::info!("{message}");
self.log_level = log_level;
self.dependency_log_levels = dependency_log_levels;
}
Err(error) => {
// Log and return without updating our internal log level
tracing::error!("Failed to update log level: {error}");
}
}
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is the core bit of it, pretty nice!

Comment on lines +170 to +171
/// State used to dynamically update the log level
pub(crate) log_state: Option<logging::LogState>,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm excited to move to lsp-server because I think the startup procedure there will result in us creating GlobalState / LspState after we've received InitializeParams, meaning we will be able to get rid of Option<>s here and in GlobalState

Comment on lines -235 to +240
let (log_state, log_tx) = LogState::new(client.clone());
let (log_thread_state, log_tx) = LogThreadState::new(client.clone());
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Just a rename so we can use LogState for the bit that holds the reload handle

This thread state thing will also eventually go away in lsp-server world

@DavisVaughan DavisVaughan requested a review from lionel- January 9, 2025 20:32
@DavisVaughan DavisVaughan merged commit b862591 into main Jan 10, 2025
5 checks passed
@DavisVaughan DavisVaughan deleted the feature/dynamic-log-level branch January 10, 2025 16:47
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.

Make logLevel and dependencyLogLevels dynamic
2 participants