RFC-0035:自动流跟踪

RFC-0035:自动流跟踪
状态已拒绝
领域
  • FIDL
说明

通过向 FIDL 绑定添加跟踪事件,可在 Fuchsia 上实现跨进程的端到端流,而无需手动滚动自定义 ID。

作者
提交日期(年-月-日)2019-02-28
审核日期(年-月-日)2019-02-28

遭拒的理由

没有响应(无论是事件还是“即发即弃”调用)的消息的事务 ID 被设置为 0,因此无法使用建议的方案进行区分。

有些用例利用了 zx_channel_call(),在内核中分配事务 ID,并等待回复。 (此模式允许并发调用方依赖于内核同步,避免为事务 ID 分配锁定用户空间。) 同样,我们提出的方案也无法区分这两者。

内核跟踪支持应提供此审核所需的遥测,并且倾向于改进此机制,而不是在 FIDL 绑定中推送此机制。

最后,在 SDK 依赖项提取顺序中,由于在 Fuchsia 上广泛使用 FIDL,使用 FIDL 和使用 FIDL 绑定的情况非常接近顶部。因此,在绑定中包含遥测和指标会引发此类顾虑,使我们感到担心,而这并不是我们愿意接受的次序。您可以想象到一些构建和选择启用技巧,并且需要在未来方案中纳入。

总结

通过向 FIDL 绑定添加跟踪事件,可在 Fuchsia 上实现跨进程的端到端流,而无需手动滚动自定义 ID。

设计初衷

在 Fuchsia 上,有大量的黑客行为支持跨进程边界实现流程事件。我们可以通过一种不会使 API 接口复杂化和手动操作更少的方式实现大多数流程的自动化。

设计

Fuchsia FIDL 函数的标准属性,用于将流程开始/结束事件添加到分别生成的绑定。

该属性设置跟踪记录的类别,并使用协议函数作为名称。在 Fuchsia 上进行跟踪仅支持一个类别,因此,虽然该属性可能包含 N 个类别,但我们预计只会使用一个类别,并将使用列表中的第一个类别。

protocol Example {
    [Trace = "CATEGORY"]
    ExampleFn(bool test) -> (bool status);
};

唯一的跨进程 ID 是使用非加密哈希一起哈希处理的序数 ID、事务 ID(包含在每条消息中)和传输机制的 ID(对于 zircon 通道:发送进程通道句柄的 koid,以及接收进程句柄的相关 koid)。

zx 通道上的 FIDL 的稳定跟踪 ID 示例

我们建议组合使用以下几种标识符:

  • FIDL 通道服务器端的 koid,可通过 zx_object_get_info() 和主题 ZX_INFO_HANDLE_BASIC(在服务器端使用 koid,在客户端使用相关 koid)获取;
  • 事务消息的方法序数(注意:此值目前是一个 uint32 哈希值,很快将变为 uint64 哈希值,请参阅 RFC-0029);
  • 最后是交易消息交易 ID

如何组合这三个标识符应努力减少可能的跟踪 ID 冲突,优先级如下:

  1. 同一序数相同的两条不同消息之间,以及同一客户端和服务器之间;
  2. 同一客户端和服务器之间以及具有不同序数的不同消息之间;
  3. 发生在不同序数的不同消息之间,以及在不同客户端和服务器之间。

目前,koid 分配主要按顺序进行。因此,koid 最低位的熵高于最高位。 同样,事务 ID 也是依序分配的,因此最低位的熵更高。方法序数会经过加密哈希处理,尽管为系统使用预留了最高位,但可以放心地假定所有位都具有相同的熵。

因此,在当前条件下,合理的算法为 OR:

  • koid & OxFFFF << 48
  • ordinal & 0xFFFFFFFF << 16
  • transaction ID & 0xFF << 0

还会在 FIDL 绑定的接收端启动跟踪记录时长。对于 C++/Rust 等语言,其作用域使用 RAII 进行限定,并允许将事件与其他流事件拼接。

工效学设计

这使得我们的跟踪系统更易于使用,这对我们的基础架构来说也是一项巨大的优势。

文档和示例

应更新文档,以展示如何添加跟踪记录(如上所述)。

向后兼容性

此变更与 API 和 ABI 兼容。

性能

停用跟踪类别后,这会带来很小的开销,即每次 dje@google.com 测试(在 NUC 上)不到 5 纳秒。假设需要更多性能,我们还可以从 IR 中删除跟踪注解。

安全性

没有任何安全影响。

缺点、替代方案和未知情况

替代选项

内核跟踪机制

利用针对通道读取和通道写入的现有 ktrace 流事件。

如果没有此功能,可以尝试通过对底层通道读取和写入使用现有的 ktrace 流事件来实现此目的。 不过,这种情况是不可取的,因为这些通道在所有 FIDL 接口中是通用的,也就是说,只能指定一个类别。 这意味着,为了实际使用,用户必须启用通道读取和写入类别,这意味着所有通道读写事件(而不仅仅是相关 FIDL 接口使用的事件)都会存在。这会导致更难读取 Trace Viewer 输出、使用不必要的 ktrace 缓冲区,并且还会依赖于 FIDL 实现细节。