messages) {
40 | return messages.stream().filter(message -> message.getUnknownFields().asMap().size() > 0).collect(Collectors.toList());
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/org/raystack/firehose/serializer/JsonWrappedProtoByte.java:
--------------------------------------------------------------------------------
1 | package org.raystack.firehose.serializer;
2 |
3 | import org.raystack.firehose.message.Message;
4 | import org.raystack.firehose.exception.DeserializerException;
5 | import com.google.gson.Gson;
6 | import com.google.gson.GsonBuilder;
7 |
8 | /**
9 | * JsonWrappedProto wrap encoded64 protobuff message into json format. The
10 | * format would look like
11 | *
12 | * {
13 | * "topic":"sample-topic",
14 | * "log_key":"CgYIyOm+xgUSBgiE6r7GBRgNIICAgIDA9/y0LigCMAM\u003d",
15 | * "log_message":"CgYIyOm+xgUSBgiE6r7GBRgNIICAgIDA9/y0LigCMAM\u003d"
16 | * }
17 | *
18 | */
19 | public class JsonWrappedProtoByte implements MessageSerializer {
20 |
21 | private Gson gson;
22 |
23 | /**
24 | * Instantiates a new Json wrapped proto byte.
25 | */
26 | public JsonWrappedProtoByte() {
27 | this.gson = new GsonBuilder().registerTypeAdapter(Message.class, new MessageJsonSerializer()).create();
28 | }
29 |
30 | /**
31 | * Serialize string.
32 | *
33 | * @param message the message
34 | * @return the string
35 | * @throws DeserializerException the deserializer exception
36 | */
37 | @Override
38 | public String serialize(Message message) throws DeserializerException {
39 | return gson.toJson(message);
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/org/raystack/firehose/serializer/MessageJsonSerializer.java:
--------------------------------------------------------------------------------
1 | package org.raystack.firehose.serializer;
2 |
3 | import org.raystack.firehose.message.Message;
4 | import com.google.gson.JsonElement;
5 | import com.google.gson.JsonObject;
6 | import com.google.gson.JsonSerializationContext;
7 | import com.google.gson.JsonSerializer;
8 |
9 | import java.lang.reflect.Type;
10 |
11 | /**
12 | * Message Json serializer serialises Kafka message to json.
13 | */
14 | public class MessageJsonSerializer implements JsonSerializer {
15 |
16 | /**
17 | * Serialize kafka message into json element.
18 | *
19 | * @param message the message
20 | * @param typeOfSrc the type of src
21 | * @param context the context
22 | * @return the json element
23 | */
24 | @Override
25 | public JsonElement serialize(Message message, Type typeOfSrc, JsonSerializationContext context) {
26 | JsonObject object = new JsonObject();
27 | object.addProperty("topic", message.getTopic());
28 | object.addProperty("log_key", message.getSerializedKey());
29 | object.addProperty("log_message", message.getSerializedMessage());
30 | return object;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/org/raystack/firehose/serializer/MessageSerializer.java:
--------------------------------------------------------------------------------
1 | package org.raystack.firehose.serializer;
2 |
3 | import org.raystack.firehose.message.Message;
4 | import org.raystack.firehose.exception.DeserializerException;
5 |
6 | /**
7 | * Serializer serialize Message into string format.
8 | */
9 | public interface MessageSerializer {
10 |
11 | /**
12 | * Serialize kafka message into string.
13 | *
14 | * @param message the message
15 | * @return serialised message
16 | * @throws DeserializerException the deserializer exception
17 | */
18 | String serialize(Message message) throws DeserializerException;
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/org/raystack/firehose/sink/GenericSink.java:
--------------------------------------------------------------------------------
1 | package org.raystack.firehose.sink;
2 |
3 | import org.raystack.depot.Sink;
4 | import org.raystack.depot.SinkResponse;
5 | import org.raystack.firehose.exception.DeserializerException;
6 | import org.raystack.firehose.message.FirehoseMessageUtils;
7 | import org.raystack.firehose.message.Message;
8 | import org.raystack.firehose.metrics.FirehoseInstrumentation;
9 |
10 | import java.io.IOException;
11 | import java.sql.SQLException;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 | import java.util.stream.Collectors;
15 |
16 | public class GenericSink extends AbstractSink {
17 | private final List messageList = new ArrayList<>();
18 | private final Sink sink;
19 |
20 | public GenericSink(FirehoseInstrumentation firehoseInstrumentation, String sinkType, Sink sink) {
21 | super(firehoseInstrumentation, sinkType);
22 | this.sink = sink;
23 | }
24 |
25 | @Override
26 | protected List execute() throws Exception {
27 | List messages = FirehoseMessageUtils.convertToDepotMessage(messageList);
28 | SinkResponse response = sink.pushToSink(messages);
29 | return response.getErrors().keySet().stream()
30 | .map(index -> {
31 | Message message = messageList.get(index.intValue());
32 | message.setErrorInfo(response.getErrorsFor(index));
33 | return message;
34 | }).collect(Collectors.toList());
35 | }
36 |
37 | @Override
38 | protected void prepare(List messages) throws DeserializerException, IOException, SQLException {
39 | messageList.clear();
40 | messageList.addAll(messages);
41 | }
42 |
43 | @Override
44 | public void close() throws IOException {
45 | sink.close();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/org/raystack/firehose/sink/Sink.java:
--------------------------------------------------------------------------------
1 | package org.raystack.firehose.sink;
2 |
3 | import org.raystack.firehose.message.Message;
4 |
5 | import java.io.Closeable;
6 | import java.io.IOException;
7 | import java.util.List;
8 |
9 | /**
10 | * An interface for developing custom Sinks to FirehoseConsumer.
11 | */
12 | public interface Sink extends Closeable {
13 |
14 | /**
15 | * method to write batch of messages read from kafka.
16 | * The logic of how to persist the data goes in here.
17 | * in the future this method should return Response object instead of list of messages
18 | *
19 | * @param message list of {@see EsbMessage}
20 | * @return the list of failed messages
21 | * @throws IOException in case of error conditions while persisting it to the custom sink.
22 | */
23 | List pushMessage(List message) throws IOException;
24 |
25 | /**
26 | * Method that inform that sink is managing kafka offset to be committed by its own.
27 | *
28 | * @return
29 | */
30 | default boolean canManageOffsets() {
31 | return false;
32 | }
33 |
34 | /**
35 | * Method to register kafka offsets and setting it to be committed.
36 | * This method should be implemented when sink manages the commit offsets by themselves.
37 | * Or when {@link Sink#canManageOffsets()} return true
38 | *
39 | * @param messageList messages to be committed
40 | */
41 | default void addOffsetsAndSetCommittable(List messageList) {
42 |
43 | }
44 |
45 | /**
46 | * Method to calculate offsets ready to be committed.
47 | * This method should be implemented when sink manages the commit offsets by themselves.
48 | */
49 | default void calculateCommittableOffsets() {
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/org/raystack/firehose/sink/SinkFactoryUtils.java:
--------------------------------------------------------------------------------
1 | package org.raystack.firehose.sink;
2 |
3 | import org.raystack.depot.message.SinkConnectorSchemaMessageMode;
4 |
5 | import java.util.HashMap;
6 | import java.util.Map;
7 |
8 | public class SinkFactoryUtils {
9 | protected static Map addAdditionalConfigsForSinkConnectors(Map env) {
10 | Map finalConfig = new HashMap<>(env);
11 | finalConfig.put("SINK_CONNECTOR_SCHEMA_PROTO_MESSAGE_CLASS", env.getOrDefault("INPUT_SCHEMA_PROTO_CLASS", ""));
12 | finalConfig.put("SINK_CONNECTOR_SCHEMA_PROTO_KEY_CLASS", env.getOrDefault("INPUT_SCHEMA_PROTO_CLASS", ""));
13 | finalConfig.put("SINK_CONNECTOR_SCHEMA_DATA_TYPE", env.getOrDefault("INPUT_SCHEMA_DATA_TYPE", "protobuf"));
14 | finalConfig.put("SINK_METRICS_APPLICATION_PREFIX", "firehose_");
15 | finalConfig.put("SINK_CONNECTOR_SCHEMA_PROTO_ALLOW_UNKNOWN_FIELDS_ENABLE", env.getOrDefault("INPUT_SCHEMA_PROTO_ALLOW_UNKNOWN_FIELDS_ENABLE", "false"));
16 | finalConfig.put("SINK_CONNECTOR_SCHEMA_MESSAGE_MODE",
17 | env.getOrDefault("KAFKA_RECORD_PARSER_MODE", "").equals("key") ? SinkConnectorSchemaMessageMode.LOG_KEY.name() : SinkConnectorSchemaMessageMode.LOG_MESSAGE.name());
18 | return finalConfig;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/org/raystack/firehose/sink/bigquery/BigquerySinkUtils.java:
--------------------------------------------------------------------------------
1 | package org.raystack.firehose.sink.bigquery;
2 |
3 | import java.util.Map;
4 | import java.util.function.Function;
5 |
6 | public class BigquerySinkUtils {
7 | public static Function