/******************************************************************************* * 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.epics; import java.text.DecimalFormat; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.log4j.Logger; import org.epics.archiverappliance.config.ConfigService; import org.epics.archiverappliance.engine.metadata.MetaGet; import org.epics.archiverappliance.engine.model.ArchiveChannel; import org.epics.archiverappliance.engine.pv.EngineContext; import org.epics.archiverappliance.engine.pv.PVContext; import org.epics.archiverappliance.engine.pv.PVMetrics; import org.json.simple.JSONAware; import org.json.simple.JSONValue; /** * POJO with some basic metrics. * @author mshankar * */ public class EngineMetrics implements JSONAware { private static final Logger logger = Logger.getLogger(EngineMetrics.class); private int pvCount; private int connectedPVCount; private int disconnectedPVCount; private int pausedPVCount; private int totalEPICSChannels; private double eventRate; private double dataRate; private double secondsConsumedByWritter=0.00; //private static Logger logger=Logger.getLogger(EngineMetrics.class.getName()); public double getSecondsConsumedByWritter() { return secondsConsumedByWritter; } public void setSecondsConsumedByWritter(double secondsConsumedByWritter) { this.secondsConsumedByWritter = secondsConsumedByWritter; } public double getEventRate() { return eventRate; } public void setEventRate(double eventRate) { this.eventRate = eventRate; } public double getDataRate() { return dataRate; } public void setDataRate(double dataRate) { this.dataRate = dataRate; } public int getPvCount() { return pvCount; } public void setPvCount(int pvCount) { this.pvCount = pvCount; } public int getDisconnectedPVCount() { return disconnectedPVCount; } public void setDisconnectedPVCount(int disconnectedPVCount) { this.disconnectedPVCount = disconnectedPVCount; } @Override public String toJSONString() { DecimalFormat twoSignificantDigits = new DecimalFormat("###,###,###,###,###,###.##"); HashMap<String, String> engineMetrics = new HashMap<String, String>(); engineMetrics.put("eventRate", twoSignificantDigits.format(eventRate)); engineMetrics.put("dataRate", twoSignificantDigits.format(dataRate)); engineMetrics.put("dataRateGBPerDay", twoSignificantDigits.format((dataRate*60*60*24)/(1024*1024*1024))); engineMetrics.put("dataRateGBPerYear", twoSignificantDigits.format((dataRate*60*60*24*365)/(1024*1024*1024))); engineMetrics.put("pvCount", Integer.toString(pvCount)); engineMetrics.put("connectedPVCount", Integer.toString(connectedPVCount)); engineMetrics.put("disconnectedPVCount", Integer.toString(disconnectedPVCount)); engineMetrics.put("formattedWriteThreadSeconds", twoSignificantDigits.format(secondsConsumedByWritter)); engineMetrics.put("secondsConsumedByWritter", Double.toString(secondsConsumedByWritter)); return JSONValue.toJSONString(engineMetrics); } public String getDetails(EngineContext context) { DecimalFormat twoSignificantDigits = new DecimalFormat("###,###,###,###,###,###.##"); LinkedList<Map<String, String>> details = new LinkedList<Map<String, String>>(); addDetailedStatus(details, "Total PV count", Integer.toString(pvCount)); addDetailedStatus(details, "Disconnected PV count", Integer.toString(disconnectedPVCount)); addDetailedStatus(details, "Connected PV count", Integer.toString(connectedPVCount)); addDetailedStatus(details, "Paused PV count", Integer.toString(pausedPVCount)); addDetailedStatus(details, "Total channels", Integer.toString(totalEPICSChannels)); addDetailedStatus(details, "Approx pending jobs in engine queue", Long.toString((context.getScheduler().getQueue().size()))); addDetailedStatus(details, "Event Rate (in events/sec)", twoSignificantDigits.format(eventRate)); addDetailedStatus(details, "Data Rate (in bytes/sec)", twoSignificantDigits.format(dataRate)); addDetailedStatus(details, "Data Rate in (GB/day)", twoSignificantDigits.format((dataRate*60*60*24)/(1024*1024*1024))); addDetailedStatus(details, "Data Rate in (GB/year)", twoSignificantDigits.format((dataRate*60*60*24*365)/(1024*1024*1024))); addDetailedStatus(details, "Time consumed for writing samplebuffers to STS (in secs)", twoSignificantDigits.format(secondsConsumedByWritter)); if(secondsConsumedByWritter != 0) { double writesPerSec = eventRate * context.getWritePeriod() / secondsConsumedByWritter; double writeBytesPerSec = (dataRate * context.getWritePeriod() / secondsConsumedByWritter)/(1024*1024); addDetailedStatus(details, "Benchmark - writing at (events/sec)", twoSignificantDigits.format(writesPerSec)); addDetailedStatus(details, "Benchmark - writing at (MB/sec)", twoSignificantDigits.format(writeBytesPerSec)); } addDetailedStatus(details, "PVs pending computation of meta info", Integer.toString(MetaGet.getPendingMetaGetsSize())); addDetailedStatus(details, "Total number of reference counted channels", Integer.toString(PVContext.getChannelCount())); addDetailedStatus(details, "Total number of CAJ channels", Integer.toString(context.getCAJChannelCount())); return JSONValue.toJSONString(details); } private static void addDetailedStatus(LinkedList<Map<String, String>> details, String name, String value) { Map<String, String> obj = new LinkedHashMap<String, String>(); obj.put("name", name); obj.put("value", value); obj.put("source", "engine"); details.add(obj); } public static EngineMetrics computeEngineMetrics(EngineContext engineContext, ConfigService configService) { EngineMetrics engineMetrics = new EngineMetrics(); // Event rate is in events/sec double eventRate = 0.0; // Data rate is in bytes/sec double dataRate = 0.0; int connectedChannels = 0; int disconnectedChannels = 0; int totalChannels = 0; Set<String> pausedPVs = configService.getPausedPVsInThisAppliance(); Iterator<Entry<String, ArchiveChannel>> it=engineContext.getChannelList().entrySet().iterator(); while(it.hasNext()){ Entry<String, ArchiveChannel> tempEntry=it.next(); ArchiveChannel channel=tempEntry.getValue(); String pvName = channel.getName(); try { if(pausedPVs.contains(pvName)) { // Skipping paused PV. continue; } PVMetrics pvMetrics = channel.getPVMetrics(); totalChannels++; if(pvMetrics==null) { disconnectedChannels++; continue; } if(!pvMetrics.isConnected()) { disconnectedChannels++; } else { connectedChannels++; } eventRate += pvMetrics.getEventRate(); dataRate += pvMetrics.getStorageRate(); } catch(Exception ex) { logger.error("Exception computing engine metrics for PV " + channel.getName(), ex); } } engineMetrics.setEventRate(eventRate); engineMetrics.setDataRate(dataRate); engineMetrics.setPvCount(totalChannels); engineMetrics.setConnectedPVCount(connectedChannels); engineMetrics.setDisconnectedPVCount(disconnectedChannels); engineMetrics.setPausedPVCount(pausedPVs.size()); int totalchannelCount = engineContext.getChannelList().size(); for(ArchiveChannel archiveChannel : engineContext.getChannelList().values()) { totalchannelCount += archiveChannel.getMetaChannelCount(); } engineMetrics.setTotalEPICSChannels(totalchannelCount); engineMetrics.setSecondsConsumedByWritter(engineContext.getAverageSecondsConsumedByWritter()); return engineMetrics; } public int getConnectedPVCount() { return connectedPVCount; } public void setConnectedPVCount(int connectedPVCount) { this.connectedPVCount = connectedPVCount; } public int getTotalEPICSChannels() { return totalEPICSChannels; } public void setTotalEPICSChannels(int totalEPICSChannels) { this.totalEPICSChannels = totalEPICSChannels; } /** * @return the pausedPVCount */ public int getPausedPVCount() { return pausedPVCount; } /** * @param pausedPVCount the pausedPVCount to set */ public void setPausedPVCount(int pausedPVCount) { this.pausedPVCount = pausedPVCount; } }