-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
[Proposal] [Next] Query Logging Improvements #942
Comments
I'm thinking we can change how much we log based on the log level set for At
At
At
Thanks to |
Looks great, thanks for coming with this up.
If I've understood the current proposal right, sqlx query verbosity changes depending on the If you think that might make sense, consider keeping the log level just the log level and add some kind of == |
I didn't think of slow query logging when I wrote that out but yeah, it should definitely include the parameters so it's possible to repro the slowdown. So the slow query log at
That's hard cause like, what arbitrary number is acceptable? What about for a slow-query log? Then you'd probably want all the parameters for reproducibility. Perhaps for slow-query logging we should have an option to dump the full query data with the complete SQL and all parameters to a file or some other sink. |
I like the ideas for INFO and TRACE, but I don't think printing parameters is a good idea. It has the potential for injecting PII into logs. |
True, but it could come in handy for reproducing slow queries. Instead of changing output for /// Log query arguments (values substituted into value placeholders, i.e. `$N` / `?`).
///
/// ### Note: Beware of Personally Identifiable Information
/// This will likely expose personally identifiable information (PII), or otherwise infringe on privacy of users
//// (which may be protected by law), if the logs are submitted to third-party providers like Sentry, Firebase, etc.
///
/// Take care when enabling this option.
pub fn log_arguments(&mut self, log_args: bool) -> &mut Self As suggested in my previous comment, maybe we don't want to lean directly on |
@abonander big agree on the 2nd point. Personally I strongly dislike that the query is formatted at all -- we're losing valuable information in the logs! The original, unaltered string can have a lot of interesting hints at the cause of a problem that are simply being thrown away irrecoverably. I could always pipe the query through an sql formatter from vim if I really cared about it being pretty - taking that hit at runtime seems pointless. The query formatter it's running now is doing a full tokenization, which is so much more expensive than the remove-the-indent bit you suggest. |
I presume, you have to do the same for
So, putting all formats and queries together, did I get you right:
? For me, it's
Thus said, I still would have preferred something like But the choice is yours after all, I won't insist on this point of view much 🙂 |
I think you can either make it configurable, or just pick some arbitrary number (100?) and recommend to log the full log for all parameters. Parameters' value inflate with their quantity drastically: 1-10 params can be valuable, but what about 1843, especially when they are displayed detached from the main query? :)
Great ideas in general, not sure if feasible to implement right away. I like the idea to try and be as failsafe as possible for the end user, but not sure it's possible in general to predict everything and log the query in the best possible format, keeping this whole shebang configurable might be just enough. |
I'm also +1 for making query logging configurable, perhaps as an option when building the sqlx Connection, with some sensible default. Probably we would want two parameters, one to configure the standard log level (defaults to either off or the short summary) and one to configure the slow query log level (defaults to the short summary). |
Let's take a step back here and go survey how other large SQL frameworks do this. Rails, Django, etc. There must be some inspiration on what works well to draw from. |
It would be nice if We'd prefer this stuff in our honeycomb traces. I turn all the default "info" stuff from SQLx down to "debug" because it's not useful enough in production. |
I just wanted to echo the request to change these logs from |
The log level can already be customized (and had its default changed) on |
|
I just published a new patch version of sqlformat that removes the regex dependency. Does this help? |
Yes it does! Thanks a lot. |
I'd suggest adding the ability to entirely disable logging of the actual query and print just a warning message with the line number when a query is slow, as this would be useful for very large queries. I use large batch insert queries that max out the number of placeholders, and formatting these to log causes my inserts to take about thirty times longer in debug builds and around three times longer in release. It chews up quite a lot of CPU in the process compared to the non-logging insertions (which are mainly I/O bound.) |
Yeah, I think I tend to agree cause I personally don't really pay attention at all to the queries being logged, it just adds noise. And if you're running in, say, Gcloud, you pay by the byte for log storage so noise isn't just annoying but can be costly too. Learned that the hard way recently. With |
I don't think libraries should tailor their log output to very specific use cases like that when there is the option to just set the log level per module in RUST_LOG. Primarily logging all queries should be something enabled in development and when trying to trace specific bugs only anyway. |
Just want to express a +1 for the original proposal which makes the My company is running a Of all the dependencies we have, sqlx is the only one where we had to adjust the log level because it was too verbose. I think this is probably the case for most people, and therefore that by default the INFO logs should print a relatively short, single-line log at most. My company ended up disabling |
Agree and same situation than @MaxFangX at my company |
Beyond a discussion of how to format the logs, I would like to propose that any logging of the happy and typical path be reduced to
Because of this, even with filtering, every database access unnecessarily incurs an extra atomic load and a boolean equality check in release builds. |
I recently developed an API with rust (Poem with Seaql which uses sqlx underneath), |
As the original author of the log implementation, and after having used this for a while in production... I am +1 for moving the normal, happy-path logs to DEBUG level. It does add quite a bit of noise, and the comments I've seen about performance are valid as well. |
I don't filter DEBUG in production so I won't get any performance benefit from this change. Perhaps could set the level behind a feature flag or compile time env var, so that at least we have the choice for what works best for us? on a separate note, I have slow query logging enabled, and the output looks like this:
If the log event emits the SQL anyway, could we use the space where it prints a snippet of the SQL ( |
I would like to adjust the log levels of full queries to TRACE. Is it possible to make this configurable? Furthermore, I propose setting slow queries to WARN level instead. It might be useful to have the "slow" interval as a configurable parameter, with a default setting of around 100ms. |
https://docs.rs/sqlx/latest/sqlx/trait.ConnectOptions.html#tymethod.log_statements
https://docs.rs/sqlx/latest/sqlx/trait.ConnectOptions.html#tymethod.log_slow_statements |
So currently I am passing a connection string into |
There is; you can parse it from the string and modify it in-place: // Using the standard `FromStr` trait and `str::parse()` method
let mut opts: PgConnectOptions = "<your database URL>".parse()?;
opts.log_statements(...);
let pool = pool_options.connect_with(&opts).await?; |
That's what I was missing, thank you so much! 💖 |
How to log full sql in unit test ? |
A lot of people will probably agree with me when I say there's room for improvement with how we currently log queries.
Logging is very noisy because we always print the whole query at INFO. I think at most we should be printing at
INFO
is the source file and line of the query (which we can do with#[track_caller]
andstd::panic::Location::caller()
), maybe the first couple keywords in the query as context, and the time the query took. We should only be logging the full query (with parameters interpolated) at TRACE.Logging is expensive because we pretty-print the SQL. I think we shouldn't be doing nearly that much to it. At most, we should be removing excess indentation so the query isn't weirdly left-padded in logs. I think
sqlformat
can help us there instead of rolling it ourselves. (cc @shssoichiro)It doesn't make sense for
ConnectOptions::{log_statements, log_slow_statements}
to take alog::LevelFilter
; instead, it should beOption<log::Level>
. Then, if someone is using a crate liketracing
that includeslog
but doesn't want to uselog
directly, they can still disable query logging by passingNone
(Add a way to disable query logging programmatically #939).(Bug) we don't actually obey the log-level setting forDone: fix(logging): make query logging obey level setting forsqlx::query
, only the global log setting. This doesn't need to be innext
, though; I'll be fixing it shortly.sqlx::query
target #945The text was updated successfully, but these errors were encountered: