routing/
error_logging_router.rs1use crate::error::{ErrorReporter, RouteRequestErrorInfo};
6use async_trait::async_trait;
7use capability_source::CapabilitySource;
8use fidl_fuchsia_component_runtime::RouteRequest;
9use router_error::RouterError;
10use runtime_capabilities::{
11 Capability, CapabilityBound, Connector, Data, Dictionary, DirConnector, Routable, Router,
12 WeakInstanceToken,
13};
14
15pub struct ErrorLoggingRouter<R: ErrorReporter> {
16 inner_router: Capability,
17 route_request: RouteRequestErrorInfo,
18 error_reporter: R,
19 error_location: WeakInstanceToken,
20}
21
22impl<R: ErrorReporter> ErrorLoggingRouter<R> {
23 pub fn new(
24 inner_router: Capability,
25 route_request: impl Into<RouteRequestErrorInfo>,
26 error_reporter: R,
27 error_location: WeakInstanceToken,
28 ) -> Capability {
29 match &inner_router {
30 Capability::ConnectorRouter(_) => Router::<Connector>::new(Self {
31 inner_router,
32 route_request: route_request.into(),
33 error_reporter,
34 error_location,
35 })
36 .into(),
37 Capability::DirConnectorRouter(_) => Router::<DirConnector>::new(Self {
38 inner_router,
39 route_request: route_request.into(),
40 error_reporter,
41 error_location,
42 })
43 .into(),
44 Capability::DictionaryRouter(_) => Router::<Dictionary>::new(Self {
45 inner_router,
46 route_request: route_request.into(),
47 error_reporter,
48 error_location,
49 })
50 .into(),
51 Capability::DataRouter(_) => Router::<Data>::new(Self {
52 inner_router,
53 route_request: route_request.into(),
54 error_reporter,
55 error_location,
56 })
57 .into(),
58 _ => panic!("non-router type passed to ErrorLoggingRouter"),
59 }
60 }
61}
62
63#[async_trait]
64impl<T: CapabilityBound, R: ErrorReporter> Routable<T> for ErrorLoggingRouter<R>
65where
66 Router<T>: TryFrom<Capability>,
67{
68 async fn route(
69 &self,
70 request: RouteRequest,
71 target: WeakInstanceToken,
72 ) -> Result<Option<T>, RouterError> {
73 let inner_router: Router<T> =
74 self.inner_router.clone().try_into().ok().expect("type mismatch");
75 match inner_router.route(request, target).await {
76 Ok(res) => Ok(res),
77 Err(err) => {
78 self.error_reporter
79 .report(&self.route_request, &err, self.error_location.clone())
80 .await;
81 Err(err)
82 }
83 }
84 }
85
86 async fn route_debug(
87 &self,
88 request: RouteRequest,
89 target: WeakInstanceToken,
90 ) -> Result<CapabilitySource, RouterError> {
91 let inner_router: Router<T> =
92 self.inner_router.clone().try_into().ok().expect("type mismatch");
93 match inner_router.route_debug(request, target).await {
94 Ok(res) => Ok(res),
95 Err(err) => {
96 self.error_reporter
97 .report(&self.route_request, &err, self.error_location.clone())
98 .await;
99 Err(err)
100 }
101 }
102 }
103}