/*
* Copyright © 2016 Cask Data, Inc.
*
* Licensed 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.
*/
package co.cask.cdap.data2.audit;
import co.cask.cdap.common.conf.CConfiguration;
import co.cask.cdap.common.conf.Constants;
import co.cask.cdap.proto.audit.AuditMessage;
import co.cask.cdap.proto.audit.AuditPayload;
import co.cask.cdap.proto.audit.AuditType;
import co.cask.cdap.proto.id.EntityId;
import co.cask.cdap.security.spi.authentication.SecurityRequestContext;
import com.google.common.base.Charsets;
import com.google.common.base.Objects;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.gson.Gson;
import com.google.inject.Inject;
import org.apache.twill.kafka.client.Compression;
import org.apache.twill.kafka.client.KafkaClient;
import org.apache.twill.kafka.client.KafkaPublisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
/**
* Publish audit messages on Kafka.
*/
public class KafkaAuditPublisher implements AuditPublisher {
private static final Logger LOG = LoggerFactory.getLogger(KafkaAuditPublisher.class);
private static final Gson GSON = new Gson();
private final Supplier<KafkaPublisher> publisherSupplier;
private final String kafkaTopic;
@Inject
public KafkaAuditPublisher(final KafkaClient kafkaClient, CConfiguration cConf) {
this.publisherSupplier = Suppliers.memoize(new Supplier<KafkaPublisher>() {
@Override
public KafkaPublisher get() {
return kafkaClient.getPublisher(KafkaPublisher.Ack.LEADER_RECEIVED, Compression.SNAPPY);
}
});
this.kafkaTopic = cConf.get(Constants.Audit.KAFKA_TOPIC);
}
@Override
public void publish(EntityId entityId, AuditType auditType, AuditPayload auditPayload) {
String userId = Objects.firstNonNull(SecurityRequestContext.getUserId(), "");
AuditMessage auditMessage = new AuditMessage(System.currentTimeMillis(), entityId, userId, auditType, auditPayload);
LOG.trace("Publishing audit message {}", auditMessage);
try {
ByteBuffer message = Charsets.UTF_8.encode((GSON.toJson(auditMessage)));
KafkaPublisher.Preparer preparer = publisherSupplier.get().prepare(kafkaTopic);
preparer.add(message, entityId);
preparer.send().get();
} catch (Exception e) {
LOG.error("Got exception publishing audit message {}. Exception:", auditMessage, e);
}
}
}