package org.ff4j.elastic.store;
/*
* #%L
* ff4j-store-elastic
* %%
* Copyright (C) 2013 - 2016 FF4J
* %%
* 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.
* #L%
*/
import static org.ff4j.audit.EventConstants.ACTION_CLEAR;
import static org.ff4j.audit.EventConstants.ACTION_CREATE;
import static org.ff4j.audit.EventConstants.ACTION_DELETE;
import static org.ff4j.audit.EventConstants.ACTION_DISCONNECT;
import static org.ff4j.audit.EventConstants.ACTION_TOGGLE_OFF;
import static org.ff4j.audit.EventConstants.ACTION_TOGGLE_ON;
import static org.ff4j.audit.EventConstants.ACTION_UPDATE;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.ff4j.audit.Event;
import org.ff4j.audit.EventConstants;
import org.ff4j.audit.EventQueryDefinition;
import org.ff4j.audit.EventSeries;
import org.ff4j.audit.MutableHitCount;
import org.ff4j.audit.chart.TimeSeriesChart;
import org.ff4j.audit.repository.AbstractEventRepository;
import org.ff4j.elastic.ElasticConnection;
import org.ff4j.elastic.ElasticQueryBuilder;
import org.ff4j.utils.Util;
import io.searchbox.client.JestResult;
import io.searchbox.core.SearchResult;
import io.searchbox.core.SearchResult.Hit;
public class EventRepositoryElastic extends AbstractEventRepository {
private ElasticConnection connection;
/** Connection to ElasticSearch query builder */
private ElasticQueryBuilder builder;
public EventRepositoryElastic(ElasticConnection connection) {
this.connection = connection;
}
@Override
public boolean saveEvent(Event event) {
Util.assertEvent(event);
JestResult result = getConnection().execute(getBuilder().queryCreateEvent(event));
return (result != null && result.isSucceeded());
}
@Override
public Event getEventByUUID(String uuid, Long timestamp) {
return getConnection().execute(getBuilder().queryGetEventById(uuid)).getSourceAsObject(Event.class);
}
@Override
public Map<String, MutableHitCount> getFeatureUsageHitCount(EventQueryDefinition query) {
JestResult result = getConnection()
.execute(getBuilder().queryGetEventQueryDefinition(query, EventConstants.ACTION_CHECK_OK));
List<Event> events = result.getSourceAsObjectList(Event.class);
Map<String, MutableHitCount> hitCount = new HashMap<String, MutableHitCount>();
for (Event event : events) {
String name = event.getName();
if (hitCount.containsKey(name)) {
hitCount.get(name).inc();
} else {
hitCount.put(name, new MutableHitCount(1));
}
}
return hitCount;
}
@Override
public TimeSeriesChart getFeatureUsageHistory(EventQueryDefinition query, TimeUnit units) {
// Create the interval depending on units
TimeSeriesChart tsc = new TimeSeriesChart(query.getFrom(), query.getTo(), units);
// Search All events
Iterator<Event> iterEvent = searchFeatureUsageEvents(query).iterator();
// Dispatch events into time slots
while (iterEvent.hasNext()) {
tsc.addEvent(iterEvent.next());
}
return tsc;
}
@Override
public EventSeries searchFeatureUsageEvents(EventQueryDefinition query) {
JestResult result = getConnection()
.execute(getBuilder().queryGetEventQueryDefinition(query, EventConstants.ACTION_CHECK_OK));
List<Event> events = result.getSourceAsObjectList(Event.class);
EventSeries es = new EventSeries();
for (Event event : events) {
es.add(event);
}
return es;
}
@Override
public void purgeFeatureUsage(EventQueryDefinition query) {
this.purgeAuditTrail(query);
}
@Override
public Map<String, MutableHitCount> getHostHitCount(EventQueryDefinition query) {
JestResult result = getConnection()
.execute(getBuilder().queryGetEventQueryDefinition(query, EventConstants.ACTION_CHECK_OK));
List<Event> events = result.getSourceAsObjectList(Event.class);
Map<String, MutableHitCount> hitCount = new HashMap<String, MutableHitCount>();
for (Event event : events) {
String hostName = event.getHostName();
if (hitCount.containsKey(hostName)) {
hitCount.get(hostName).inc();
} else {
hitCount.put(hostName, new MutableHitCount(1));
}
}
return hitCount;
}
@Override
public Map<String, MutableHitCount> getUserHitCount(EventQueryDefinition query) {
JestResult result = getConnection()
.execute(getBuilder().queryGetEventQueryDefinition(query, EventConstants.ACTION_CHECK_OK));
List<Event> events = result.getSourceAsObjectList(Event.class);
Map<String, MutableHitCount> hitCount = new HashMap<String, MutableHitCount>();
for (Event event : events) {
String user = event.getUser();
if (hitCount.containsKey(user)) {
hitCount.get(user).inc();
} else {
hitCount.put(user, new MutableHitCount(1));
}
}
return hitCount;
}
@Override
public Map<String, MutableHitCount> getSourceHitCount(EventQueryDefinition query) {
JestResult result = getConnection()
.execute(getBuilder().queryGetEventQueryDefinition(query, EventConstants.ACTION_CHECK_OK));
List<Event> events = result.getSourceAsObjectList(Event.class);
Map<String, MutableHitCount> hitCount = new HashMap<String, MutableHitCount>();
for (Event event : events) {
String source = event.getSource();
if (hitCount.containsKey(source)) {
hitCount.get(source).inc();
} else {
hitCount.put(source, new MutableHitCount(1));
}
}
return hitCount;
}
@Override
public EventSeries getAuditTrail(EventQueryDefinition query) {
JestResult result = getConnection().execute(getBuilder().queryGetEventQueryDefinition(query));
List<Event> events = result.getSourceAsObjectList(Event.class);
EventSeries es = new EventSeries();
Set<String> candidates = Util.set(ACTION_DISCONNECT, //
ACTION_TOGGLE_ON, ACTION_TOGGLE_OFF, ACTION_CREATE, //
ACTION_DELETE, ACTION_UPDATE, ACTION_CLEAR);
for (Event event : events) {
if (candidates.contains(event.getAction()))
es.add(event);
}
return es;
}
@Override
public void purgeAuditTrail(EventQueryDefinition query) {
SearchResult result = getConnection().search(getBuilder().queryReadAllEvents(), true);
if (result != null && result.isSucceeded()) {
for (Hit<Event, Void> event : result.getHits(Event.class)) {
getConnection().execute(getBuilder().queryDeleteEvent(event.source.getUuid()));
}
}
}
@Override
public void createSchema() {
getConnection().execute(getBuilder().queryFlushIndex());
}
/**
* Getter accessor for attribute 'connection'.
*
* @return current value of 'connection'
*/
public ElasticConnection getConnection() {
return connection;
}
/**
* Setter accessor for attribute 'connection'.
*
* @param connection
* new value for 'connection '
*/
public void setConnection(ElasticConnection connection) {
this.connection = connection;
}
/**
* Getter accessor for attribute 'builder'.
*
* @return current value of 'builder'
*/
public ElasticQueryBuilder getBuilder() {
if (builder == null) {
builder = new ElasticQueryBuilder(connection);
}
return builder;
}
}