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

Rust: use tracing/tracing-subscriber for logging #18608

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

aibaars
Copy link
Contributor

@aibaars aibaars commented Jan 28, 2025

This PR changes the logging system in the Rust codebase to use the tracing and tracing-subscriber crates and configures them the same way as the Ruby extractor. In addition it adds the possibility to collect flame graph data by ssetting CODEQL_EXTRACTOR_RUST_OPTION_FLAME_LOG to a file path. The collected data can be visualised as a flame graph or chart using the inferno tool .

@github-actions github-actions bot added the Rust Pull requests that update Rust code label Jan 28, 2025
@aibaars aibaars marked this pull request as ready for review February 3, 2025 10:22
@Copilot Copilot bot review requested due to automatic review settings February 3, 2025 10:22
@aibaars aibaars requested a review from a team as a code owner February 3, 2025 10:22

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again, by re-requesting a review.

@@ -85,7 +87,7 @@ impl<'a> Extractor<'a> {
}
translator.emit_source_file(ast);
translator.trap.commit().unwrap_or_else(|err| {
log::error!(
tracing::error!(
Copy link
Contributor

Choose a reason for hiding this comment

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

very minor nit: for consistency with info and warn we should probably pull in error alongside them and just have

Suggested change
tracing::error!(
error!(

here

@@ -180,11 +182,19 @@ fn cwd() -> anyhow::Result<AbsPathBuf> {

fn main() -> anyhow::Result<()> {
let start = Instant::now();
let flame_layer = if let Ok(path) = std::env::var("CODEQL_EXTRACTOR_RUST_OPTION_FLAME_LOG") {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer this to go through the same mechanism we have for other configuration knobs, rather than a direct access to the env here:

  • adding the corresponding option to codeql-extractor.yml with docs and all
  • adding flame_log to the Config structure
  • configuring tracing after extracting said configuration

This would make it work with the whole extractor option machinery, and from the code perspective I like the invariant that all configuration goes through the Config structure, and we don't have to go hunt for other env accesses across the code.

@@ -51,7 +51,7 @@ impl<'a> RustAnalyzer<'a> {
project: &ProjectManifest,
config: &CargoConfig,
) -> Option<(RootDatabase, Vfs)> {
let progress = |t| (log::trace!("progress: {}", t));
let progress = |t| (tracing::trace!("progress: {}", t));
Copy link
Contributor

Choose a reason for hiding this comment

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

very minor nit: again we can drop the tracing namespace here provided we also pull trace in the use above

@@ -62,7 +62,7 @@ impl<'a> RustAnalyzer<'a> {
match load_workspace_at(manifest.as_ref(), config, &load_config, &progress) {
Ok((db, vfs, _macro_server)) => Some((db, vfs)),
Err(err) => {
log::error!("failed to load workspace for {}: {}", manifest, err);
tracing::error!("failed to load workspace for {}: {}", manifest, err);
Copy link
Contributor

Choose a reason for hiding this comment

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

here we can directly drop tracing:: as far as I can see (we already pull in error above)

Comment on lines +172 to +200
match severity {
DiagnosticSeverity::Debug => tracing::debug!(
"{}:{}:{}: {}",
self.path,
start.line + 1,
start.col + 1,
&full_message
),
DiagnosticSeverity::Info => tracing::info!(
"{}:{}:{}: {}",
self.path,
start.line + 1,
start.col + 1,
&full_message
),
DiagnosticSeverity::Warning => tracing::warn!(
"{}:{}:{}: {}",
self.path,
start.line + 1,
start.col + 1,
&full_message
),
DiagnosticSeverity::Error => tracing::error!(
"{}:{}:{}: {}",
self.path,
start.line + 1,
start.col + 1,
&full_message
),
Copy link
Contributor

Choose a reason for hiding this comment

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

you can avoid all this duplication by using tracing::Level and replacing the old log:log! with tracing:event!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried, but that does not seem to be possible. See also: tokio-rs/tracing#2730

Copy link
Contributor

Choose a reason for hiding this comment

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

ah, I see. Too bad :/

Comment on lines +30 to +42
/// Create a `Subscriber` configured with the tracing level based on the environment variables
/// `RUST_LOG` and `CODEQL_VERBOSITY` (prioritized in that order), falling back to `warn` if neither is set.
pub fn default_subscriber_with_level(
language: &str,
) -> Filtered<
tracing_subscriber::fmt::Layer<
tracing_subscriber::Registry,
DefaultFields,
Format<tracing_subscriber::fmt::format::Full, ()>,
>,
EnvFilter,
tracing_subscriber::Registry,
> {
Copy link
Contributor

Choose a reason for hiding this comment

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

hmm, this bypasses our own current numerical env we use for this CODEQL_RUST_EXTRACTOR_VERBOSE or CODEQL_RUST_EXTRACTOR_OPTION_VERBOSE, which I would prefer to keep (AFAIK CODEQL_VERBOSITY is not a generic codeql cli setting, so actually I think the env extractor namespacing should be used, although admittedly verbosity is still not enrolled in our codeql-extractor.yml file).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this is the same behaviour as the "tree-sitter" based extractors use.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm ok with moving from the integer verbose level input to the verbosity string input, but I would still prefer for it to go through the rest of the Config/extractor option machinery for Rust. Could you maybe:

  • have a codeql_verbosity: Option<&str> or similar type parameter here, instead of taking it directly from the env
  • in the set_tracing_level function, pass std::env("CODEQL_VERBOSITY") so we preserve the same behaviour for other extractor
  • in rust, add a verbosity string extractor option
  • in rust, replace verbose: u8 with verbosity: Option<String> in the Config structure, and pass that to default_subscriber_with_level
  • that would cover CODEQL_EXTRACTOR_RUST_VERBOSITY or CODEQL_EXTRACTOR_RUST_OPTION_VERBOSITY (including passing it via -overbosity). If we also want CODEQL_VERBOSITY, that can be added to the config extraction (maybe it is already?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Rust Pull requests that update Rust code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants