Currently the protocol buffers involved in protobuf ingestion are not available in the public repository. To retrieve the protobufs required for protobuf ingestion, see the next section.
bytes value), and the server derives telemetry channels from the message structure.
Example
Given this protobuf message:Vehicle.velocityVehicle.direction[0]Vehicle.direction[1](a channel will be created for each index of an array)Vehicle.vehicle_stateVehicle.propulsion.fuel_levelVehicle.batteries[cpu].voltage(a channel will be created for each key of a map)Vehicle.batteries[cpu].tempVehicle.batteries[propulsion].voltageVehicle.batteries[propulsion].temp
Schema Registration
The gRPC service ProtobufDescriptorService includes an RPC calledAddProtobufDescriptor which registers a protobuf message during ingestion.
Registration Process
- Registration is performed by message type and
namespace, allowing for schema separation between different systems. - The
namespaceis provided when saving descriptors and when ingesting messages. A major usecase ofnamespaceis environment. If a developer wants to iterate on the protobuf definitions without impacting live telemetry, a newnamespacecan segregate these protobuf descriptors and ingestion requests.
Request Structure
- The request takes a
file_descriptor_setfield that should be generated by compiling the protobuf. A simple way to get this is to compile withprotoc:
Versioning
- Adding multiple
ProtobufDescriptorswith the same message type andnamespacestores a new version of descriptor. This is beneficial for managing multiple versions of the same message, especially when newer versions reserve fields that were used by older versions. - When a message is ingested, all stored protobuf descriptor sets for that message type and
namespaceare used to generate channel values. The unique set of channels generated will then be ingested.
Deletion
DeleteProtobufDescriptorsremoves all descriptors for the message type andnamespace.This can be useful for:- Cleaning up test protobuf messages that are no longer in use.
- Simplifying ingestion when a new version of the protobuf message is fully backward compatible. Deleting existing descriptors and adding the latest descriptor can streamline the ingestion process.
- New protobuf descriptors must be backward compatible with existing protobuf descriptors that have the same
message_type_full_nameand are in the samenamespace. - A protobuf descriptor violates backward compatibility when a field name changes e.g. field
velocitywith number1changes tospeed.
You can use the
CheckProtobufDescriptorCompatibility RPC to return incompatibility information.speed with number 2, and reserving the old field. You can optionally delete the old protobuf descriptor with the ID provided in the error message.
AddProtobufDescriptor
For details, see the API docs forprotobuf_descriptors.
DeleteProtobufDescriptors
For details, see the API docs forprotobuf_descriptors.
Data Ingestion
Once the schema has been registered, this protobuf message can be sent toIngestProtobuf endpoint.
The grpc service IngestService has an rpc called IngestArbitraryProtobufDataStream which takes a stream of ingestion request messages to be ingested.
IngestArbitraryProtobufDataStreamRequest
For details, see the API docs forprotobuf_descriptors.
Sift Protobuf Options
To create more descriptive channels, additional options can be added to the protobuf definition. The proto file channel_parsing_options.proto contains the custom message and field options that will add this meta data to the message’s generated channel.- Units and Description: Can be added to a primitive fields to make the units and description available when the channel is displayed
- Bytes Decoding: Can be used to interpret a bytes-typed field as other types, such as UTF-8
- The API provides an enum
BytesDecodingType, including:BYTES_DECODING_TYPE_UNSPECIFIED,BYTES_DECODING_TYPE_UTF8.
- The API provides an enum
- Tags: Can be helpful when a protobuf field path needs additional context from the data to be unique.
- The API includes:
TagSource,TagTarget, enums describing source/target relationships.
- The API includes:
- Map Key Display Overrides: Similar to tags except they replace the display value of a map key. This can be useful when the keys are not human-readable or have transient values.
- The API includes MapKeyOverrideType with values such as:
MAP_KEY_OVERRIDE_TARGETMAP_KEY_OVERRIDE_SOURCEMAP_KEY_OVERRIDE_REMOVE_KEYMAP_KEY_OVERRIDE_ENUM
- The API includes MapKeyOverrideType with values such as:
Tagging example
A tag source identifies a field whose value becomes a tag. It can apply to ancestor fields, sibling fields, or both, depending on configuration. Given the following proto messages, here is an example demonstrating a field acting as the origin of a tag:TestProto.nameTestProto.primary_child.child_nameTestProto.primary_child.map_int_to_message[1].sub_child_nameTestProto.primary_child.map_int_to_message[1].idTestProto.array_of_children[0].child_nameTestProto.array_of_children[0].map_int_to_message[1].sub_child_nameTestProto.array_of_children[0].map_int_to_message[1].idTestProto.type_id
TestProto(type_id:3).nameTestProto(type_id:3).primary_child(kid_name:childname).child_nameTestProto(type_id:3).primary_child(kid_name:childname).map_int_to_message[1].sub_child_name(id:35)TestProto(type_id:3).primary_child(kid_name:childname).map_int_to_message[1].idTestProto(type_id:3).array_of_children[0].child_nameTestProto(type_id:3).array_of_children[0].map_int_to_message[1].sub_child_name(id:35)TestProto(type_id:3).array_of_children[0].map_int_to_message[1].idTestProto(type_id:3).type_id
field_name(field_1:value_1)(field_2:value_2)
Refer to the Channel Parsing Options documentation for more detailed descriptions of how these options are applied.
Map Key and Array Index Override example
Given the following proto messages:TestProto.nameTestProto.map_key_test[0].new_keyTestProto.map_key_test[0].some_valueTestProto.map_key_removal_test[0]TestProto.map_key_enum_test[0]TestProto.array_index_override_test[0].new_indexTestProto.array_index_override_test[0].other_valueTestProto.array_index_override_remove_index[0]TestProto.array_index_enum_test[0]
new_key is my-new-key/my-new-index):
TestProto.nameTestProto.map_key_test[my-new-key].new_keyTestProto.map_key_test[my-new-key].some_valueTestProto.map_key_removal_testTestProto.map_key_enum_test[NONE]TestProto.array_index_override_test[my-new-index].new_indexTestProto.array_index_override_test[my-new-index].other_valueTestProto.array_index_override_remove_indexTestProto.array_index_enum_test[NONE]