fuchsia_syslog_listener/
lib.rs

1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Log listener support library.
6
7#![deny(missing_docs)]
8
9use anyhow::{Context as _, Error};
10use fidl_fuchsia_logger::{
11    LogFilterOptions, LogListenerSafeRequest, LogListenerSafeRequestStream, LogMessage, LogProxy,
12};
13use futures::channel::mpsc;
14use futures::TryStreamExt;
15
16/// This trait is used to pass log message back to client.
17pub trait LogProcessor {
18    /// Called when log is received from logger.
19    fn log(&mut self, message: LogMessage);
20
21    /// Called when logger service signals that it is done dumping logs.
22    /// This is only called if we request logger service to dump logs
23    /// rather than registering a listener.
24    fn done(&mut self);
25}
26
27async fn log_listener(
28    mut processor: impl LogProcessor,
29    mut stream: LogListenerSafeRequestStream,
30) -> Result<(), fidl::Error> {
31    while let Some(request) = stream.try_next().await? {
32        match request {
33            LogListenerSafeRequest::Log { log, responder } => {
34                processor.log(log);
35                responder.send().ok();
36            }
37            LogListenerSafeRequest::LogMany { log, responder } => {
38                for msg in log {
39                    processor.log(msg);
40                }
41                responder.send().ok();
42            }
43            LogListenerSafeRequest::Done { control_handle: _ } => {
44                processor.done();
45                return Ok(());
46            }
47        }
48    }
49    Ok(())
50}
51
52/// Register listener or log dumper based on the parameters passed.
53pub async fn run_log_listener_with_proxy<'a>(
54    logger: &LogProxy,
55    processor: impl LogProcessor + 'a,
56    options: Option<&'a LogFilterOptions>,
57) -> Result<(), Error> {
58    let (listener_ptr, listener_stream) = fidl::endpoints::create_request_stream();
59    logger.listen_safe(listener_ptr, options).context("failed to register listener")?;
60    log_listener(processor, listener_stream).await?;
61    Ok(())
62}
63
64impl LogProcessor for mpsc::UnboundedSender<LogMessage> {
65    fn log(&mut self, message: LogMessage) {
66        // this is called in spawned tasks which may outlive the test's interest
67        self.unbounded_send(message).ok();
68    }
69
70    fn done(&mut self) {
71        self.close_channel();
72    }
73}