package com.cookpad.puree; import com.google.gson.Gson; import com.google.gson.JsonObject; import com.cookpad.puree.outputs.PureeOutput; import com.cookpad.puree.storage.PureeStorage; import com.cookpad.puree.storage.Records; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; @ParametersAreNonnullByDefault public class PureeLogger { final Gson gson; final Map<Class<?>, List<PureeOutput>> sourceOutputMap = new HashMap<>(); final PureeStorage storage; final ScheduledExecutorService executor; public PureeLogger(Map<Class<?>, List<PureeOutput>> sourceOutputMap, Gson gson, PureeStorage storage, ScheduledExecutorService executor) { this.sourceOutputMap.putAll(sourceOutputMap); this.gson = gson; this.storage = storage; this.executor = executor; forEachOutput(new PureeLogger.Consumer<PureeOutput>() { @Override public void accept(@Nonnull PureeOutput value) { value.initialize(PureeLogger.this); } }); } public void send(PureeLog log) { List<PureeOutput> outputs = getRegisteredOutputPlugins(log); for (PureeOutput output : outputs) { JsonObject jsonLog = serializeLog(log); output.receive(jsonLog); } } public PureeStorage getStorage() { return storage; } public ScheduledExecutorService getExecutor() { return executor; } public Records getBufferedLogs() { return storage.selectAll(); } public void discardBufferedLogs() { storage.clear(); } public void truncateBufferedLogs(int truncateThresholdInRows) { storage.truncateBufferedLogs(truncateThresholdInRows); } public void flush() { forEachOutput(new PureeLogger.Consumer<PureeOutput>() { @Override public void accept(@Nonnull PureeOutput value) { value.flush(); } }); } /** * Serialize a {@link PureeLog} into {@link JsonObject} with {@link Gson}. * * @param log {@link PureeLog}. * @return serialized json object. */ @Nonnull public JsonObject serializeLog(PureeLog log) { return (JsonObject) gson.toJsonTree(log); } @Nonnull public List<PureeOutput> getRegisteredOutputPlugins(PureeLog log) { return getRegisteredOutputPlugins(log.getClass()); } @Nonnull public List<PureeOutput> getRegisteredOutputPlugins(Class<? extends PureeLog> logClass) { List<PureeOutput> outputs = sourceOutputMap.get(logClass); if (outputs == null) { throw new NoRegisteredOutputPluginException("No output plugin registered for " + logClass); } return outputs; } public interface Consumer<T> { void accept(@Nonnull T value); } public void forEachOutput(Consumer<PureeOutput> f) { for (List<PureeOutput> outputs : new HashSet<>(sourceOutputMap.values())) { for (PureeOutput output : outputs) { f.accept(output); } } } public static class NoRegisteredOutputPluginException extends IllegalStateException { public NoRegisteredOutputPluginException(String detailMessage) { super(detailMessage); } } }