将任意数据映射到 OTLP AnyValue

状态: 开发中

本文档定义了如何将任意数据(例如内存中的对象)映射(转换)为 OTLP 的 AnyValue

当 OpenTelemetry 需要将 OpenTelemetry 外部生成的值转换为可以使用 OTLP 导出器导出的值,或者在 OpenTelemetry 边界内部使用的值时,就需要进行这种映射。示例如下:

  • 日志 SDK 中,将从日志库接收到的值转换为 OpenTelemetry 表示形式。
  • 在 Collector 中,将从各种数据源接收到的值转换为 pdata 内部表示形式。

转换为 AnyValue

AnyValue 能够表示某些类型的原始数据和结构化数据。

具有任何形式的源数据(例如内存对象或需要转换为 AnyValue 的其他格式的数据)的实现,应遵循以下规则。

原始值

整数值

在 64 位有符号整数范围 [-2^63..2^63-1] 内的整数值应转换为 AnyValue 的 int_value 字段。

超出 64 位有符号整数范围的整数值应使用十进制表示法转换为 AnyValue 的 string_value 字段。

枚举

属于有限枚举集的值(例如 Java enum)应转换为 AnyValue 的 string_value 字段,并将字符串值设置为枚举的符号名称。

如果无法获取枚举的符号名称,则实现应在可以自然获取序数值时,将枚举值映射到 AnyValue 的 int_value 字段,设置为枚举的序数值。

如果也无法获取序数值,则枚举应转换为 AnyValue 的 bytes_value 字段,通过实现认为合理的方式进行转换。

浮点数值

在 IEEE 754 64 位浮点数范围和精度内的浮点值(包括 IEEE 32 位浮点值)应转换为 AnyValue 的 double_value 字段。

超出 IEEE 754 64 位浮点数范围或精度的浮点值(例如 IEEE 128 位浮点值)应使用十进制浮点表示法转换为 AnyValue 的 string_value 字段。

字符串值

有效的 UTF-8 序列的字符串值应转换为 AnyValue 的 string_value 字段。

非有效 Unicode 序列的字符串值应转换为 AnyValue 的 bytes_value 字段,其中字节按源字符串的原始顺序和格式表示。

字节序列

字节序列(例如 Go 的 []byte 切片或文件的原始字节内容)应转换为 AnyValue 的 bytes_value 字段。

复合值

数组值

表示其他值有序序列的值(如 数组向量、有序 列表切片)应转换为 AnyValue 的 array_value 字段。字符串值和字节序列是此规则的例外(请参阅上文)。

本文档中描述的规则应递归应用于数组的每个元素。

具有唯一键的关联数组

表示具有唯一键的关联数组(也常称为映射、字典或键值存储)的值应转换为 AnyValue 的 kvlist_value 字段。

如果源数组的键不是字符串,则必须通过任何可用手段将其转换为字符串,通常通过编程语言提供的 toString() 或 stringify 函数。转换函数必须选择一种方式,以确保生成的字符串键在目标数组中是唯一的。

源数组每个元素的值部分应递归转换为 AnyValue。

例如,JSON 对象 {"a": 123, "b": "def"} 应转换为

AnyValue{
    kvlist_value:KeyValueList{
        values:[
            KeyValue{key:"a",value:AnyValue{int_value:123}},
            KeyValue{key:"b",value:AnyValue{string_value:"def"}},
        ]
    }
}

本文档中描述的规则应递归应用于关联数组的每个值。

具有非唯一键的关联数组

表示具有非唯一键的关联数组(也称为多重映射、多重字典)的值应转换为 AnyValue 的 kvlist_value 字段,其中多个值可能与同一个键相关联。

生成的 kvlist_value 字段必须只列出每个键一次,并且 kvlist_value 字段的每个元素的值必须是一个使用 AnyValue 的 array_value 字段表示的数组,数组的每个元素代表源数组中与给定键相关联的一个值。

例如,下表中显示的关联数组

“abc”123
“def”“foo”
“def”“bar”

应转换为

AnyValue{
    kvlist_value:KeyValueList{
        values:[
            KeyValue{
                key:"abc",
                value:AnyValue{array_value:ArrayValue{values[
                    AnyValue{int_value:123}
                ]}}
            },
            KeyValue{
                key:"def",
                value:AnyValue{array_value:ArrayValue{values[
                    AnyValue{string_value:"foo"},
                    AnyValue{string_value:"bar"}
                ]}}
            },
        ]
    }
}

本文档中描述的规则应递归应用于关联数组的每个值。

集合

无序的唯一值集合(如 Java SetC++ setPython Set)应转换为 AnyValue 的 array_value 字段,其中集合的每个元素成为数组的一个元素。

本文档中描述的规则应递归应用于集合的每个值。

其他值

上面未列出的任何其他值,如果源数据可以(使用编程语言中可用的 toString() 或 stringify 函数)序列化为字符串(可 stringify),则应转换为 AnyValue 的 string_value 字段。

如果源数据无法序列化为字符串,则应通过任何可用手段将其序列化为字节序列,然后转换为 AnyValue 的 bytes_value 字段。

如果源数据既不能序列化为字符串也不能序列化为字节序列,则应将其转换为空的 AnyValue。

空值

如果源数据没有关联的类型,并且为空、null、nil 或以其他方式指示数据缺失,则应将其转换为 的 AnyValue,其中所有字段均未设置。

具有关联类型的空值(例如,空关联数组)应使用上面为该类型定义的相应规则进行转换。