2018-12-13 14:47:20 -05:00
---
2019-08-21 00:48:59 -04:00
id: protobuf
2018-12-13 14:47:20 -05:00
title: "Protobuf"
---
2018-11-13 12:38:37 -05:00
<!--
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
~ distributed with this work for additional information
~ regarding copyright ownership. The ASF licenses this file
~ to you under the Apache License, Version 2.0 (the
~ "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
2017-05-30 16:11:58 -04:00
2020-01-03 12:33:19 -05:00
This Apache Druid extension enables Druid to ingest and understand the Protobuf data format. Make sure to [include ](../../development/extensions.md#loading-extensions ) `druid-protobuf-extensions` as an extension.
2017-05-30 16:11:58 -04:00
2020-01-17 18:52:05 -05:00
The `druid-protobuf-extensions` provides the [Protobuf Parser ](../../ingestion/data-formats.md#protobuf-parser )
for [stream ingestion ](../../ingestion/index.md#streaming ). See corresponding docs for details.
2017-05-30 16:11:58 -04:00
## Example: Load Protobuf messages from Kafka
2020-02-07 12:26:52 -05:00
This example demonstrates how to load Protobuf messages from Kafka. Please read the [Load from Kafka tutorial ](../../tutorials/tutorial-kafka.md ) first, and see [Kafka Indexing Service ](./kafka-ingestion.md ) documentation for more details.
2017-05-30 16:11:58 -04:00
2020-02-07 12:26:52 -05:00
The files used in this example are found at [`./examples/quickstart/protobuf` in your Druid directory ](https://github.com/apache/druid/tree/master/examples/quickstart/protobuf ).
2017-05-30 16:11:58 -04:00
2020-02-07 12:26:52 -05:00
For this example:
- Kafka broker host is `localhost:9092`
- Kafka topic is `metrics_pb`
- Datasource name is `metrics-protobuf`
2017-05-30 16:11:58 -04:00
2020-02-07 12:26:52 -05:00
Here is a JSON example of the 'metrics' data schema used in the example.
2017-05-30 16:11:58 -04:00
```json
{
"unit": "milliseconds",
"http_method": "GET",
"value": 44,
"timestamp": "2017-04-06T02:36:22Z",
"http_code": "200",
"page": "/",
"metricType": "request/latency",
"server": "www1.example.com"
}
```
### Proto file
2020-02-07 12:26:52 -05:00
The corresponding proto file for our 'metrics' dataset looks like this.
2017-05-30 16:11:58 -04:00
```
syntax = "proto3";
message Metrics {
string unit = 1;
string http_method = 2;
int32 value = 3;
string timestamp = 4;
string http_code = 5;
string page = 6;
string metricType = 7;
string server = 8;
}
```
### Descriptor file
2020-02-07 12:26:52 -05:00
Next, we use the `protoc` Protobuf compiler to generate the descriptor file and save it as `metrics.desc` . The descriptor file must be either in the classpath or reachable by URL. In this example the descriptor file was saved at `/tmp/metrics.desc` , however this file is also available in the example files. From your Druid install directory:
2017-05-30 16:11:58 -04:00
```
2020-02-07 12:26:52 -05:00
protoc -o /tmp/metrics.desc ./quickstart/protobuf/metrics.proto
2017-05-30 16:11:58 -04:00
```
2020-02-07 12:26:52 -05:00
## Create Kafka Supervisor
2017-05-30 16:11:58 -04:00
Below is the complete Supervisor spec JSON to be submitted to the Overlord.
2020-02-07 12:26:52 -05:00
Make sure these keys are properly configured for successful ingestion.
2017-05-30 16:11:58 -04:00
2020-02-07 12:26:52 -05:00
Important supervisor properties
- `descriptor` for the descriptor file URL
- `protoMessageType` from the proto definition
- `parser` should have `type` set to `protobuf` , but note that the `format` of the `parseSpec` must be `json`
2017-05-30 16:11:58 -04:00
```json
{
"type": "kafka",
"dataSchema": {
2020-02-07 12:26:52 -05:00
"dataSource": "metrics-protobuf",
2017-05-30 16:11:58 -04:00
"parser": {
"type": "protobuf",
"descriptor": "file:///tmp/metrics.desc",
"protoMessageType": "Metrics",
"parseSpec": {
"format": "json",
"timestampSpec": {
"column": "timestamp",
"format": "auto"
},
"dimensionsSpec": {
"dimensions": [
"unit",
"http_method",
"http_code",
"page",
"metricType",
"server"
],
"dimensionExclusions": [
"timestamp",
"value"
]
}
}
},
"metricsSpec": [
{
"name": "count",
"type": "count"
},
{
"name": "value_sum",
"fieldName": "value",
"type": "doubleSum"
},
{
"name": "value_min",
"fieldName": "value",
"type": "doubleMin"
},
{
"name": "value_max",
"fieldName": "value",
"type": "doubleMax"
}
],
"granularitySpec": {
"type": "uniform",
"segmentGranularity": "HOUR",
"queryGranularity": "NONE"
}
},
"tuningConfig": {
"type": "kafka",
"maxRowsPerSegment": 5000000
},
"ioConfig": {
"topic": "metrics_pb",
"consumerProperties": {
"bootstrap.servers": "localhost:9092"
},
"taskCount": 1,
"replicas": 1,
"taskDuration": "PT1H"
}
}
```
2020-02-07 12:26:52 -05:00
## Adding Protobuf messages to Kafka
2017-05-30 16:11:58 -04:00
2020-02-07 12:26:52 -05:00
If necessary, from your Kafka installation directory run the following command to create the Kafka topic
2017-05-30 16:11:58 -04:00
2020-02-07 12:26:52 -05:00
```
./bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic metrics_pb
```
This example script requires `protobuf` and `kafka-python` modules. With the topic in place, messages can be inserted running the following command from your Druid installation directory
```
./bin/generate-example-metrics | ./quickstart/protobuf/pb_publisher.py
```
You can confirm that data has been inserted to your Kafka topic using the following command from your Kafka installation directory
```
./bin/kafka-console-consumer --zookeeper localhost --topic metrics_pb
```
2017-05-30 16:11:58 -04:00
2020-02-07 12:26:52 -05:00
which should print messages like this
2017-05-30 16:11:58 -04:00
2020-02-07 12:26:52 -05:00
```
millisecondsGETR"2017-04-06T03:23:56Z*2002/list:request/latencyBwww1.example.com
```
If your supervisor created in the previous step is running, the indexing tasks should begin producing the messages and the data will soon be available for querying in Druid.
## Generating the example files
The files provided in the example quickstart can be generated in the following manner starting with only `metrics.proto` .
### `metrics.desc`
The descriptor file is generated using `protoc` Protobuf compiler. Given a `.proto` file, a `.desc` file can be generated like so.
```
protoc -o metrics.desc metrics.proto
```
### `metrics_pb2.py`
`metrics_pb2.py` is also generated with `protoc`
```
protoc -o metrics.desc metrics.proto --python_out=.
```
### `pb_publisher.py`
After `metrics_pb2.py` is generated, another script can be constructed to parse JSON data, convert it to Protobuf, and produce to a Kafka topic
2017-05-30 16:11:58 -04:00
```python
#!/usr/bin/env python
import sys
import json
from kafka import KafkaProducer
from metrics_pb2 import Metrics
2020-02-07 12:26:52 -05:00
2017-05-30 16:11:58 -04:00
producer = KafkaProducer(bootstrap_servers='localhost:9092')
topic = 'metrics_pb'
for row in iter(sys.stdin):
d = json.loads(row)
2020-02-07 12:26:52 -05:00
metrics = Metrics()
2017-05-30 16:11:58 -04:00
for k, v in d.items():
setattr(metrics, k, v)
pb = metrics.SerializeToString()
producer.send(topic, pb)
2020-02-07 12:26:52 -05:00
producer.flush()
2019-08-21 00:48:59 -04:00
```