# Inspect Quick Start

[TOC]

This document is a guide on how to get started with [Component
Inspection](README.md) depending on your needs:

**I want to learn more about Inspect concepts**

Read the [README](README.md).

**I want to know how to use the iquery tool**

Read the [iquery manual][iquery]. For detailed examples of usage,
see the [Codelab](codelab/codelab.md).

This document provides a simplified example of iquery below.

**I have an existing or new component, and I want to support inspection.**

Continue reading this document.

## Languages

See below for the quick start guide in your language of choice.

* {C++}

  #### Setup
  This section assumes you are writing an asynchronous component and that
  some part of your component (typically `main.cc`) looks like this:

  ```cpp
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
  auto component_context = sys::ComponentContext::CreateAndServeOutgoingDirectory();
  // ...
  loop.Run();
  ```

  This sets up an async loop, creates a `ComponentContext` wrapping handles
  provided by the runtime, and then runs that loop following some other
  initialization work.

  **Add the following include**

  ```cpp
  #include <lib/sys/inspect/cpp/component.h>
  ```

  **Change your initialization code to look like the following:**

  ```cpp
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
  auto component_context = sys::ComponentContext::CreateAndServeOutgoingDirectory();
  auto inspector =
        std::make_unique<sys::ComponentInspector>(component_context.get());
  inspect::Node& root_node = inspector->root();
  // ...
  loop.Run();
  ```

  You are now using Inspect! To add some data and see it in action, try adding the following:

  ```cpp
  // Important: Make sure to hold on to hello_world_property and don't let it go out of scope.
  auto hello_world_property = root_node.CreateStringProperty("hello", "world");
  ```

  See [Viewing Inspect Data](#viewing-inspect-data) below to view what you are now exporting.

  See [Supported Data Types](#supported-data-types) for a full list of data types you can try.

  Want to test your Inspect integration? Include
  [lib/inspect/testing/cpp/inspect.h][testing-header]
  in your unit test for a full set of matchers. See [this example][vmo-example] of how it is used.

  [testing-header]: /sdk/lib/inspect/testing
  [vmo-example]: /src/sys/appmgr/integration_tests/inspect/test-vmo.cc

  Read on to learn how Inspect is meant to be used in C++.

  #### Dynamic Value Support

  The C++ library has two property creators for lazily inflating Inspect
  trees at read-time: `CreateLazyNode` and `CreateLazyValues`.

  Both of these methods take a callback returning a promise for an
  inspect::Inspector, the only difference is how the dynamic values are
  stored in the tree.

  `root->CreateLazyNode(name, callback)` creates a child node of
  `root` with the given `name`. The `callback` returns a promise for an
  `inspect::Inspector` whose root node is spliced into the parent hierarchy
  when read. The example below shows that a child called "lazy" exists with
  the string property "version" and has an additional child that is called
  "lazy."

  `root->CreateLazyValues(name, callback)` works like `root->CreateLazyNode(name,
  callback)`, except all properties and child nodes on the promised root node are
  added directly as values
  to the original `root`. In the second output of this example, the internal
  lazy nodes do not appear and their values are flattened into properties on
  `root`.

  ```cpp
  root->CreateLazy{Node,Values}("lazy", [] {
    Inspector a;
    a.GetRoot().CreateString("version", "1.0", &a);
    a.GetRoot().CreateLazy{Node,Values}("lazy", [] {
      Inspector b;
      b.GetRoot().CreateInt("value", 10, &b);
      return fit::make_ok_promise(std::move(b));
    }, &a);

    return fit::make_ok_promise(std::move(a));
  });
  ```

  Output (CreateLazyNode):

  ```
  root:
    lazy:
      version = "1.0"
      lazy:
        val = 10
  ```

  Output (CreateLazyValues):

  ```
  root:
    val = 10
    version = "1.0"
  ```

  Warning: It is the developer's responsibility to ensure that names
  flattened from multiple lazy value nodes do not conflict. If they do,
  output behavior is undefined.

  The return value of `CreateLazy{Node,Values}` is a `LazyNode` that owns
  the passed callback.  The callback is never called once the `LazyNode` is
  destroyed. If you destroy a `LazyNode` concurrently with the execution of
  a callback, the destroy operation is blocked until the callback returns
  its promise.

  If you want to dynamically expose properties on `this`, you may simply
  write the following:

  ```cpp
  class Employee {
    public:
      Employee(inspect::Node node) : node_(std::move(node)) {
        calls_ = node_.CreateInt("calls", 0);

        // Create a lazy node that populates values on its parent
        // dynamically.
        // Note: The callback will never be called after the LazyNode is
        // destroyed, so it is safe to capture "this."
        lazy_ = node_.CreateLazyValues("lazy", [this] {
          // Create a new Inspector and put any data in it you want.
          inspect::Inspector inspector;

          // Keep track of the number of times this callback is executed.
          // This is safe because the callback is executed without locking
          // any state in the parent node.
          calls_.Add(1);

          // ERROR: You cannot modify the LazyNode from the callback. Doing
          // so may deadlock!
          // lazy_ = ...

          // The value is set to the result of calling a method on "this".
          inspector.GetRoot().CreateInt("performance_score",
                                        this->CalculatePerformance(), &inspector);

          // Callbacks return a fit::promise<Inspector>, so return a result
          // promise containing the value we created.
          // You can alternatively return a promise that is completed by
          // some asynchronous task.
          return fit::make_ok_promise(std::move(inspector));
        });
      }

    private:
      inspect::Node node_;
      inspect::IntProperty calls_;
      inspect::LazyNode lazy_;
  };
  ```

  #### C++ Library Concepts

  Now that you have a `root_node` you may start building your
  hierarchy. This section describes some important concepts and patterns
  to help you get started.

  * A Node may have any number of key/value pairs called **Properties**.
  * The key for a Value is always a UTF-8 string, the value may be one of the supported types below.
  * A Node may have any number of children, which are also Nodes.

  The code above gives you access to a single node named
  "root". `hello_world_property` is a Property that contains a string value
  (aptly called a **StringProperty**).

  * Values and Nodes are created under a parent Node.

  Class `Node` has creator methods for every type of
  supported value. `hello_world_property` was created using
  `CreateStringProperty`. You could create a child under the root node
  by calling `root_node.CreateChild("child name")`. Note that names must
  always be UTF-8 strings.

  * Values and Nodes have strict ownership semantics.

  `hello_world_property` owns the Property. When it is destroyed (goes
  out of scope) the underlying Property is deleted and no longer present
  in your component's Inspect output. This is true for child Nodes as well.

  If you are creating a value that doesn't need to be modified, use a
  [`ValueList`](/zircon/system/ulib/inspect/include/lib/inspect/cpp/value_list.h)
  to keep them alive until they are no longer needed.

  * Inspection is best-effort.

  Due to space limitations, the Inspect library may be unable to satisfy
  a `Create` request. This error is not surfaced to your code: you will
  receive a Node/Property object for which the methods are no-ops.

  * Pattern: Pass in child Nodes to child objects.

  It is useful to add an `inspect::Node` argument to the constructors
  for your own classes. The parent object, which should own its own
  `inspect::Node`, may then pass in the result of `CreateChild(...)`
  to its children when they are constructed:

  ```cpp
  class Child {
    public:
      Child(inspect::Node my_node) : my_node_(std::move(my_node)) {
        // Create a string that doesn't change, and emplace it in the ValueList
        my_node_.CreateString("version", "1.0", &values_);
        // Create metrics and properties on my_node_.
      }

    private:
      inspect::Node my_node_;
      inspect::StringProperty some_property_;
      inspect::ValueList values_;
      // ... more properties and metrics
  };

  class Parent {
    public:
      // ...

      void AddChild() {
        // Note: inspect::UniqueName returns a globally unique name with the specified prefix.
        children_.emplace_back(my_node_.CreateChild(inspect::UniqueName("child-")));
      }

    private:
      std::vector<Child> children_;
      inspect::Node my_node_;
  };
  ```

* {Rust}

  #### Setup

  This section assumes you are writing an asynchronous component and that some
  part of your component (typically main.rs) looks similar to this:

  ```rust
  #[fasync::run_singlethreaded]
  async fn main() -> Result<(), Error> {
    ...
    let mut fs = ServiceFs::new();
    ...
    Ok(())
  }
  ```

  Add the following to your initialization code:

  ```rust
  // This creates the root of an inspect tree.
  let inspector = component::inspector();

  // This serves the inspect Tree to the default path for reading at the standard
  // location "/diagnostics/fuchsia.inspect.Tree".
  inspector.serve(&mut fs)?;

  // This will give you a reference to the root node of the inspect tree.
  let root = inspector.root();
  ```

  Don't forget to `use fuchsia_inspect::component;`!

  Now you can use inspect! For example try the following:

  ```rust
  let hello_world_property = root.create_string("hello", "world!");
  ```

  See [this example](/examples/diagnostics/inspect/rust/src/main.rs) for further
  learning of other types offered by the API.

  To test your inspect code, you can use `assert_inspect_tree`:

  ```rust

  let inspector = component::inspector();
  let root = inspector.root();
  let child = root.create_child("child1");
  child.record_double("some_property_name", 1.0);
  child.record_string("another_property", "example");
  let children = inspector.create_child("children");

  assert_inspect_tree!(inspector, root: {
    child1: {
      some_property_name: 1.0,
      another_property: "example",
      children: {},
    }
  });
  ```

  Learn more about [testing](/src/lib/diagnostics/inspect/node-hierarchy/rust/src/testing.rs) inspect.

  See [the docs](https://fuchsia-docs.firebaseapp.com/rust/fuchsia_inspect/index.html)
  to learn about other methods offered by the Rust API.

  See [Viewing Inspect Data](#viewing-inspect-data) below to view what you are now exporting.

  See [Supported Data Types](#supported-data-types) for a full list of data types you can try.

  #### Rust Library Concepts

  Refer to [C++ Library Concepts](#c_library-concepts), as similar concepts
  apply in Rust.

  The Rust library provides two ways of managing nodes and properties: creation and recording.

  With the `create_*` methods, the ownership of the property or node object to the caller.
  When the returned object is dropped, it is removed. For example:

  ```rust
  {
      let property = root.create_int("name", 1);
  }
  ```

  In this example, the property went out of scope so a drop on the property is
  called. Readers won't see this property.

  With the `record_*` methods, the lifetime of the node the method is
  called on is entangled with the resulting property. When the node the method was called
  is deleted, the recorded property is deleted.

  ```rust
  {
      let node = root.create_child("name");
      {
        node.record_uint(2); // no return
      }
      // The uint property will still be visible to readers.
  }
  ```

  In this example, neither the `name` node nor the uint property is visible to readers
  after `node` is dropped.

  #### Dynamic Value Support

  Refer to [C++ Dynamic Value Support](#dynamic-value-support), as similar
  concepts apply in Rust.

  Example:

  ```rust
  root.create_lazy_{child,values}("lazy", [] {
      async move {
          let inspector = Inspector::new();
          inspector.root().record_string("version", "1.0");
          inspector.root().record_lazy_{node,values}("lazy", [] {
              let inspector = Inspector::new();
              inspector.root().record_int("value", 10);
              // `_value`'s drop is called when the function returns, so it will be removed.
              // For these situations `record_` is provided.
              let _value = inspector.root().create_int("gone", 2);
              Ok(inspector)
          });
          Ok(inspector)
      }
      .boxed()
  });

  Output (create_lazy_node):
  root:
    lazy:
      version = "1.0"
      lazy:
        val = 10

  Output (create_lazy_values):
  root:
    val = 10
    version = "1.0"
  ```


* {Dart}

  This example obtains and adds several data types and nested children to the
  root Inspect node.

  `BUILD.gn`:

  ```dart
  flutter_app("inspect_mod") {
  [...]
    deps = [
      [...]
      "//topaz/public/dart/fuchsia_inspect",
      [...]
    ]
  [...]

  ```

  ```dart {highlight="lines:6"}
  import 'package:fuchsia_inspect/inspect.dart' as inspect;
  [...]
  class RootIntentHandler extends IntentHandler {
    @override
    void handleIntent(Intent intent) {
      var inspectNode = inspect.Inspect().root;
      runApp(InspectExampleApp(inspectNode));
    }
  }
  ```

  `inspect_example_app.dart`:

  ```dart {highlight="lines:4,7-10,16"}
  import 'package:fuchsia_inspect/inspect.dart' as inspect;

  class InspectExampleApp extends StatelessWidget {
    final inspect.Node _inspectNode;

    InspectExampleApp(this._inspectNode) {
      _inspectNode.stringProperty('greeting').setValue('Hello World');
      _inspectNode.doubleProperty('double down')..setValue(1.23)..add(2);
      _inspectNode.intProperty('interesting')..setValue(123)..subtract(5);
      _inspectNode.byteDataProperty('bytes').setValue(ByteData(4)..setUint32(0, 0x01020304));
    }
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        home: _InspectHomePage(
            inspectNode: _inspectNode.child('home-page')),
        [...]
    }
  ```

  You can call `delete()` on a Node or Property when you're done with it.
  Deleting a node deletes everything under it.

  `delete()` can also be triggered by a Future completing or broadcast Stream
  closing:

  ```dart
  var answerFuture = _answerFinder.getTheAnswer();
  var wait = _inspectNode.stringProperty('waiting')..setValue('for a hint');
  answerFuture.whenComplete(wait.delete);

  stream.listen((_) {}, onDone: node.delete);

  // FIDL proxies contain a future that completes when the connection closes:
  final _proxy = my_fidl_import.MyServiceProxy();
  _proxy.ctrl.whenClosed.whenComplete(node.delete);
  ```

## Viewing Inspect Data

  You can use the `[iquery]` tool to view the Inspect data you
  exported from your component by looking through the Hub.

  This section assumes you have SSH access to your running Fuchsia system and
  that you started running your component. We will use the name
  `my_component.cmx` as a placeholder for the name of your component.

### Find your Inspect endpoint

  Try the following:

  ```sh
  # This prints all component selectors (monikers in v2 or realm paths in v1) available.
  $ iquery list

  # This prints all files containing inspect under /hub (this won't show v2 components)
  $ iquery list-files /hub

  # This filters the above list to only print your component.
  $ iquery list-files /hub | grep my_component.cmx
  $ iquery list | grep my_component.cmx  # TODO(fxbug.dev/45458): allow to pass a manifest filter
  ```

  Under the listed directories you will see some paths including
  "system\_objects." This Inspect data is placed there by the Component Runtime
  itself.

  Your component's endpoint will be listed as `<path>/my_component.cmx/<id>/out/diagnostics/root.inspect`.

  Note: If you followed [Dynamic Value Support](#dynamic-value-support) above,
  "root.inspect" will be missing.

### Read your Inspect data

  Use the moniker that `list` printed above, and run:

  ```sh
  $ iquery show realm/my_component.cmx
  ```

  You can also spcify a node/property using selectors:

  ```sh
  $ iquery show realm/my_component.cmx:root/path/to/some:property
  ```

  Navigate to the `out/` directory that was printed above, and run:

  ```sh
  $ iquery --recursive fuchsia.inspect.Tree
  # Or root.inspect if you are exposing a vmo file directly
  # (this is not the case if using inspect libs directly)
  ```

  Or `root.inspect` instead of `fuchsia.inspect.Tree`. Note that this is not the
  case in general (except on Dart). If you are using the standard inspect libs it'll be the Tree
  protocol.

  This will print out the following if you followed the suggested steps above:

  ```sh
  root:
    hello = world
  ```

## Supported Data Types

 Type | Description | Notes
  -----|-------------|-------
    IntProperty | A metric containing a signed 64-bit integer. | All Languages
    UIntProperty | A metric containing an unsigned 64-bit integer. | Not supported in Dart
    DoubleProperty | A metric containing a double floating-point number. | All Languages
    BoolProperty | A metric containing a double floating-point number. | All Languages
    {Int,Double,UInt}Array | An array of metric types, includes typed wrappers for various histograms. | Same language support as base metric type
    StringProperty | A property with a UTF-8 string value. | All Languages
    ByteVectorProperty | A property with an arbitrary byte value. | All Languages
    Node | A node under which metrics, properties, and more nodes may be nested. | All Languages
    LazyNode | Instantiates a complete tree of Nodes dynamically. | C++, Rust

[iquery]: /docs/reference/diagnostics/consumers/iquery.md
