对结构化记录进行编码

受其轨迹格式启发,Fuchsia 正逐渐改用有线格式处理结构化日志。这种新的日志传输格式允许将任意数据结构作为日志记录来使用和传播。

验证

日志记录的大小上限为 32kb。

向诊断服务发送过大记录或无效的记录将关闭其数据流,并由诊断服务记录错误。

原语

整数采用小端字节编码。有符号整数是二进制补码。

时间戳是以纳秒为单位的带符号的 64 位整数,由 zx_clock_get_monotonic 记录。

字符串由 16 位“字符串引用”表示。如果最高有效位 (MSB) 为 0,则字符串为空。如果 MSB 为 1,则引用的剩余位表示后续 UTF-8 字节流的长度。MSB 为 0 以外的所有字符串引用(空字符串除外)都会保留以供将来的扩展使用。字符串会以零填充,直到实现 8 字节对齐。

记录由许多 8 字节的单词组成,并 8 字节对齐。

记录

建议实现者在测试编码器时使用 /sdk/fidl/fuchsia.diagnostics.stream/record.fidl 中的 FIDL 绑定作为记录的“参考”API。这些类型支持日志读取器和写入器的交叉验证互操作性。

日志记录所需的元数据包括记录类型、记录的总长度和时间戳。这些数据位于记录的前 16 个字节中:

.---------------------------------------------------------------.
|         |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|
|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|
|---+-----------+-----------------------------------------------|
| T | SizeWords | Reserved                            | Severity|
|---------------------------------------------------------------|
| TimestampNanos                                                |
'---------------------------------------------------------------'

T (type)       = {0,3}    must be 9
SizeWords      = {4,15}   includes header word
Reserved       = {16,55}  must be 0
Severity       = {56,63}  severity of the log record
TimestampNanos = {64,127}

目前,所有记录的类型都应为 9。系统选择此方式来反映跟踪记录格式,但可能需要更改此格式,才能让跟踪工具处理这些记录。在 /sdk/fidl/fuchsia.diagnostics/severity.fidl 中定义了严重的值

参数

日志记录数据通过键入的键值对列表进行传送。键始终是非空字符串,支持不同类型的参数,并且值可以有多种类型。

参数标头

每个参数都有一个 8 字节的标头,后跟参数名称,然后是参数值。 在写入参数的内容之前,名称会进行 0 到 8 字节对齐。

.---------------------------------------------------------------.
|         |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|
|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|
|---+-----------+-----------------------------------------------|
| T | SizeWords | NameRef     | Varies                          |
|---------------------------------------------------------------|
| Name (1+ words)                                               |
'---------------------------------------------------------------'

T (type)  = {0,3}           see table below
SizeWords = {4,15}          includes header word
NameRef   = {16,31}         string ref for the argument name
Varies    = {32,63}         varies by argument type, must be 0 if unused
NameLen   = 64*NameRef
Name      = {64,64+NameLen} name of the argument, padded to 8-byte alignment

参数标头的前 4 位确定参数具有哪种类型:

T(类型) name
3 有符号 64 位整数
4 无符号 64 位整数
5 双精度浮点数
6 UTF-8 字符串
9 布尔值

有符号的 64 位整数参数

系统会在参数名称终止后附加有符号整数。

.---------------------------------------------------------------.
|         |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|
|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|
|---+-----------+-----------------------------------------------|
| 3 | SizeWords | NameRef     | Reserved                        |
|---------------------------------------------------------------|
| Name (1+ words)                                               |
'---------------------------------------------------------------'
| Value                                                         |
'---------------------------------------------------------------'

T (type)  = {0,3}                  must be 3
SizeWords = {4,15}                 includes header word
NameRef   = {16,31}                string ref for the argument name
Reserved  = {32,63}                must be 0
NameEnd   = 64+(64*NameRef)
Name      = {64,NameEnd}           name of the argument, padded to 8-byte alignment
Value     = {NameEnd+1,SizeWords*64}

64 位无符号整数参数

无符号整数会在参数名称终止后附加。

.---------------------------------------------------------------.
|         |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|
|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|
|---+-----------+-----------------------------------------------|
| 4 | SizeWords | NameRef     | Reserved                        |
|---------------------------------------------------------------|
| Name (1+ words)                                               |
'---------------------------------------------------------------'
| Value                                                         |
'---------------------------------------------------------------'

T (type)  = {0,3}                  must be 4
SizeWords = {4,15}                 includes header word
NameRef   = {16,31}                string ref for the argument name
Reserved  = {32,63}                must be 0
NameEnd   = 64+(64*NameRef)
Name      = {64,NameEnd}           name of the argument, padded to 8-byte alignment
Value     = {NameEnd+1,SizeWords*64}

64 位浮点参数

浮点数会在参数名称终止后附加。

.---------------------------------------------------------------.
|         |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|
|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|
|---+-----------+-----------------------------------------------|
| 5 | SizeWords | NameRef     | Reserved                        |
|---------------------------------------------------------------|
| Name (1+ words)                                               |
'---------------------------------------------------------------'
| Value                                                         |
'---------------------------------------------------------------'

T (type)  = {0,3}                  must be 5
SizeWords = {4,15}                 includes header word
NameRef   = {16,31}                string ref for the argument name
Reserved  = {32,63}                must be 0
NameEnd   = 64+(64*NameRef)
Name      = {64,NameEnd}           name of the argument, padded to 8-byte alignment
Value     = {NameEnd+1,SizeWords*64}

字符串参数

字符串采用 UTF-8 编码,用零填充直到 8 字节对齐,然后附加到参数名称后面。

.---------------------------------------------------------------.
|         |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|
|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|
|---+-----------+-----------------------------------------------|
| 6 | SizeWords | NameRef     | ValueRef      | Reserved        |
|---------------------------------------------------------------|
| Name (1+ words)                                               |
'---------------------------------------------------------------'
| Value (1+ words)                                              |
'---------------------------------------------------------------'

T (type)  = {0,3}                  must be 6
SizeWords = {4,15}                 includes header word
NameRef   = {16,31}                string ref for the argument name
ValueRef  = {32,47}                string ref for the argument value
Reserved  = {48,63}                must be 0
NameEnd   = 64+(64*NameRef)
Name      = {64,NameEnd}           name of the argument, padded to 8-byte alignment
Value     = {NameEnd+1,SizeWords*64}

布尔值参数

布尔值会附加到参数标头中的 NameRef 字段后面。

.---------------------------------------------------------------.
|         |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|
|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|
|---+-----------+-----------------------------------------------|
| 9 | SizeWords | NameRef     |B| Reserved                      |
|---------------------------------------------------------------|
| Name (1+ words)                                               |
'---------------------------------------------------------------'

T (type)      = {0,3}                  must be 9
SizeWords     = {4,15}                 includes header word
NameRef       = {16,31}                string ref for the argument name
B (BoolValue) = {32}                   boolean value
Reserved      = {33,63}                must be 0
NameEnd       = 64+(64*NameRef)
Name          = {64,NameEnd}           name of the argument, padded to 8-byte alignment

对“legacy”格式的消息进行编码

调用 LogSink.Connect 的组件应以“数据报”模式(与“流式传输”)传递套接字,并将“旧版”有线格式写入其中。它使用小端字节序整数,并且混合使用带长度前缀和以 null 结尾的 UTF-8 字符串。