package com.sumologic.client.implementations; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Queue; import org.apache.log4j.Logger; import com.sumologic.client.SumologicSender; import com.sumologic.client.KinesisConnectorForSumologicConfiguration; import com.amazonaws.services.kinesis.connectors.KinesisConnectorConfiguration; import com.amazonaws.services.kinesis.connectors.UnmodifiableBuffer; import com.amazonaws.services.kinesis.connectors.interfaces.IEmitter; /** * This class is used to store records from a stream to Sumologic log files. It requires the use of a * SumologicTransformer, which is able to transform records into a format that can be sent to * Sumologic. */ public class SumologicEmitter implements IEmitter<String> { private static final Logger LOG = Logger.getLogger(SumologicEmitter.class.getName()); private SumologicSender sender; private KinesisConnectorForSumologicConfiguration config; private static final boolean SEND_RECORDS_IN_BATCHES = true; private long batchSize = 1000L; public SumologicEmitter(KinesisConnectorConfiguration configuration) { this.config = (KinesisConnectorForSumologicConfiguration) configuration; sender = new SumologicSender(this.config.SUMOLOGIC_URL); batchSize = this.config.BUFFER_RECORD_COUNT_LIMIT; } public SumologicEmitter(String url) { sender = new SumologicSender(url); } @Override public List<String> emit(final UnmodifiableBuffer<String> buffer) throws IOException { List<String> records = buffer.getRecords(); if (SEND_RECORDS_IN_BATCHES) { return sendBatchConcatenating(records); } else { return sendRecordsOneByOne(records); } } public List<String> sendBatchConcatenating(List<String> records) { boolean success = false; List<String> failedRecords = new ArrayList<String>(); List<String> currentBatch = new ArrayList<String>(); Queue<String> unprocessedRecords = new LinkedList<String>(records); String message = ""; int recordCount = 0; for(String record: records) { currentBatch.add(record); unprocessedRecords.poll(); message += record; message += "\n"; recordCount++; if (recordCount >= batchSize) { try { LOG.info("Sending batch of: "+recordCount+" records"); success = sender.sendToSumologic(message); } catch (IOException e) { LOG.warn("Couldn't send batch of " + recordCount + " record to Sumologic: "+e.getMessage()); success = false; } if (!success) { failedRecords.addAll(currentBatch); failedRecords.addAll(unprocessedRecords); return failedRecords; } currentBatch = new ArrayList<String>(); recordCount = 0; message = ""; } } try { LOG.info("Sending batch of: "+recordCount+" records"); success = sender.sendToSumologic(message); } catch (IOException e) { LOG.warn("Couldn't send record to Sumologic: "+e.getMessage()); success = false; } if (!success) { failedRecords.addAll(currentBatch); failedRecords.addAll(unprocessedRecords); return failedRecords; } return failedRecords; } public List<String> sendRecordsOneByOne (List<String> records) { ArrayList<String> failedRecords = new ArrayList<String>(); for (String record: records) { try { if (!sender.sendToSumologic(record)) { failedRecords.add(record); } } catch (IOException e) { LOG.warn("Couldn't send record: "+record); } } LOG.info("Sent records: "+(records.size()-failedRecords.size())+" failed: "+failedRecords.size()); return failedRecords; } @Override public void fail(List<String> records) { for (String record : records) { LOG.error("Could not emit record: " + record); } } @Override public void shutdown() { } }