Implement adr-9 logging; implemented via tracing.#6748
Conversation
2cc1a10 to
232db75
Compare
44d3fcf to
4cf0c93
Compare
|
Hey @bendk, sorry about this 😬 Let's talk about it later today. |
bendk
left a comment
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
bendk
left a comment
There was a problem hiding this comment.
Thanks for talking through that filtering question with me. I think this one is ready to merge once those printlns 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.
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.
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_forwarderSummary of changes:
Existing
error-supportcrate re-exportslog,info,warn,traceetc. All existing components are changed so that instead of usinglog::directly we use the re-exports fromerror-support.error-supportalso grows atestingfeature to expose a couple of helpers for tests.new crate
tracing-supportwhich also re-exportslog,info,warn,traceetc and also has atestingfeature which re-exports the same test functions.error-supportalso grows new features to control whether it re-exports the log calls from thelogandenv_loggercrates, or fromtracing-support.The intent here is that in app-services we will use the feature which uses
tracing(because we also haverust_log_forwardersetup to support that), but initially on desktop we will enable the feature to continue usinglogwhile 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).