-
-
Notifications
You must be signed in to change notification settings - Fork 104
Using tracing
crate
#3960
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
Using tracing
crate
#3960
Conversation
7c8626e
to
d137f9e
Compare
Oh, I've wanted this for a while :) |
0913923
to
8ff2a79
Compare
There are three main tasks in setting up the
Subscriber is already implemented in this PR as an One option is to instrument all Context and Accounts calls. I am currently considering not setting up the subscriber from the Instead:
|
f5f2710
to
d6e5bfd
Compare
This layer should be part of the Rust public API.
Yes, I agree this is the right approach. |
967cc85
to
d089e5b
Compare
src/events.rs
Outdated
let &level = event.metadata().level(); | ||
|
||
// FIXME | ||
let context_id = 0; |
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's still a question where to get this context_id
from.
It should be possible to set it from Accounts.start_io()
for every account.start_io()
future.
I am currently considering looking for context_id
field on the current span. If current span has no context ID field, then set it to 0. The problem is that some library called by delta chat core may set up a span too, then context_id
will become invisible, but at least all delta chat events will have proper context ID. We can also try to walk the span tree if needed.
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.
Could we require a subscriber per context and insert the context id into the subscriber at creation time?
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 thought about this, but this means account manager will have to create subscribers, and these subscribers will catch all the tracing
events, converting them to Delta Chat events. For Rust programs like repl
and Rust bots these subscribers are not needed, they might want to subscribe to all events directly from main()
and account manager creating its own subscribers will interfere.
On Wed, Jan 18, 2023 at 11:00 -0800, link2xt wrote:
@link2xt commented on this pull request.
+ // FIXME
+ let context_id = 0;
I thought about this, but this means account manager will have to create subscribers, and these subscribers will catch all the `tracing` events, converting them to Delta Chat events. For Rust programs like `repl` and Rust bots these subscribers are not needed, they might want to subscribe to all events directly from `main()` and account manager creating its own subscribers will interfere.
Repl and Rust bots are not a strong argument against floris' suggestion i think.
If it works for jsonrpc-desktop/android/ios usage and python/js bots then
repl/rust can maybe just live with it or do something in addition to work-around if it's an issue?
|
On Thu 19 Jan 2023 at 07:21 -0800, holger krekel wrote:
On Wed, Jan 18, 2023 at 11:00 -0800, link2xt wrote:
> @link2xt commented on this pull request.
> + // FIXME
> + let context_id = 0;
>
> I thought about this, but this means account manager will have to create subscribers, and these subscribers will catch all the `tracing` events, converting them to Delta Chat events. For Rust programs like `repl` and Rust bots these subscribers are not needed, they might want to subscribe to all events directly from `main()` and account manager creating its own subscribers will interfere.
Repl and Rust bots are not a strong argument against floris' suggestion i think.
If it works for jsonrpc-desktop/android/ios usage and python/js bots then
repl/rust can maybe just live with it or do something in addition to work-around if it's an issue?
I'm not really sure anymore if my suggestion would really work out. The
subscriber is global and you still need to support multiple accounts.
So I fear that somehow the context id needs to be in the span otherwise
the subscriber doesn't know which account an event is from.
I guess a standard span name of `context` with an `id` field would work
this, rather than searching any span for a matching id (or context_id)
field. The trickier bit will be to activate that span in the right
places.
|
f2bedff
to
ad03ac7
Compare
Took a glance at |
See |
The PR is ready for review, it only needs rebasing and maybe repl/README updates to make it usable. But applications and bots built with this will already work. |
src/events.rs
Outdated
if let Some(span_context_id) = span.extensions().get::<EventContextId>() { | ||
context_id = *span_context_id; | ||
if context_id.0 > 0 { | ||
break; |
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't we also set here EventContextId
for the original span so that we don't need to loop again on subsequent events?
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.
Also i'd prefer to have a span id in the log instead of a context id (which is per-account afaiu). So, when an event occurs, and it's the first event in its span, we, say, first log that there's a new span (in the context of its parent span), i.e. send a fake event "span created" from its parent span (which propagate up if needed), and then process the original event. This way logs would be more structured. And also spans w/o "real" events wouldn't produce any logs
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't we also set here
EventContextId
for the original span so that we don't need to loop again on subsequent events?
I am not sure such microoptimization makes things better. If there is only one event emitted in this span, then it's an additional memory write for no gain.
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.
Also i'd prefer to have a span id in the log instead of a context id (which is per-account afaiu).
Context ID inside event indicates which account received an event when account manager is used and there is only a single event emitter for multiple accounts. I do not see how span ID helps with this, it only indicates part of the code which emitted an event, but there is no way to tell if it's the current account or another account running in the background.
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 am not sure such microoptimization makes things better. If there is only one event emitted in this span, then it's an additional memory write for no gain.
Yes, but i personally prefer things that scale better in questional situations. Anyway, it's not critical here.
Context ID inside event indicates which account received an event when account manager is used and there is only a single event emitter for multiple accounts. I do not see how span ID helps with this, it only indicates part of the code which emitted an event, but there is no way to tell if it's the current account or another account running in the background.
I suppose we have different root spans for accounts and thus can learn from logs which account an event belongs to. Anyway, i don't suggest to implement this now as it changes the structure of logs. Just to think how we could make logs more structured and also get rid of such loops searching for EventContextId
@@ -11,18 +11,24 @@ use deltachat_jsonrpc::api::{Accounts, CommandApi}; | |||
use futures_lite::stream::StreamExt; | |||
use tokio::io::{self, AsyncBufReadExt, BufReader}; | |||
use tokio::task::JoinHandle; | |||
use tracing::{info, trace}; |
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.
Maybe we can reexport all such macros somewhere in our crate to just write smth like use crate::tracing::macros::*
? Because if we need, say, info
, we also need other macros too and it's not convenient to constantly fix these use
statements
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.
There is an upstream proposal to implement use tracing::prelude::*
: tokio-rs/tracing#167 . Wildcard import of modules not called prelude
is generally a bad style, clippy will complain.
We can of course add our own internal prelude
module, but this seems better suited for upstream or at least a separate crate.
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.
Btw, for now we can use tracing as log;
and this commit will be smaller and we don't need to list all necessary macros explicitly.
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.
We can also define our own private module deltachat::prelude
and include deltachat::prelude::*
everywhere.
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.
Looks good to me but maybe somebody with more experience with logging/tracing in Rust should take a look also
c14a00e
to
a85b988
Compare
7ff5ce1
to
e0e9caa
Compare
I removed all the |
d24dc3a
to
75b4100
Compare
It is unclear now how to set the context/account ID when JSON-RPC requests are made. In |
2d3cdb1
to
ff9a7c9
Compare
ff9a7c9
to
0db7386
Compare
0db7386
to
4f364f0
Compare
@@ -50,13 +50,13 @@ impl Context { | |||
/// Set last error string. | |||
/// Implemented as blocking as used from macros in different, not always async blocks. | |||
pub fn set_last_error(&self, error: &str) { | |||
let mut last_error = self.last_error.write().unwrap(); | |||
let mut last_error = self.events.last_error.write().unwrap(); | |||
*last_error = error.to_string(); |
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.
Again, maybe call to_string()
before taking lock?
} | ||
|
||
#[macro_export] | ||
macro_rules! warn { |
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.
Since the new warn!
macro doesn't take a context
anymore, would be nice to adapt log_err()
and so on, too, maybe by just letting it use the warn!
macro. After rebasing though, because it'll create a merge conflict otherwise, and it's not urgent either.
@link2xt what happened to this? |
Was probably closed when we renamed But the problem is that every caller has to set an |
This is now replaced with a much simpler approach #6919 |
No description provided.