[pbs-devel] [RFC proxmox v2 2/2] proxmox-log: added tracing infra

Gabriel Goller g.goller at proxmox.com
Thu Nov 2 15:58:02 CET 2023


Thanks for the review!

On 11/2/23 14:43, Wolfgang Bumiller wrote:
> [..]
>> +
>> +impl<S: Subscriber> Layer<S> for FilelogLayer {
>> +    fn on_event(&self, event: &Event<'_>, _ctx: Context<'_, S>) {
>> +        let mut buf = String::new();
>> +
>> +        event.record(&mut EventVisitor::new(&mut buf));
> I'd argue the above 2 lines should be part of the closure below,
> otherwise in the error case you just produce a string to throw away.
I Agree!
>> +
>> +        let logger_exists = LOGGER.try_with(|logger| {
>> +            log_to_file(&mut logger.borrow_mut(), event.metadata().level(), buf);
>> +        });
>> +        if let Err(e) = logger_exists {
>> +            error!(
> Is it wise to call log functions from within log handlers? ;-)
Hmm, yes this could be tricky...
How do we want to handle this anyway? We could panic here, but that 
seems a bit
harsh. Logging with `eprintln` is also an option, but a quite useless 
one tbh.
>> [..]
>> +pub struct WorkerTaskFilter {
>> +    in_worker_task: Arc<Mutex<bool>>,
> AFAICT you only have locks which are shortlived to set/clear/check this
> value.
> For such a thing you can use `Arc<AtomicBool>` and get rid of all the
> error handling.
Ooh, this makes it a lot easier, thanks for the heads up!I think we 
should be alright by just using `Ordering::Relaxed` everywhere, right?
>> +}
>> +
>> +impl WorkerTaskFilter {
>> +    pub fn new(in_worker_task: Arc<Mutex<bool>>) -> WorkerTaskFilter {
>> +        WorkerTaskFilter { in_worker_task }
>> +    }
>> +}
>> +
>> +impl<S: Subscriber + for<'a> LookupSpan<'a>> Filter<S> for WorkerTaskFilter {
>> +    fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
>> +        let metadata = ctx.metadata(id);
>> +        if let Some(m) = metadata {
>> +            if m.name() == "worker_task" {
> I'm not so happy with this.
> Now each time we poll a worker task we go through this layer system
> which uses string comparison to know whether we're currently in a worker
> task, for something that is actually rather static in the code.
> I'd much prefer a simply custom `Future` wrapping the worker task's
> future and setting this flag for the duration of the `poll()` method.
Ok, but the `Future` wrapper would only work for the task, right?
So we would need to keep the `span` version (or come up with
something different) for the thread use-case and then again have a
lot of `if (thread) { do this } else if (task) { do this }` stuff, which 
I don't
really like.
What we could do is have another `tokio::task_local!()` thingy, which 
contains a bool 'log_to_tasklog'. Then have another `scope` and 
`sync_scope` around the worker logic (So we would substitute the span 
stuff with another TLS).
> This just seems like a whole lot of overhead we don't need for such
> simple functionality. Also, the `on_enter` and `on_exit` methods make it
> look like you could easily enter and exit this type of span, but that's
> not the case. `on_exit` always stores `false`, so nested spans
> temporarily disabling and enabling the worker task log would just end up
> with a messed up state (this would need to be a counter...).
Right, I would need a counter here..
>> [..]
>> +
>> +impl Visit for EventVisitor<'_> {
>> +    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
>> +        if field.name() == "message" {
>> +            self.buf.push_str(&format!("{:?}", value));
> String implements fmt::Write. You can
>
>      use std::fmt::Write as _;
>      let _ = write!(state.buf, "{value:?}");
>
> it's possible for this to be more efficient since it does not enforce
> the creation of a separate allocated string.

Thanks!

> [..]





More information about the pbs-devel mailing list