package com.jivesoftware.os.amza.ui.region; import com.google.common.base.Predicates; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.jivesoftware.os.amza.service.AmzaService; import com.jivesoftware.os.amza.service.ring.AmzaRingReader; import com.jivesoftware.os.amza.service.stats.AmzaStats; import com.jivesoftware.os.amza.service.stats.AmzaStats.CompactionStats; import com.jivesoftware.os.amza.ui.soy.SoyRenderer; import com.jivesoftware.os.mlogger.core.MetricLogger; import com.jivesoftware.os.mlogger.core.MetricLoggerFactory; import java.text.NumberFormat; import java.util.List; import java.util.Map; import java.util.concurrent.Executors; import static com.jivesoftware.os.amza.ui.region.MetricsPluginRegion.getDurationBreakdown; /** * */ // soy.page.compactionsPluginRegion public class CompactionsPluginRegion implements PageRegion<CompactionsPluginRegion.CompactionsPluginRegionInput> { private static final MetricLogger LOG = MetricLoggerFactory.getLogger(); private final NumberFormat numberFormat = NumberFormat.getInstance(); private final String template; private final SoyRenderer renderer; private final AmzaRingReader ringReader; private final AmzaService amzaService; private final AmzaStats amzaStats; public CompactionsPluginRegion(String template, SoyRenderer renderer, AmzaRingReader ringReader, AmzaService amzaService, AmzaStats amzaStats) { this.template = template; this.renderer = renderer; this.ringReader = ringReader; this.amzaService = amzaService; this.amzaStats = amzaStats; } public static class CompactionsPluginRegionInput { final String action; final String fromIndexClass; final String toIndexClass; public CompactionsPluginRegionInput(String action, String fromIndexClass, String toIndexClass) { this.action = action; this.fromIndexClass = fromIndexClass; this.toIndexClass = toIndexClass; } } @Override public String render(CompactionsPluginRegionInput input) { Map<String, Object> data = Maps.newHashMap(); try { if (input.action.equals("rebalanceStripes")) { new Thread( () -> { amzaService.rebalanceStripes(); }, "rebalanceStripes" ).start(); } if (input.action.equals("forceCompactionDeltas")) { new Thread( () -> { amzaService.mergeAllDeltas(true); }, "forceCompactionDeltas" ).start(); } if (input.action.equals("forceCompactionTombstones")) { new Thread( () -> { try { amzaService.compactAllTombstones(); } catch (Exception e) { throw new RuntimeException(e); } }, "forceCompactionTombstones" ).start(); } if (input.action.equals("forceExpunge")) { new Thread( () -> { try { amzaService.expunge(); } catch (Exception e) { throw new RuntimeException(e); } }, "forceExpunge" ).start(); } if (input.action.equals("migrateIndexClass")) { amzaService.migrate(input.fromIndexClass, input.toIndexClass); } List<Map.Entry<String, CompactionStats>> ongoingCompactions = amzaStats.ongoingCompactions(AmzaStats.CompactionFamily.values()); data.put("ongoingCompactions", (Object) Iterables.transform(Iterables.filter(ongoingCompactions, Predicates.notNull()), (Map.Entry<String, CompactionStats> input1) -> { return ImmutableMap.of("name", input1.getKey(), "elapse", getDurationBreakdown(input1.getValue().elapse()), "timers", Iterables.transform(Iterables.filter(input1.getValue().getTimings(), Predicates.notNull()), (Map.Entry<String, Long> input2) -> { return ImmutableMap.of("name", input2.getKey(), "value", getDurationBreakdown(input2.getValue())); }), "counters", Iterables.transform(Iterables.filter(input1.getValue().getCounts(), Predicates.notNull()), (Map.Entry<String, Long> input2) -> { return ImmutableMap.of("name", input2.getKey(), "value", numberFormat.format(input2.getValue())); }) ); })); List<Map.Entry<String, CompactionStats>> recentCompaction = amzaStats.recentCompaction(); data.put("recentCompactions", (Object) Iterables.transform(Iterables.filter(recentCompaction, Predicates.notNull()), (Map.Entry<String, CompactionStats> input1) -> { return ImmutableMap.of("name", input1.getKey(), "age", getDurationBreakdown(System.currentTimeMillis() - input1.getValue().startTime()), "duration", getDurationBreakdown(input1.getValue().duration()), "timers", Iterables.transform(Iterables.filter(input1.getValue().getTimings(), Predicates.notNull()), (Map.Entry<String, Long> input2) -> { return ImmutableMap.of("name", input2.getKey(), "value", getDurationBreakdown(input2.getValue())); }), "counters", Iterables.transform(Iterables.filter(input1.getValue().getCounts(), Predicates.notNull()), (Map.Entry<String, Long> input2) -> { return ImmutableMap.of("name", input2.getKey(), "value", numberFormat.format(input2.getValue())); }) ); })); long compactionTotal = 0; for (AmzaStats.CompactionFamily compactionFamily : AmzaStats.CompactionFamily.values()) { compactionTotal += amzaStats.getTotalCompactions(compactionFamily); } data.put("totalCompactions", numberFormat.format(compactionTotal)); } catch (Exception e) { LOG.error("Unable to retrieve data", e); } return renderer.render(template, data); } @Override public String getTitle() { return "Compactions"; } }