OTEP-0178: 任意のデータをOTLPのAnyValueにマッピングする

このドキュメントでは、任意のデータ(たとえばインメモリのオブジェクト)をOTLPのAnyValueにマッピング(変換)する方法を定義します。

動機

このマッピングは、変換された値が言語や実装をまたいで曖昧さがなく一貫したものになるように、Logging Library SDKを正しく実装するために必要です。

説明

AnyValueは、特定の型のプリミティブなデータと構造化されたデータを表現できます。

インメモリのオブジェクトや他の形式から得られるデータなど、任意の形式のソースデータを持ち、それをAnyValueに変換する必要がある実装は、以下に説明するルールに従うべきです(SHOULD)。

プリミティブな値

整数値

64ビット符号付き数値の範囲[-2^63..2^63-1]に収まる整数値は、AnyValueのint_valueフィールドに変換されるべきです(SHOULD)。

64ビット符号付き数値の範囲外にある整数値は、10進表現を使ってAnyValueのstring_valueフィールドに変換されるべきです(SHOULD)。

列挙型

限定された列挙集合に属する値(たとえばJavaのenum)は、列挙型のシンボル名を文字列として設定したAnyValueのstring_valueフィールドに変換されるべきです(SHOULD)。

列挙型のシンボル名を取得できない場合、実装は、序数が自然に取得できるのであれば、列挙型の値をその序数と等しい値を設定したAnyValueのint_valueフィールドにマッピングするべきです(SHOULD)。

序数値も取得できない場合、列挙型は、実装が妥当と判断する任意の方法でAnyValueのbytes_valueフィールドに変換されるべきです(SHOULD)。

浮動小数点値

IEEE 754の64ビット浮動小数点数の範囲と精度に収まる浮動小数点値(IEEEの32ビット浮動小数点値を含む)は、AnyValueのdouble_valueフィールドに変換されるべきです(SHOULD)。

IEEE 754の64ビット浮動小数点数の範囲または精度の外にある浮動小数点値(たとえばIEEEの128ビット浮動小数点値)は、10進の浮動小数点表現を使ってAnyValueのstring_valueフィールドに変換されるべきです(SHOULD)。

文字列値

有効なUnicodeシーケンスである文字列値は、AnyValueのstring_valueフィールドに変換されるべきです(SHOULD)。

有効なUnicodeシーケンスではない文字列値は、ソース文字列の元の順序と形式を表すバイト列として、AnyValueのbytes_valueに変換されるべきです(SHOULD)。

バイト列

バイト列(たとえばGoの[]byteスライスやファイルの生のバイト内容)は、AnyValueのbytes_valueフィールドに変換されるべきです(SHOULD)。

複合的な値

配列値

他の値の順序付きシーケンスを表す値(たとえば配列ベクター、順序付きのリストスライス)は、AnyValueのarray_valueフィールドに変換されるべきです(SHOULD)。 文字列値とバイト列は、このルールの例外です(前述を参照してください)。

一意なキーを持つ連想配列

一意なキーを持つ連想配列を表す値(マップ、ディクショナリ、キーバリューストアとも呼ばれます)は、AnyValueのkvlist_valueフィールドに変換されるべきです(SHOULD)。

ソースの配列のキーが文字列でない場合、それらは利用可能な任意の手段で文字列に変換されなければなりません(MUST)。 多くの場合、プログラミング言語で利用可能なtoString()やstringify関数を使用します。 変換関数は、結果として得られる文字列のキーが変換先の配列内で一意になることを保証する方法で選ばれなければなりません(MUST)。

ソースの配列の各要素の値の部分は、再帰的にAnyValueに変換されるべきです(SHOULD)。

たとえば、JSONオブジェクト {"a": 123, "b": "def"} は次のように変換されるべきです(SHOULD)。

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

一意でないキーを持つ連想配列

同じキーに複数の値が関連付けられる可能性がある、一意でないキーを持つ連想配列を表す値(マルチマップ、マルチディクトとも呼ばれることがあります)は、AnyValueのkvlist_valueフィールドに変換されるべきです(SHOULD)。

結果として得られるkvlist_valueフィールドは各キーを一度だけリストしなければならず(MUST)、kvlist_valueフィールドの各要素の値は、AnyValueのarray_valueフィールドを使って表現された配列でなければならず(MUST)、array_valueの各要素は、指定されたキーに関連付けられたソースの配列の1つの値を表します。

たとえば、次の表に示す連想配列は、

キー
“abc”123
“def”“foo”
“def”“bar”

次のように変換されるべきです(SHOULD)。

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フィールドに変換されるべきです(SHOULD)。

その他の値

上記に列挙されていないその他の値は、ソースデータがプログラミング言語で利用可能なtoString()やstringify関数を使って文字列にシリアライズできる(文字列化できる)場合、AnyValueのstring_valueフィールドに変換されるべきです(SHOULD)。

ソースデータを文字列にシリアライズできない場合、その値は、利用可能な任意の手段でバイト列にシリアライズすることで、AnyValueのbytes_valueフィールドに変換されるべきです(SHOULD)。

ソースデータを文字列にもバイト列にもシリアライズできない場合、それは空のAnyValueに変換されるべきです(SHOULD)。

空の値

ソースデータに型が関連付けられておらず、空、null、nil、またはその他の方法でデータが存在しないことを示している場合、それはすべてのフィールドが未設定であるのAnyValueに変換されるべきです(SHOULD)。

型が関連付けられている空の値(たとえば空の連想配列)は、上記で定義された対応する型のルールを使って変換されるべきです(SHOULD)。

代替案

このドキュメントに列挙されているマッピングの一部は、異なる方法で設計することもできます。 たとえば、マルチマップは、配列値を持つマップの代わりに、マップの配列として表現することもできます。 このような代替の表現方法も検討されましたが、このドキュメントで選択された解決策よりも有利であるとは判断されませんでした。

将来の可能性

AnyValueがより多くのデータ型をサポートするように拡張された場合、より自然なマッピングとなるように、このドキュメントの一部のルールが改訂されることがあります。 これが行われる場合、既存のマッピングルールに依存しているアプリケーションを壊さないように、後方互換性が慎重に検討されるべきです。