package de.is24.util.monitoring.state2graphite; import de.is24.util.monitoring.InApplicationMonitor; import de.is24.util.monitoring.MultiValueProvider; import de.is24.util.monitoring.Reportable; import de.is24.util.monitoring.ReportableObserver; import de.is24.util.monitoring.State; import de.is24.util.monitoring.StateValueProvider; import de.is24.util.monitoring.keyhandler.KeyDefinitionExpander; import de.is24.util.monitoring.tools.LocalHostNameResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collection; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class StateValuesToGraphite implements ReportableObserver { private static final Logger LOGGER = LoggerFactory.getLogger(StateValuesToGraphite.class); private ScheduledExecutorService ex; private Map<String, StateValueProvider> stateValues; private Map<String, MultiValueProvider> multiValueProviders; private GraphiteConnection graphiteClient; public StateValuesToGraphite(String graphiteHost, int graphitePort, String appName) { this(appName, new LocalHostNameResolver(), new GraphiteConnection(graphiteHost, graphitePort)); } StateValuesToGraphite(String appName, LocalHostNameResolver localHostNameResolver, GraphiteConnection graphiteClient) { this.graphiteClient = graphiteClient; String keyPrefix = KeyDefinitionExpander.preparePrefix(appName, localHostNameResolver); stateValues = new ConcurrentHashMap<String, StateValueProvider>(); multiValueProviders = new ConcurrentHashMap<String, MultiValueProvider>(); InApplicationMonitor.getInstance().getCorePlugin().addReportableObserver(this); ex = Executors.newSingleThreadScheduledExecutor(); ex.scheduleAtFixedRate(new ReportStateValuesJob(graphiteClient, keyPrefix), 1, 10, TimeUnit.SECONDS); } @Override public void addNewReportable(Reportable reportable) { if (reportable instanceof StateValueProvider) { stateValues.put(reportable.getName(), (StateValueProvider) reportable); } else if (reportable instanceof MultiValueProvider) { multiValueProviders.put(reportable.getName(), (MultiValueProvider) reportable); } } public long multiValueProviderCount() { return multiValueProviders.size(); } public void shutdown() { InApplicationMonitor.getInstance().getCorePlugin().removeReportableObserver(this); ex.shutdown(); } private class ReportStateValuesJob implements Runnable { private final GraphiteConnection graphiteClient; private final String keyPrefix; public ReportStateValuesJob(GraphiteConnection graphiteClient, String keyPrefix) { this.graphiteClient = graphiteClient; this.keyPrefix = keyPrefix; } @Override public void run() { LOGGER.debug("writing {} state values to graphite", stateValues.size()); Long curTimeInSec = System.currentTimeMillis() / 1000; StringBuilder lines = new StringBuilder(); addStateValues(curTimeInSec, lines); addMultiStates(curTimeInSec, lines); graphiteClient.send(lines.toString()); } private void addStateValues(Long curTimeInSec, StringBuilder lines) { for (StateValueProvider stateValueProvider : stateValues.values()) { try { StringBuilder line = new StringBuilder(); line.append(keyPrefix) .append(".") .append(stateValueProvider.getName()) .append(" ") .append(stateValueProvider.getValue()) .append(" ") .append(curTimeInSec) .append("\n"); // only add complete lines if getValue throws Exception lines.append(line.toString()); } catch (Exception e) { LOGGER.warn("getting StateValue failed for {}", stateValueProvider.getName()); } } } private void addMultiStates(Long curTimeInSec, StringBuilder lines) { for (MultiValueProvider multiValueProvider : multiValueProviders.values()) { Collection<State> values = multiValueProvider.getValues(); for (State state : values) { StringBuilder line = new StringBuilder(); line.append(keyPrefix) .append(".") .append(multiValueProvider.getName()) .append(".") .append(state.name) .append(" ") .append(state.value) .append(" ") .append(curTimeInSec) .append("\n"); lines.append(line.toString()); } } } } @Override public String toString() { return "StateValuesToGraphite:" + graphiteClient.toString(); } }