package org.eluder.logback.ext.kinesis.appender; import ch.qos.logback.core.spi.DeferredProcessingAware; import com.amazonaws.regions.RegionUtils; import com.amazonaws.services.kinesis.AmazonKinesisAsyncClient; import com.amazonaws.services.kinesis.model.PutRecordRequest; import com.amazonaws.services.kinesis.model.PutRecordResult; import com.amazonaws.util.StringUtils; import org.eluder.logback.ext.aws.core.AbstractAwsEncodingStringAppender; import org.eluder.logback.ext.aws.core.LoggingEventHandler; import org.eluder.logback.ext.core.AppenderExecutors; import org.eluder.logback.ext.core.ByteArrayPayloadConverter; import java.nio.ByteBuffer; import java.util.UUID; import java.util.concurrent.CountDownLatch; import static java.lang.String.format; public class KinesisAppender<E extends DeferredProcessingAware> extends AbstractAwsEncodingStringAppender<E, byte[]> { private String region; private String stream; private AmazonKinesisAsyncClient kinesis; public final void setRegion(String region) { this.region = region; } public final void setStream(String stream) { this.stream = stream; } @Override public void start() { if (RegionUtils.getRegion(region) == null) { addError(format("Region not set or invalid for appender '%s'", getName())); return; } if (StringUtils.isNullOrEmpty(stream)) { addError(format("Stream not set for appender '%s", getName())); return; } setConverter(new ByteArrayPayloadConverter()); super.start(); } @Override protected void doStart() { kinesis = new AmazonKinesisAsyncClient( getCredentials(), getClientConfiguration(), AppenderExecutors.newExecutor(this, getThreadPoolSize()) ); kinesis.setRegion(RegionUtils.getRegion(region)); } @Override protected void doStop() { if (kinesis != null) { AppenderExecutors.shutdown(this, kinesis.getExecutorService(), getMaxFlushTime()); kinesis.shutdown(); kinesis = null; } } @Override protected void handle(E event, byte[] encoded) throws Exception { ByteBuffer buffer = ByteBuffer.wrap(encoded); PutRecordRequest request = new PutRecordRequest() .withPartitionKey(getPartitionKey(event)) .withStreamName(stream) .withData(buffer); String errorMessage = format("Appender '%s' failed to send logging event '%s' to Kinesis stream '%s'", getName(), event, stream); CountDownLatch latch = new CountDownLatch(isAsyncParent() ? 0 : 1); kinesis.putRecordAsync(request, new LoggingEventHandler<PutRecordRequest, PutRecordResult>(this, latch, errorMessage)); AppenderExecutors.awaitLatch(this, latch, getMaxFlushTime()); } protected String getPartitionKey(E event) { return UUID.randomUUID().toString(); } }