-
Notifications
You must be signed in to change notification settings - Fork 239
Implement adr-9 logging; implemented via tracing. #6748
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
Conversation
2cc1a10
to
232db75
Compare
44d3fcf
to
4cf0c93
Compare
Hey @bendk, sorry about this 😬 Let's talk about it later today. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, I love these changes.
There were a couple pieces of leftover debug code that should be removed. Other than that, the only "blocker" for me is the question of how we filter for app-services events. Is a list of target strings the best way? The answer may be yes, but I just wanted to discuss it some.
println!("XXXXX - hello println"); | ||
eprintln!("XXXXX - hello eprintln"); | ||
error!("oh no places"); | ||
//panic!("at the disco!!!"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is hilarious, but probably should be deleted.
// println!( | ||
// "TRACING EVENT {target} - {prefix} - {}", | ||
// SINKS_BY_TARGET.read().len() | ||
// ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: another piece of leftover code.
|
||
// The "targets" (in practice, crate names) which are hooked up to the `tracing` crate for logging. | ||
// We should improve this, or better still, just kill this crate entirely - but it is a natural consequence | ||
// of using `tracing` that each target must be explicitly listened for *somewhere*. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you expand on this one a bit. Killing this crate sounds great, but how would that work in practice?
Also, what do you mean by "each target must be explicitly listened for somewhere."? When I first read that, I added "..or else something would break" in my head. Now that I re-read it, it seems like we would lose the logs. I think you framed this on our call as "there's no way to globally listen for all events", which seems clearer to me.
pub use foreign_logger::{AppServicesLogger, Level, Record}; | ||
// ideally we'd use tracing::Level as an external type, but that would cause a breaking change | ||
// for mobile, so we clone it. | ||
// (it's a shame uniffi can't re-export types!) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cloning seems okay to me, but I don't understand what's stopping us from using this as an external type. Can you link to an issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can work as an "external type", but in that scenario it means that the existing rust-log-support in the mobile platforms needs to change - eg, we'd need a PR for Swift and Android which subtly changes the dependencies so that the new crate tracing_support
is referenced. IOW, this is just a work-around to avoid the breaking-change dance.
The second comment was a reflection on this - it's kinda a shame we can't have uniffi pretend Level
was directly exported by rust-log-forwarder, but I've no idea how that would work - maybe I should remove that comment?
wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, I see what you mean now.
The "re-export types" feature seems doable to me. Maybe it already works on some languages. For example python imports the type name, that might be enough. We probably should be adding the name to __all__
as well though.
// Set up a tracing subscriber for crates which use tracing and forward to the foreign log forwarder. | ||
for target in TRACING_TARGETS { | ||
tracing_support::register_event_sink_arc(target, (*level).into(), sink.clone()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should work fine, but I want to try to figure out how to wire this all up differently -- mostly just to think about the possibilities here and understand the requirements better.
Could we have a tracing field that distinguished app-services events from other events and have this code subscribe to all those events at once? For example, the error_support
macros could set a boolean field named app_services
and the tracing_support
code could decide if an event should be forwarded to the event sink by looking for the presence of that field rather than filtering on the target
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the problem here is that we'd also need to filter on the target? ie, we'd need some way of getting all targets and then filtering after the target matches, which I'm not sure if possible, and if it was, would leave us in the same place we are in the log
crate wrt performance impact of intercepting and formatting logs we don't ultimately care about.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking that we could replace this code in tracing_support and then we get access to all the events, regardless of target.
However, looking through that code again makes me see some bigger-picture issues. By using target
as the basis of the filter, you could easily extend that to having different levels per-target and having that filtering happen before anything gets pushed across the FFI. That makes me now want to change anything. I feel like there might be some changes down the road, especially as we try to make this work for both error reporting and logging, but the current code seems like the best place to start.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for talking through that filtering question with me. I think this one is ready to merge once those println
s are removed from places_api.rs
pub use foreign_logger::{AppServicesLogger, Level, Record}; | ||
// ideally we'd use tracing::Level as an external type, but that would cause a breaking change | ||
// for mobile, so we clone it. | ||
// (it's a shame uniffi can't re-export types!) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, I see what you mean now.
The "re-export types" feature seems doable to me. Maybe it already works on some languages. For example python imports the type name, that might be enough. We probably should be adding the name to __all__
as well though.
// Set up a tracing subscriber for crates which use tracing and forward to the foreign log forwarder. | ||
for target in TRACING_TARGETS { | ||
tracing_support::register_event_sink_arc(target, (*level).into(), sink.clone()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking that we could replace this code in tracing_support and then we get access to all the events, regardless of target.
However, looking through that code again makes me see some bigger-picture issues. By using target
as the basis of the filter, you could easily extend that to having different levels per-target and having that filtering happen before anything gets pushed across the FFI. That makes me now want to change anything. I feel like there might be some changes down the road, especially as we try to make this work for both error reporting and logging, but the current code seems like the best place to start.
huh, yeah, maybe that could work! I do agree we shouldn't over-rotate now because I doubt many of these limitations are going to be a problem in practice. Eg, even today, all logs from sql-support don't indicate what component they originated in, but in practice this isn't a problem we've noticed because there's enough context to guess that. So let's just see what actually hurts us once this is in place. |
Weird, I thought I already approved. In any case, it's looking great to me. |
/taskcluster ci full |
…r logging. Summary of changes: * Existing `error-support` crate re-exports `log`, `info`, `warn`, `trace` etc. All existing components are changed so that instead of using `log::` directly we use the re-exports from `error-support`. * `error-support` also grows a `testing` feature to expose a couple of helpers for tests. * new crate `tracing-support` which also re-exports `log`, `info`, `warn`, `trace` etc and also has a `testing` feature which re-exports the same test functions. * `error-support` also grows new features to control whether it re-exports the log calls from the `log` and `env_logger` crates, or from `tracing-support`. The intent here is that in app-services we will use the feature which uses `tracing` (because we also have `rust_log_forwarder` setup to support that, but initially on desktop we will enable the feature to continue using `log` while we work on setting up an appropriate tracing subscriber there. There's also a feature to control how error reporting is done - by default it is done like has always been done on mobile, but is setup so that on Desktop it will use the tracing facility. This means we can eventually end up using a single tracing subscriber for both error reports and logs (and also any other event types we invent in the future).
No changes required for mobile consumers, it's all abstracted in
rust_log_forwarder
Summary of changes:
Existing
error-support
crate re-exportslog
,info
,warn
,trace
etc. All existing components are changed so that instead of usinglog::
directly we use the re-exports fromerror-support
.error-support
also grows atesting
feature to expose a couple of helpers for tests.new crate
tracing-support
which also re-exportslog
,info
,warn
,trace
etc and also has atesting
feature which re-exports the same test functions.error-support
also grows new features to control whether it re-exports the log calls from thelog
andenv_logger
crates, or fromtracing-support
.The intent here is that in app-services we will use the feature which uses
tracing
(because we also haverust_log_forwarder
setup to support that), but initially on desktop we will enable the feature to continue usinglog
while we work on setting up an appropriate tracing subscriber there.There's also a feature to control how error reporting is done - by default it is done like has always been done on mobile, but is setup so that on Desktop it will use the tracing facility. This means we can eventually end up using a single tracing subscriber for both error reports and logs (and also any other event types we invent in the future).