/* * 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. */ package org.apache.usergrid.persistence.qakka.serialization.auditlog.impl; import com.datastax.driver.core.PagingState; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Statement; import com.datastax.driver.core.querybuilder.QueryBuilder; import com.google.inject.Inject; import org.apache.usergrid.persistence.core.CassandraConfig; import org.apache.usergrid.persistence.core.astyanax.MultiTenantColumnFamilyDefinition; import org.apache.usergrid.persistence.core.datastax.TableDefinition; import org.apache.usergrid.persistence.core.datastax.impl.TableDefinitionStringImpl; import org.apache.usergrid.persistence.qakka.core.CassandraClient; import org.apache.usergrid.persistence.qakka.serialization.Result; import org.apache.usergrid.persistence.qakka.serialization.auditlog.AuditLog; import org.apache.usergrid.persistence.qakka.serialization.auditlog.AuditLogSerialization; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.UUID; import java.util.stream.Collectors; public class AuditLogSerializationImpl implements AuditLogSerialization { private static final Logger logger = LoggerFactory.getLogger( AuditLogSerializationImpl.class ); private final CassandraClient cassandraClient; private final CassandraConfig cassandraConfig; public final static String TABLE_AUDIT_LOG = "audit_log"; public final static String COLUMN_ACTION = "action"; public final static String COLUMN_STATUS = "status"; public final static String COLUMN_QUEUE_NAME = "queue_name"; public final static String COLUMN_REGION = "region"; public final static String COLUMN_MESSAGE_ID = "message_id"; public final static String COLUMN_QUEUE_MESSAGE_ID = "queue_message_id"; public final static String COLUMN_TRANSFER_TIME = "transfer_time"; // design note: want to be able to query this by message_id, so we can do "garbage collection" // of message data items that have been processed in all target regions static final String CQL = "CREATE TABLE IF NOT EXISTS audit_log ( " + "action text, " + "status text, " + "queue_name text, " + "region text, " + "message_id timeuuid, " + "queue_message_id timeuuid, " + "transfer_time bigint, " + "PRIMARY KEY (message_id, transfer_time) " + ") WITH CLUSTERING ORDER BY (transfer_time ASC); "; @Inject public AuditLogSerializationImpl( CassandraConfig cassandraConfig, CassandraClient cassandraClient ) { this.cassandraConfig = cassandraConfig; this.cassandraClient = cassandraClient; } @Override public void recordAuditLog( AuditLog.Action action, AuditLog.Status status, String queueName, String region, UUID messageId, UUID queueMessageId ) { Statement insert = QueryBuilder.insertInto(TABLE_AUDIT_LOG) .value(COLUMN_ACTION, action.toString() ) .value(COLUMN_STATUS, status.toString() ) .value(COLUMN_QUEUE_NAME, queueName ) .value(COLUMN_REGION, region ) .value(COLUMN_MESSAGE_ID, messageId ) .value(COLUMN_QUEUE_MESSAGE_ID, queueMessageId ) .value(COLUMN_TRANSFER_TIME, System.currentTimeMillis() ); cassandraClient.getApplicationSession().execute(insert); } @Override public Result<AuditLog> getAuditLogs( UUID messageId ) { Statement query = QueryBuilder.select().all().from(TABLE_AUDIT_LOG) .where( QueryBuilder.eq( COLUMN_MESSAGE_ID, messageId ) ); ResultSet rs = cassandraClient.getApplicationSession().execute( query ); final List<AuditLog> auditLogs = rs.all().stream().map( row -> new AuditLog( AuditLog.Action.valueOf( row.getString( COLUMN_ACTION )), AuditLog.Status.valueOf( row.getString( COLUMN_STATUS )), row.getString( COLUMN_QUEUE_NAME ), row.getString( COLUMN_REGION ), row.getUUID( COLUMN_MESSAGE_ID ), row.getUUID( COLUMN_QUEUE_MESSAGE_ID ), row.getLong( COLUMN_TRANSFER_TIME ) ) ).collect( Collectors.toList() ); return new Result<AuditLog>() { @Override public PagingState getPagingState() { return null; // no paging } @Override public List<AuditLog> getEntities() { return auditLogs; } }; } @Override public Collection<MultiTenantColumnFamilyDefinition> getColumnFamilies() { return Collections.EMPTY_LIST; } @Override public Collection<TableDefinition> getTables() { return Collections.singletonList( new TableDefinitionStringImpl( cassandraConfig.getApplicationKeyspace(), TABLE_AUDIT_LOG, CQL ) ); } }