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.
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 for 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 affecting live telemetry, a newnamespacecan segregate these protobuf descriptors and ingestion requests.
Request Structure
- The request takes a
file_descriptor_setfield which should be generated by compiling the protobuf. A simple way to get this is to compile withprotoc:
Versioning
- Adding multiple ProtobufDescriptors with the same message type and
namespacewill store 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
namespacewill be used to generate channel values. The unique set of channels generated will then be ingested.
Deletion
DeleteProtobufDescriptorswill remove all descriptors for the message type andnamespace.This might 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.
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
| Field | Type | Description |
|---|---|---|
| message_type_full_name | string | The fully qualified message type name, including the package |
| namespace | string | The namespace for this message |
| file_descriptor_set | bytes | The compiled bytes of the file descriptor set for the protobuf message |
| proto_file_name | string | The filename containing the protobuf message |
DeleteProtobufDescriptors
| Field | Type | Description |
|---|---|---|
| message_type_full_name | string | The fully qualified message type name, including the package |
| namespace | string | The namespace for this message |
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
| Field | Type | Description |
|---|---|---|
| message_type_identifier | string | The fully qualified message type name, including the package |
| namespace | string | The namespace of the protobuf message |
| message_type_display_name | string | (Optional) This will replace the message name in the channel name. It can be useful if the same message is reused by different sources |
| asset_name | string | The name of the asset that is the source of this telemetry |
| timestamp | google.protobuf.Timestamp | The timestamp of the telemetry points |
| value | bytes | The serialized bytes of the protobuf message |
| run_id | string | The optional id of the run that is associated with this telemetry point |
Sift Protobuf Options
To allow for creating more descriptive channels, some 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 & Description - These options can be added to a primitive fields so that the units and description will be available when the channel is displayed
- Bytes Decoding - This option can be used to interpret a bytes typed field as other types like utf-8
- Tags - This can be helpful when a protobuf field path needs additional context from the data to be unique
- Map Key Display Overrides - These options are similar to tags except that they will replace the display value of a map key. This can be useful when the keys are not human-readable or have transient values
Tagging example
Given the following proto messages: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 & 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]