診斷與監控

連線至元件中的 FIDL 通訊協定結合了能力轉送和目錄提供功能。這表示診斷連線問題可能涉及幾種不同的層:

  • 用戶端在資訊清單中要求通訊協定能力。
  • 供應商會在資訊清單中公開通訊協定能力。
  • 元件拓撲會將能力從供應器轉送到用戶端。
  • 供應商使用正確的帳號代碼提供通訊協定。
  • 用戶端正嘗試連線至正確的通訊協定控制代碼。

在本節中,您將探索一些 API 和工具,協助您找出並修正元件連線相關問題,以及監控元件的長期健康狀態。

監控 FIDL 連線

fidlcat 工具可讓您監控 FIDL 連線並進行偵錯,以便追蹤元件傳送和接收的個別 FIDL 訊息。與 Fuchsia 偵錯工具 (zxdb) 類似,fidlcat 會連線至目標裝置上正在執行的 debug_agent 元件,並監控執行中的程序。

圖表顯示「fidlcat」如何與在 Fuchsia 裝置上執行的 debug_agent 服務互動,監控特定程序的 FIDL 呼叫並進行偵錯。

設定監控工作階段需要下列高階步驟:

  1. 在目標裝置上執行 debug_agent 元件。
  2. 執行 fidlcat 用戶端並連線至目標裝置。

如要啟動 FIDL 偵錯工作階段,最簡單的方法是使用 ffx debug fidl 指令,在本機 Fuchsia 建構作業中完成上述所有操作。不過,如果您需要單獨設定這些步驟,也可以手動執行這些步驟。

以下是 FIDL 通訊協定要求的 fidlcat 訊息範例。追蹤記錄輸出內容包含各項翻譯的實用資訊,包括:

  • 元件或程序名稱
  • 叫用系統呼叫
  • FIDL 程式庫、通訊協定和方法名稱
  • 含有參數或傳回值的訊息酬載
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!"
    }

使用檢查

元件檢查功能可讓 Fuchsia 元件使用 Inspect API 顯示關於自身的結構化診斷資訊。Fuchsia 透過開發人員工具和錯誤報告提供這類資訊,協助診斷問題或監控效能。

元件會以名為「Nodes」的樹狀結構的形式公開檢查指標,每個指標都包含一組屬性,做為鍵/值組合。屬性支援多種數字、字串和陣列資料類型。元件檢查器程式庫提供了元件的根節點介面,可讓您將其他感興趣的屬性附加至應用程式。

這張樹狀圖顯示元件檢查功能如何以「節點」的樹狀結構提供結構化指標資料,而每個節點可包含一或多個鍵/值「屬性」屬性。

您可以使用開發人員工具擷取目前發布至「檢查」的一組指標:

  • ffx inspect:可讓您使用元件選取器,以互動方式查詢檢查狀態。這有助於在開發期間對元件進行偵錯。
  • ffx target snapshot:擷取整個系統的偵錯快照封存,其中包含 JSON 格式的「檢查」資料。
ffx inspect show core/foo-example
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

運動:監控服務供應商元件

在本節中,您將使用診斷工具監控 echo 伺服器元件的健康狀態和行為。

啟動模擬器

如果您尚未擁有執行中的執行個體,請透過網路支援啟動 FEMU:

ffx emu start workstation_eng.x64 --headless

監控 FIDL 流量

建立包含伺服器和用戶端元件的 echo-realm 新執行個體:

ffx component run /core/ffx-laboratory:echo-realm fuchsia-pkg://fuchsiasamples.com/echo-realm#meta/echo_realm.cm

您可以使用 fidlcat 監控元件中的 FIDL 連線並進行偵錯。啟動 ffx debug fidl 並設定以監控 echo 伺服器元件:

ffx debug fidl --remote-name echo_server.cm --fidl-ir-path bazel-out/
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!

啟動 echo 用戶端執行個體,啟動與伺服器之間的 FIDL 連線:

ffx component start /core/ffx-laboratory:echo-realm/echo_client

用戶端會繫結至伺服器元件,並使用 Echo FIDL 通訊協定進行通訊。查看 ffx debug fidl 輸出,查看 echo 伺服器處理的 FIDL 交易清單:

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/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/examples.routing.echo.Echo) }

echo_server.cm 58694:58696 zx_channel_read_etc(handle: handle = Channel:f93b597b(channel:0:svc/examples.routing.echo.Echo), options: uint32 = 0, num_bytes: uint32 = 512, num_handles: uint32 = 4)
  -> ZX_OK
    received request 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/examples.routing.echo.Echo), options: uint32 = 0)
  sent response 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/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/examples.routing.echo.Echo))
  -> ZX_OK

