/*******************************************************************************
* Copyright (c) 2011 The Board of Trustees of the Leland Stanford Junior University
* as Operator of the SLAC National Accelerator Laboratory.
* Copyright (c) 2011 Brookhaven National Laboratory.
* EPICS archiver appliance is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*******************************************************************************/
package org.epics.archiverappliance.engine.bpl.reports;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.epics.archiverappliance.common.BPLAction;
import org.epics.archiverappliance.config.ConfigService;
import org.epics.archiverappliance.engine.model.ArchiveChannel;
import org.epics.archiverappliance.engine.pv.EngineContext;
import org.epics.archiverappliance.engine.pv.PVMetrics;
import org.epics.archiverappliance.utils.ui.MimeTypeConstants;
import org.json.simple.JSONValue;
/**
* We collect many metrics during archiving in the PVMetrics objects. Most of these are doubles/longs.
* We should be able to report on these metrics using a generic framework.
* This is the superclass for such a framework.
* Subclass this and then register the subclass in the BPL...
* @author mshankar
*
*/
public class GenericPVMetricsReport<T extends Number> implements BPLAction {
private static final Logger logger = Logger.getLogger(GenericPVMetricsReport.class);
private Function<PVMetrics, T> getFn;
private final String metricName;
private String applianceName;
public GenericPVMetricsReport(Function<PVMetrics, T> getFn, String metricName) {
this.getFn = getFn;
this.metricName = metricName;
}
@Override
public void execute(HttpServletRequest req, HttpServletResponse resp,
ConfigService configService) throws IOException {
String limit = req.getParameter("limit");
logger.info(metricName + " report for " + (limit == null ? "default limit " : ("limit " + limit)));
resp.setContentType(MimeTypeConstants.APPLICATION_JSON);
List<HashMap<String, String>> result = applyMetric(configService, limit);
try (PrintWriter out = resp.getWriter()) {
out.println(JSONValue.toJSONString(result));
}
}
private List<HashMap<String, String>> applyMetric(ConfigService configService, String limitStr) {
this.applianceName = configService.getMyApplianceInfo().getIdentity();
HashMap<String, T> pvs2Rate = new HashMap<String, T>();
EngineContext engineContext = configService.getEngineContext();
for(ArchiveChannel channel : engineContext.getChannelList().values()) {
pvs2Rate.put(channel.getName(), this.getFn.apply(channel.getPVMetrics()));
}
int limitNum = pvs2Rate.size();
if(limitStr != null) {
limitNum = Integer.parseInt(limitStr);
}
List<HashMap<String, String>> retVal = pvs2Rate.entrySet()
.stream()
.filter(new Predicate<Entry<String, T>>() { // Get rid of entries that have 0
@Override
public boolean test(Entry<String, T> t) {
return t.getValue().doubleValue() > 0;
}
})
.sorted(Map.Entry.comparingByValue(Collections.reverseOrder()))
.limit(limitNum)
.map(new Function<Entry<String, T>, HashMap<String, String>>() {
@Override
public HashMap<String, String> apply(Entry<String, T> t) {
HashMap<String, String> ret = new HashMap<String, String>();
ret.put("pvName", t.getKey());
ret.put("instance", GenericPVMetricsReport.this.applianceName);
ret.put(metricName, t.getValue().toString());
return ret;
}
})
.collect(Collectors.toList());
return retVal;
}
}