| |
| # Diagnostics and monitoring |
| |
| Connecting to FIDL protocols within components is a combination of capability |
| routing and directory serving. This means that diagnosing connection issues can |
| cover a few different layers: |
| |
| * Client requests the protocol capability in its manifest. |
| * Provider exposes the protocol capability in its manifest. |
| * Component topology routes the capability from the provider to the client. |
| * Provider is serving the protocol on the correct handle. |
| * Client is attempting to connect to the correct protocol handle. |
| |
| In this section, you'll explore some APIs and tools to help you find and fix |
| problems with component connections, and monitor the long-term health of your |
| components. |
| |
| ## Verifying capability routes |
| |
| The `ffx scrutiny` utility provides a host of features for auditing system |
| security, including an audit of the capability routes in the static component |
| topology. The `verify routes` subcommand discovers and reports routing errors, |
| which can help you find any missing `offer` or `expose` declarations in your |
| manifest. |
| |
| ```posix-terminal |
| ffx scrutiny verify routes |
| ``` |
| |
| This enables you to perform initial validation of your declarations before you |
| even run the components! |
| |
| ```none {:.devsite-disable-click-to-copy} |
| [ |
| { |
| "capability_type": "protocol", |
| "results": { |
| "errors": [ |
| { |
| "capability": "fidl.examples.echo.Echo", |
| "error": "no offer declaration for `/core` with name `fidl.examples.echo.Echo`", |
| "using_node": "/core/echo_client" |
| } |
| ] |
| } |
| } |
| ] |
| ``` |
| |
| ## Monitoring FIDL connections |
| |
| The `fidlcat` tool allows you to monitor and debug FIDL connections to trace |
| individual FIDL messages sent and received by your component. Similar to the |
| Fuchsia debugger (`zxdb`), `fidlcat` connects to a running `debug_agent` |
| component on the target device and monitors running processes. |
| |
| ![Diagram showing how "fidlcat" interacts with the debug_agent service running |
| on a Fuchsia device to monitor and debug FIDL calls for a given process.] |
| (images/fidlcat.png){: width="592"} |
| |
| Setting up the monitoring session requires the following high-level steps: |
| |
| 1. Run the `debug_agent` component on the target device. |
| 1. Run the `fidlcat` client and connect to the target device. |
| |
| The simplest method to start a debug session is to use the `fx fidlcat` |
| command, which does all of these in the context of your local Fuchsia build. |
| However, these steps can also be performed manually if you need to configure |
| them separately. |
| |
| Below is an example `fidlcat` message for a FIDL protocol request. The trace |
| output contains helpful information for each translation, including: |
| |
| * The component or process name |
| * The system call invoked |
| * The FIDL library, protocol, and method name |
| * Message payload containing parameters or return values |
| |
| ```none {:.devsite-disable-click-to-copy} |
| echo-client.cm 256109:256122 zx_channel_read(handle:handle: e4c7c57f, options:uint32: 0, num_bytes:uint32: 48, num_handles:uint32: 0) |
| -> ZX_OK |
| received response fidl.examples.echo/Echo.EchoString = { |
| response: string = "hello world!" |
| } |
| ``` |
| Note: For complete details on `fidlcat` usage and options, see |
| [Monitor and debug your FIDL calls](/docs/development/monitoring/fidlcat). |
| |
| ## Using Inspect |
| |
| Component Inspection enables Fuchsia components to expose structured diagnostic |
| information about themselves using the Inspect API. Fuchsia provides this |
| information through the developer tools and bug reports to assist in diagnosing |
| issues or monitoring performance. |
| |
| Components expose inspection metrics as a tree of named **Nodes**, each |
| containing a set of **Properties** as key/value pairs. Properties support a |
| variety of numeric, string, and array data types. The component inspector |
| libraries provide an interface to your component's **root node** where you can |
| attach additional properties of interest to your application. |
| |
| {: width="583"} |
| |
| You can retrieve the current set of metrics published to Inspect using the |
| developer tools: |
| |
| * `ffx inspect`: Lets you interactively query the Inspect state using |
| component selectors. This is helpful for debugging components during |
| development. |
| * `ffx target snapshot`: Captures a debug snapshot archive of the entire |
| system, which contains the Inspect data in JSON format. |
| |
| ```posix-terminal |
| ffx inspect show core/foo-example |
| ``` |
| |
| ```none {:.devsite-disable-click-to-copy} |
| core/foo-example: |
| metadata: |
| filename = fuchsia.inspect.Tree |
| component_url = fuchsia-pkg://fuchsia.com/foo-example#meta/foo-example.cm |
| timestamp = 55457379176 |
| payload: |
| root: |
| version = 1.0 |
| request_metrics: |
| request_count = 3 |
| error = timeout |
| ``` |
| |
| Note: For more details on using the Inspect API, see |
| [Fuchsia component inspection](/docs/development/diagnostics/inspect). |
| |
| ## Exercise: Monitoring provider components |
| |
| In this section, you'll use the diagnostics tools to monitor the health and |
| behavior of the echo server component. |
| |
| ### Monitor FIDL traffic |
| |
| You can use `fidlcat` to monitor and debug the FIDL connections in your |
| components. Launch `fidlcat` and configure it to monitor the echo server |
| component: |
| |
| ```posix-terminal |
| fx fidlcat --remote-name=echo_server.cm |
| ``` |
| |
| ```none {:.devsite-disable-click-to-copy} |
| Checking for debug agent on [fe80::d6c5:4526:c282:fb6%qemu]:2345. |
| Debug agent not found. Starting one. |
| INFO: [main.cc(238)] Connected to symbol server gs://fuchsia-artifacts-release/debug |
| INFO: [main.cc(122)] Connecting to port 2345 on fe80::d6c5:4526:c282:fb6%qemu... |
| INFO: [main.cc(92)] Connected! |
| ``` |
| |
| <aside class="key-point"> |
| The <code>--remote-name</code> parameter configures <code>fidlcat</code> to |
| watch for a matching process name and attach as soon as it is discovered. You |
| can use <code>--remote-pid</code> to attach to an existing process. |
| </aside> |
| |
| Initiate a FIDL connection to the server by starting an echo client instance: |
| |
| ```posix-terminal |
| ffx component bind /core/ffx-laboratory:echo-realm/echo_client |
| ``` |
| |
| The client binds to the server component and communicates using the `Echo` |
| FIDL protocol. Review the `fidlcat` output to see a list of the FIDL |
| transactions handled by echo server: |
| |
| ```none {:.devsite-disable-click-to-copy} |
| Monitoring echo_server.cm |
| |
| echo_server.cm 58694:58696 zx_channel_read_etc(handle: handle = fb9b5273, options: uint32 = 0, num_bytes: uint32 = 512, num_handles: uint32 = 4) |
| -> ZX_OK |
| received request fuchsia.io/Directory.Open = { flags: uint32 = 3, mode: uint32 = 493, path: string = "svc/fidl.examples.routing.echo.Echo", object: handle = Channel:f93b597b(ZX_RIGHT_TRANSFER | ZX_RIGHT_READ | ZX_RIGHT_WRITE | ZX_RIGHT_SIGNAL | ZX_RIGHT_SIGNAL_PEER | ZX_RIGHT_WAIT | ZX_RIGHT_INSPECT)(channel:0:svc/fidl.examples.routing.echo.Echo) } |
| |
| echo_server.cm 58694:58696 zx_channel_read_etc(handle: handle = Channel:f93b597b(channel:0:svc/fidl.examples.routing.echo.Echo), options: uint32 = 0, num_bytes: uint32 = 512, num_handles: uint32 = 4) |
| -> ZX_OK |
| received request fidl.examples.routing.echo/Echo.EchoString = { value: string = "Hello, Fuchsia" } |
| |
| echo_server.cm 58694:58696 zx_channel_write_etc(handle: handle = Channel:f93b597b(channel:0:svc/fidl.examples.routing.echo.Echo), options: uint32 = 0) |
| sent response fidl.examples.routing.echo/Echo.EchoString = { response: string = "Hello, Fuchsia" } |
| -> ZX_OK |
| |
| echo_server.cm 58694:58696 zx_channel_read_etc(handle: handle = Channel:f93b597b(channel:0:svc/fidl.examples.routing.echo.Echo), options: uint32 = 0, num_bytes: uint32 = 512, num_handles: uint32 = 4) |
| -> ZX_ERR_PEER_CLOSED |
| |
| echo_server.cm 58694:58696 zx_handle_close(handle: handle = Channel:f93b597b(channel:0:svc/fidl.examples.routing.echo.Echo)) |
| -> ZX_OK |
| ``` |
| |
| Notice the sequence of events: |
| |
| 1. A channel to the protocol implementation opens at |
| `svc/fidl.examples.routing.echo.Echo`. |
| 1. The server receives an `Echo.EchoString` request over the open channel, |
| containing the string payload sent by the client. |
| 1. The server sends a corresponding response with the same string payload. |
| 1. The channel closes. |
| |
| By tracing the FIDL connections between your components, `fidlcat` enables you |
| to find and diagnose potential issues such as failed connections or invalid |
| data payloads. |
| |
| <aside class="key-point"> |
| <b>Extra credit</b> |
| <p>Monitor the FIDL connections in <code>echo-client.cm</code> using |
| <code>fidlcat</code>. Do you see anything different from the messages recorded |
| from echo server?</p> |
| </aside> |
| |
| ### Add request tracking |
| |
| Component inspection allows you to publish diagnostic information from your |
| components to assist in debugging. You'll use the Inspect API to track some |
| usage statistics for the echo server component. |
| |
| Update the `handle_echo_request()` handler function in `main.rs` to accept a new |
| struct containing numeric Inspect properties for request count and bytes |
| processed. The handler increments these properties on each incoming request: |
| |
| `echo-server/src/main.rs`: |
| |
| ```rust |
| // Inspect properties managed by the server |
| struct EchoConnectionStats { |
| total_requests: fuchsia_inspect::UintProperty, |
| bytes_processed: fuchsia_inspect::UintProperty, |
| } |
| |
| // Handler for incoming service requests |
| async fn handle_echo_request(mut stream: EchoRequestStream, stats: &EchoConnectionStats) { |
| while let Some(event) = stream.try_next().await.expect("failed to serve echo service") { |
| let EchoRequest::EchoString { value, responder } = event; |
| responder.send(value.as_ref().map(|s| &**s)).expect("failed to send echo response"); |
| |
| if let Some(message) = value { |
| // Update Inspect property values |
| stats.total_requests.add(1); |
| stats.bytes_processed.add(message.len() as u64); |
| } |
| } |
| } |
| ``` |
| |
| Add the following code to `main()` to initialize the Inspect propertes and pass |
| them to the updated handler: |
| |
| `echo-server/src/main.rs`: |
| |
| ```rust |
| async fn main() -> Result<(), anyhow::Error> { |
| // ... |
| |
| // Component is serving and ready to handle incoming requests |
| component::health().set_ok(); |
| |
| {{ '<strong>' }}// Create request tracking properties {{ '</strong>' }} |
| {{ '<strong>' }}let root_node = component::inspector().root(); {{ '</strong>' }} |
| {{ '<strong>' }}let stats = EchoConnectionStats { {{ '</strong>' }} |
| {{ '<strong>' }}total_requests: root_node.create_uint("total_requests", 0), {{ '</strong>' }} |
| {{ '<strong>' }}bytes_processed: root_node.create_uint("bytes_processed", 0), {{ '</strong>' }} |
| {{ '<strong>' }}}; {{ '</strong>' }} |
| |
| // Attach request handler for incoming requests |
| service_fs |
| .for_each_concurrent(None, |_request: IncomingRequest| async { |
| match _request { |
| {{ '<strong>' }}IncomingRequest::Echo(stream) => handle_echo_request(stream, &stats).await, {{ '</strong>' }} |
| } |
| }) |
| .await; |
| |
| Ok(()) |
| } |
| ``` |
| |
| <aside class="key-point"> |
| <b>Health checks</b> |
| <p>The component template includes code that sets the |
| <code>component::health()</code> status. This is a standardized inspection |
| metric for component health, which provides a convenient way to report whether |
| your component is running well or experiencing an issue. You'll find this status |
| reported under <code>fuchsia.inspect.Health</code> in the Inspect tree.</p> |
| <p>For more details on this metric, see |
| <a href="/docs/concepts/diagnostics/inspect/health">Health check</a>.</p> |
| </aside> |
| |
| Finally, update the imports in `main.rs` to include the new Inspect libraries: |
| |
| `echo-server/src/main.rs`: |
| |
| ```rust |
| use anyhow::{self, Context}; |
| use fidl_fidl_examples_routing_echo::{EchoRequest, EchoRequestStream}; |
| use fuchsia_component::server::ServiceFs; |
| use fuchsia_inspect::{component, health::Reporter}; |
| use fuchsia_inspect::NumericProperty; |
| use futures::prelude::*; |
| ``` |
| |
| Run `fx build` again to rebuild the component: |
| |
| ```posix-terminal |
| fx build |
| ``` |
| |
| ### Verify the Inspect data |
| |
| Stop the current `echo-server` component instance. This allows the component to |
| resolve the latest version from the package server the next time it starts. |
| |
| ```posix-terminal |
| ffx component stop /core/ffx-laboratory:echo-realm/echo_server |
| ``` |
| |
| Run the echo client component multiple times. This causes the request count in |
| `echo-server` to increment with each connection: |
| |
| ```posix-terminal |
| ffx component bind /core/ffx-laboratory:echo-realm/echo_client |
| |
| ffx component bind /core/ffx-laboratory:echo-realm/echo_client |
| |
| ffx component bind /core/ffx-laboratory:echo-realm/echo_client |
| ``` |
| |
| View the available Inspect data for the echo server component with |
| `ffx inspect`. You'll see the values for request count and bytes processed in |
| the tree under the `root` node alongside the component health status: |
| |
| ```posix-terminal |
| ffx inspect show 'core/ffx-laboratory\:echo-realm/echo_server' |
| ``` |
| |
| ```none {:.devsite-disable-click-to-copy} |
| core/ffx-laboratory\:echo-realm/echo_server: |
| metadata: |
| filename = fuchsia.inspect.Tree |
| component_url = #meta/echo_server.cm |
| timestamp = 1476246046122 |
| payload: |
| root: |
| bytes_processed = 42 |
| total_requests = 3 |
| fuchsia.inspect.Health: |
| start_timestamp_nanos = 1467828507317 |
| status = OK |
| ``` |
| |
| Publishing health and behavior information using Inspect enables you to observe |
| the current state of your components and diagnose issues on production devices. |
| |
| <aside class="key-point"> |
| <b>Extra credit</b> |
| <p>Use <code>ffx target snapshot</code> tool to capture a debug snapshot from |
| the target device. This archive also contains the Inspect data in a JSON |
| format. Can you locate the same echo server data returned using |
| <code>ffx inspect</code>?</p> |
| </aside> |
| |
| ## What's next? |
| |
| Congratulations! You've successfully built a Fuchsia IPC interface using FIDL, |
| and connected two components together using that interface. |
| |
| You have completed all the modules in this course! Take your newfound |
| understanding to the next level and dive deeper into the: |
| |
| <a class="button button-primary" |
| href="/docs/concepts">Fuchsia concepts</a> |