請注意事件順序:

  1. 通訊協定實作的管道會在 svc/examples.routing.echo.Echo 開啟。
  2. 伺服器會透過開放管道收到 Echo.EchoString 要求,其中包含用戶端傳送的字串酬載。
  3. 伺服器傳送具有相同字串酬載的對應回應。
  4. 頻道關閉。

fidlcat 透過追蹤元件之間的 FIDL 連線,可讓您找出潛在問題,例如連線失敗或資料酬載無效。

新增要求追蹤

元件檢查功能可讓您發布元件中的診斷資訊,協助偵錯。您將使用 Inspect API 追蹤 echo 伺服器元件的部分使用統計資料。

更新 echo_server 要求處理常式,接受包含用於處理要求計數和已處理位元組數字檢查屬性的新結構。處理常式會在每個傳入要求中增加以下屬性:

echo-server/main.cc

struct EchoConnectionStats {
  inspect::UintProperty bytes_processed;
  inspect::UintProperty total_requests;
};

// Handler for incoming FIDL protocol requests
class EchoImplementation : public fidl::Server<examples_routing_echo::Echo> {
 public:
  // The handler for `examples.routing.echo/Echo.EchoString` requests.
  //
  // Replies back to the caller with the original request value.
  void EchoString(EchoStringRequest& request, EchoStringCompleter::Sync& completer) override {
    // Increment connection stats on each request
    stats_->total_requests.Add(1);
    stats_->bytes_processed.Add(request.value()->size());
    completer.Reply({{request.value()}});
  }

  // Called when the FIDL connection is torn down.
  void OnUnbound(fidl::UnbindInfo info, fidl::ServerEnd<examples_routing_echo::Echo> server_end) {
    if (info.is_user_initiated()) {
      return;
    }
    if (info.is_peer_closed()) {
      // The peer (the client) closed their endpoint.
      FX_LOG(DEBUG, "echo_server", "Client disconnected.");
    } else {
      // Treat other unbind causes as errors.
      FX_LOGF(ERROR, "echo_server", "Server error: %s", info.status_string());
    }
  }

  std::unique_ptr<EchoConnectionStats> stats_;
};

將下列程式碼新增至 main(),以初始化檢查正確項目,並將其傳送至更新後的處理常式:

echo-server/main.cc

int main(int argc, const char** argv) {
  // ...

  // Serve the Echo protocol
  std::unique_ptr<EchoImplementation> echo_instance = std::make_unique<EchoImplementation>();

  // Create request tracking properties
  inspect::Node& root_node = inspector.root();
  auto total_requests = root_node.CreateUint("total_requests", 0);
  auto bytes_processed = root_node.CreateUint("bytes_processed", 0);
  echo_instance->stats_ = std::make_unique<EchoConnectionStats>(EchoConnectionStats{
    std::move(bytes_processed),
    std::move(total_requests),
  }); 

  // ...
}

最後,更新匯入內容,以加入新的檢查程式庫:

echo-server/main.cc

#include <fidl/examples.routing.echo/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/inspect/component/cpp/component.h>
#include <lib/component/outgoing/cpp/outgoing_directory.h>
#include <lib/syslog/global.h>

建構更新過的套件,並發布至 fuchsiasamples.com 存放區:

bazel run //fuchsia-codelab/echo-realm:pkg.publish -- \
    --repo_name fuchsiasamples.com

驗證 Inspect 資料

建立包含更新 echo-server 的新 echo-realm 元件:

ffx component run /core/ffx-laboratory:echo-realm fuchsia-pkg://fuchsiasamples.com/echo-realm#meta/echo_realm.cm \
    --recreate

多次執行 echo 用戶端元件。這會導致每次連線中的要求數量在 echo-server 中遞增:

ffx component start /core/ffx-laboratory:echo-realm/echo_client
ffx component start /core/ffx-laboratory:echo-realm/echo_client
ffx component start /core/ffx-laboratory:echo-realm/echo_client

使用 ffx inspect 查看 echo 伺服器元件的可用檢查資料。您會看到 root 節點底下樹狀結構中處理的要求數和位元組數值,以及元件健康狀態:

ffx inspect show 'core/ffx-laboratory\:echo-realm/echo_server'
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

使用檢查功能發布健康狀態和行為資訊,即可觀察元件目前的狀態,並在實際工作環境裝置上診斷問題。

刪除執行個體

使用下列指令清除 echo-realm 例項:

ffx component destroy /core/ffx-laboratory:echo-realm

後續步驟

恭喜!您已成功使用 FIDL 建構 Fuchsia IPC 介面,並使用這個介面將兩個元件連接在一起。

您已完成本課程中的所有單元!歡迎深入瞭解 新的新知,深入瞭解

Fuchsia 概念