/* * #%L * Wisdom-Framework * %% * Copyright (C) 2013 - 2015 Wisdom Framework * %% * 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% */ package org.wisdom.monitor.extensions.executors; import com.codahale.metrics.*; import com.google.common.collect.ImmutableMap; import org.apache.felix.ipojo.annotations.Bind; import org.apache.felix.ipojo.annotations.Requires; import org.apache.felix.ipojo.annotations.Validate; import org.wisdom.api.DefaultController; import org.wisdom.api.annotations.Controller; import org.wisdom.api.annotations.Route; import org.wisdom.api.annotations.View; import org.wisdom.api.concurrent.ManagedExecutorService; import org.wisdom.api.concurrent.ManagedScheduledExecutorService; import org.wisdom.api.http.HttpMethod; import org.wisdom.api.http.Result; import org.wisdom.api.security.Authenticated; import org.wisdom.api.templates.Template; import org.wisdom.monitor.service.MonitorExtension; import java.util.*; /** * Monitor extension for executors and schedulers. */ @Controller @Authenticated("Monitor-Authenticator") public class ExecutorExtension extends DefaultController implements MonitorExtension { @Requires ManagedExecutorService[] executors; @Requires ManagedScheduledExecutorService[] schedulers; @Requires MetricRegistry metrics; @View("monitor/executors") Template template; /** * Starts the extension. It registers the different metrics into the metric registry. */ @Validate public void start() { metrics.register("executors", new MetricSet() { @Override public Map<String, Metric> getMetrics() { return ImmutableMap.<String, Metric>of( "executors.count", new Gauge<Integer>() { @Override public Integer getValue() { return getExecutors().length; } }, "schedulers.count", new Gauge<Integer>() { @Override public Integer getValue() { return getSchedulers().length; } }, "hung.count", new Gauge<Integer>() { @Override public Integer getValue() { return getHungTasks(); } }, "completed.count", new Gauge<Integer>() { @Override public Integer getValue() { return getCompletedTasks(); } } ); } }); for (ManagedExecutorService service : executors) { metrics.register(service.name(), metricsForExecutor(service)); } for (ManagedExecutorService service : schedulers) { metrics.register(service.name(), metricsForExecutor(service)); } } private MetricSet metricsForExecutor(final ManagedExecutorService executor) { return new MetricSet() { @Override public Map<String, Metric> getMetrics() { return ImmutableMap.<String, Metric>builder() .put("queue", new Gauge<Integer>() { @Override public Integer getValue() { return executor.getQueue().size(); } }) .put("completed", new Counter() { @Override public long getCount() { return executor.getCompletedTaskCount(); } }) .put("hung", new Gauge<Integer>() { @Override public Integer getValue() { return executor.getHungTasks().size(); } }) .put("active", new Gauge<Integer>() { @Override public Integer getValue() { return executor.getActiveCount(); } }) .put("pool", new Gauge<Integer>() { @Override public Integer getValue() { return executor.getPoolSize(); } }) .put("largest", new Gauge<Integer>() { @Override public Integer getValue() { return executor.getLargestPoolSize(); } }) .put("max_exec", new Gauge<Long>() { @Override public Long getValue() { return executor.getExecutionTimeStatistics().getMaximumExecutionTime(); } }) .put("total", new Gauge<Long>() { @Override public Long getValue() { return executor.getExecutionTimeStatistics().getTotalExecutionTime(); } }) .put("min_exec", new Gauge<Long>() { @Override public Long getValue() { return executor.getExecutionTimeStatistics().getMinimumExecutionTime(); } }) .put("avg", new Gauge<Double>() { @Override public Double getValue() { return executor.getExecutionTimeStatistics().getAverageExecutionTime(); } }) .build(); } }; } private ManagedExecutorService[] getExecutors() { return executors; } private ManagedScheduledExecutorService[] getSchedulers() { return schedulers; } /** * Gets the extension main view. * * @return the executors page. */ @Route(method = HttpMethod.GET, uri = "/monitor/executors") public Result index() { return ok(render(template)); } /** * Retrieves the metrics about the executors. This method is intended to be used to handled an AJAX call. * @return the metrics as JSON. */ @Route(method = HttpMethod.GET, uri = "/monitor/executors.json") public Result data() { return ok(ImmutableMap.builder() .put("executors", getExecutorsAsMap(executors)) .put("schedulers", getExecutorsAsMap(schedulers)) .put("hung", getHungTasks()) .put("completed", getCompletedTasks()) .build() ); } private Map<String, ManagedExecutorService> getExecutorsAsMap(ManagedExecutorService[] exec) { Map<String, ManagedExecutorService> map = new LinkedHashMap<>(); for (ManagedExecutorService svc : exec) { map.put(svc.name(), svc); } return map; } private int getHungTasks() { int count = 0; for (ManagedExecutorService svc : executors) { count += svc.getHungTasks().size(); } for (ManagedScheduledExecutorService svc : schedulers) { count += svc.getHungTasks().size(); } return count; } private int getCompletedTasks() { int count = 0; for (ManagedExecutorService svc : executors) { count += svc.getCompletedTaskCount(); } for (ManagedScheduledExecutorService svc : schedulers) { count += svc.getCompletedTaskCount(); } return count; } /** * @return the label displayed in the menu. */ @Override public String label() { return "Executors"; } /** * @return the url of the extension page. */ @Override public String url() { return "/monitor/executors"; } /** * @return the category of the extension such as "root", "wisdom" or "OSGi". */ @Override public String category() { return "wisdom"; } }