load what stats we want to monitor from a config file (harvester.config)
This commit is contained in:
@ -5,6 +5,7 @@ import net.i2p.util.Log;
|
||||
import net.i2p.util.Clock;
|
||||
import java.util.Properties;
|
||||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.Locale;
|
||||
@ -21,8 +22,22 @@ class DataHarvester {
|
||||
private static final Log _log = new Log(DataHarvester.class);
|
||||
private static final DataHarvester _instance = new DataHarvester();
|
||||
public static final DataHarvester getInstance() { return _instance; }
|
||||
/**
|
||||
* Contains the list of StatGroup objects loaded from the harvest.config file
|
||||
* {@see StatGroupLoader} where each statGroup defines a set of stats to pull
|
||||
* from each router's options.
|
||||
*
|
||||
*/
|
||||
private List _statGroups;
|
||||
|
||||
protected DataHarvester() {}
|
||||
/**
|
||||
* Where are we reading the stat groups from? For now, "harvester.config".
|
||||
*/
|
||||
private static final String STAT_GROUP_CONFIG_FILENAME = "harvester.config";
|
||||
|
||||
protected DataHarvester() {
|
||||
_statGroups = StatGroupLoader.loadStatGroups(STAT_GROUP_CONFIG_FILENAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Harvest all of the data from the peers and store it in the monitor.
|
||||
@ -45,9 +60,7 @@ class DataHarvester {
|
||||
_log.info("Harvest the data from " + peer.getIdentity().getHash().toBase64());
|
||||
harvestRank(monitor, peer, peers);
|
||||
harvestRankAs(monitor, peer);
|
||||
harvestEncryptionTime(monitor, peer);
|
||||
harvestDroppedJobs(monitor, peer);
|
||||
harvestProcessingTime(monitor, peer);
|
||||
harvestGroups(monitor, peer);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -138,88 +151,56 @@ class DataHarvester {
|
||||
}
|
||||
|
||||
/**
|
||||
* How long does it take the peer to perform an elGamal encryption? Stored in
|
||||
* the peer summary as "encryptTime", containing 4 doubles (numMs for 1 minute,
|
||||
* quantity in the last minute, numMs for 1 hour, quantity in the last hour)
|
||||
*
|
||||
* @param peer who are we checking the encryption time of
|
||||
* Harvest all data points from the peer
|
||||
*
|
||||
*/
|
||||
private void harvestEncryptionTime(NetMonitor monitor, RouterInfo peer) {
|
||||
double minuteMs = getDouble(peer, "stat_crypto.elGamal.encrypt.60s", 0);
|
||||
double hourMs = getDouble(peer, "stat_crypto.elGamal.encrypt.60m", 0);
|
||||
double minuteQuantity = getDouble(peer, "stat_crypto.elGamal.encrypt.60s", 7);
|
||||
double hourQuantity = getDouble(peer, "stat_crypto.elGamal.encrypt.60m", 7);
|
||||
if ( (minuteMs == -1) || (hourMs == -1) || (minuteQuantity == -1) || (hourQuantity == -1) )
|
||||
return;
|
||||
|
||||
double times[] = new double[4];
|
||||
times[0] = minuteMs;
|
||||
times[1] = minuteQuantity;
|
||||
times[2] = hourMs;
|
||||
times[3] = hourQuantity;
|
||||
|
||||
String description = "how long it takes to do an ElGamal encryption";
|
||||
String valDescr[] = new String[4];
|
||||
valDescr[0] = "encryption time avg ms (minute)";
|
||||
valDescr[1] = "# encryptions (minute)";
|
||||
valDescr[2] = "encryption time avg ms (hour)";
|
||||
valDescr[3] = "# encryptions (hour)";
|
||||
monitor.addData(peer.getIdentity().getHash().toBase64(), "encryptTime", description, valDescr, peer.getPublished(), times);
|
||||
private void harvestGroups(NetMonitor monitor, RouterInfo peer) {
|
||||
_log.debug("Harvesting group data for " + peer.getIdentity().getHash().toBase64());
|
||||
for (int i = 0; i < _statGroups.size(); i++) {
|
||||
StatGroup group = (StatGroup)_statGroups.get(i);
|
||||
harvestGroup(monitor, peer, group);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* How jobs has the peer dropped in the last minute / hour? Stored in
|
||||
* the peer summary as "droppedJobs", containing 2 doubles (num jobs for 1 minute,
|
||||
* num jobs for 1 hour)
|
||||
* Harvest the data points for the given group from the peer and toss them
|
||||
* into the monitor
|
||||
*
|
||||
* @param peer who are we checking the frequency of dropping jobs for
|
||||
*/
|
||||
private void harvestDroppedJobs(NetMonitor monitor, RouterInfo peer) {
|
||||
double minute = getDouble(peer, "stat_jobQueue.droppedJobs.60s", 0);
|
||||
double hour = getDouble(peer, "stat_jobQueue.droppedJobs.60m", 0);
|
||||
double quantity[] = new double[2];
|
||||
quantity[0] = minute;
|
||||
quantity[1] = hour;
|
||||
if ( (minute == -1) || (hour == -1) )
|
||||
return;
|
||||
|
||||
String valDescr[] = new String[2];
|
||||
valDescr[0] = "# dropped jobs (minute)";
|
||||
valDescr[1] = "# dropped jobs (hour)";
|
||||
String description = "how many dropped jobs";
|
||||
monitor.addData(peer.getIdentity().getHash().toBase64(), "droppedJobs", description, valDescr, peer.getPublished(), quantity);
|
||||
private void harvestGroup(NetMonitor monitor, RouterInfo peer, StatGroup group) {
|
||||
_log.debug("Harvesting group data for " + peer.getIdentity().getHash().toBase64() + " / " + group.getDescription());
|
||||
double values[] = harvestGroupValues(peer, group);
|
||||
if (values == null) return;
|
||||
|
||||
String description = "how long it takes to do an ElGamal encryption";
|
||||
String valDescr[] = new String[group.getStatCount()];
|
||||
for (int i = 0; i < group.getStatCount(); i++)
|
||||
valDescr[i] = group.getStat(i).getStatDescription();
|
||||
monitor.addData(peer.getIdentity().getHash().toBase64(), group.getDescription(), group.getDescription(), valDescr, peer.getPublished(), values);
|
||||
}
|
||||
|
||||
/**
|
||||
* How long does it take to process an outbound message? Stored in
|
||||
* the peer summary as "processingTime", containing 4 doubles (avg ms for 1 minute,
|
||||
* num messages for 1 minute, avg ms for 1 hour, num messages for 1 hour)
|
||||
|
||||
/**
|
||||
* Pull up a list of all values associated with the group (in the order that the
|
||||
* group specifies).
|
||||
*
|
||||
* @param peer who are we checking the frequency of dropping jobs for
|
||||
* @return values or null on error
|
||||
*/
|
||||
private void harvestProcessingTime(NetMonitor monitor, RouterInfo peer) {
|
||||
double minuteMs = getDouble(peer, "stat_transport.sendProcessingTime.60s", 0);
|
||||
double minuteFreq = getDouble(peer, "stat_transport.sendProcessingTime.60s", 7);
|
||||
double hourMs = getDouble(peer, "stat_transport.sendProcessingTime.60m", 0);
|
||||
double hourFreq = getDouble(peer, "stat_transport.sendProcessingTime.60m", 7);
|
||||
if ( (minuteMs == -1) || (hourMs == -1) || (minuteFreq == -1) || (hourFreq == -1) )
|
||||
return;
|
||||
|
||||
double times[] = new double[4];
|
||||
times[0] = minuteMs;
|
||||
times[1] = minuteFreq;
|
||||
times[2] = hourMs;
|
||||
times[3] = hourFreq;
|
||||
|
||||
String valDescr[] = new String[4];
|
||||
valDescr[0] = "process time avg ms (minute)";
|
||||
valDescr[1] = "process events (minute)";
|
||||
valDescr[2] = "process time avg ms (hour)";
|
||||
valDescr[3] = "process events (hour)";
|
||||
String description = "how long does it take to process a message";
|
||||
monitor.addData(peer.getIdentity().getHash().toBase64(), "processingTime", description, valDescr, peer.getPublished(), times);
|
||||
private double[] harvestGroupValues(RouterInfo peer, StatGroup group) {
|
||||
List values = new ArrayList(8);
|
||||
for (int i = 0; i < group.getStatCount(); i++) {
|
||||
StatGroup.StatDescription stat = group.getStat(i);
|
||||
double val = getDouble(peer, stat.getOptionName(), stat.getOptionField());
|
||||
if (val == -1)
|
||||
return null;
|
||||
else
|
||||
values.add(new Double(val));
|
||||
}
|
||||
double rv[] = new double[values.size()];
|
||||
for (int i = 0; i < values.size(); i++)
|
||||
rv[i] = ((Double)values.get(i)).doubleValue();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pull a value from the peer's option as a double, assuming the standard semicolon
|
||||
* delimited formatting
|
||||
|
53
apps/netmonitor/java/src/net/i2p/netmonitor/StatGroup.java
Normal file
53
apps/netmonitor/java/src/net/i2p/netmonitor/StatGroup.java
Normal file
@ -0,0 +1,53 @@
|
||||
package net.i2p.netmonitor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Stupid little structure to configure the DataHarvester's gathering of statistics.
|
||||
*
|
||||
*/
|
||||
public class StatGroup {
|
||||
private String _groupDescription;
|
||||
private List _stats;
|
||||
|
||||
public StatGroup(String description) {
|
||||
_groupDescription = description;
|
||||
_stats = new ArrayList();
|
||||
}
|
||||
|
||||
public String getDescription() { return _groupDescription; }
|
||||
public int getStatCount() { return _stats.size(); }
|
||||
public StatDescription getStat(int index) { return (StatDescription)_stats.get(index); }
|
||||
public void addStat(String description, String optionName, int optionField) {
|
||||
StatDescription descr = new StatDescription(description, optionName, optionField);
|
||||
_stats.add(descr);
|
||||
}
|
||||
|
||||
public class StatDescription {
|
||||
private String _statDescription;
|
||||
private String _optionName;
|
||||
private int _optionField;
|
||||
|
||||
public StatDescription(String descr, String optionName, int optionField) {
|
||||
_statDescription = descr;
|
||||
_optionName = optionName;
|
||||
_optionField = optionField;
|
||||
}
|
||||
|
||||
/** brief description of this data point */
|
||||
public String getStatDescription() { return _statDescription; }
|
||||
/**
|
||||
* if this is harvested from the RouterInfo's options, this specifies
|
||||
* which key in that map to pull from (or null if it isn't harvested
|
||||
* from there)
|
||||
*/
|
||||
public String getOptionName() { return _optionName; }
|
||||
/**
|
||||
* if this is harvested from the RouterInfo's options, this specifies
|
||||
* which field in value of that map to pull from (or -1 if it isn't harvested
|
||||
* from there)
|
||||
*/
|
||||
public int getOptionField() { return _optionField; }
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package net.i2p.netmonitor;
|
||||
|
||||
|
||||
import net.i2p.util.Log;
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Load up the StatGroups from the location specified to configure the data harvester.
|
||||
* The stat groups are formatted in a simple properties file style, e.g.: <pre>
|
||||
* # dropped jobs
|
||||
* statGroup.0.name=droppedJobs
|
||||
* statGroup.0.detail.0.name=num dropped jobs (minute)
|
||||
* statGroup.0.detail.0.option=stat_jobQueue.droppedJobs.60m
|
||||
* statGroup.0.detail.0.field=3
|
||||
* statGroup.0.detail.1.name=num dropped jobs (hour)
|
||||
* statGroup.0.detail.1.option=stat_jobQueue.droppedJobs.60h
|
||||
* statGroup.0.detail.1.field=3
|
||||
* #
|
||||
* statGroup.1.name=encryptTime
|
||||
* statGroup.1.detail.0.name=encryption time avg ms (minute)
|
||||
* statGroup.1.detail.0.option=stat_crypto.elGamal.encrypt.60s
|
||||
* statGroup.1.detail.0.field=0
|
||||
* statGroup.1.detail.1.name=num encryptions (minute)
|
||||
* statGroup.1.detail.1.option=stat_crypto.elGamal.encrypt.60s
|
||||
* statGroup.1.detail.1.field=7
|
||||
* statGroup.1.detail.2.name=encryption time avg ms (hour)
|
||||
* statGroup.1.detail.2.option=stat_crypto.elGamal.encrypt.60s
|
||||
* statGroup.1.detail.2.field=0
|
||||
* statGroup.1.detail.3.name=num encryptions (hour)
|
||||
* statGroup.1.detail.3.option=stat_crypto.elGamal.encrypt.60s
|
||||
* statGroup.1.detail.3.field=7
|
||||
* </pre>
|
||||
*/
|
||||
class StatGroupLoader {
|
||||
private static final Log _log = new Log(StatGroupLoader.class);
|
||||
/**
|
||||
* Load a list of stat groups from the file specified
|
||||
*
|
||||
* @return list of StatGroup objects
|
||||
*/
|
||||
public static List loadStatGroups(String filename) {
|
||||
_log.debug("Loading stat groups from " + filename);
|
||||
FileInputStream fis = null;
|
||||
File f = new File(filename);
|
||||
try {
|
||||
fis = new FileInputStream(f);
|
||||
Properties p = new Properties();
|
||||
p.load(fis);
|
||||
_log.debug("Config loaded from " + filename);
|
||||
return loadStatGroups(p);
|
||||
} catch (IOException ioe) {
|
||||
_log.error("Error loading the stat groups from " + f.getAbsolutePath(), ioe);
|
||||
return new ArrayList();
|
||||
}
|
||||
}
|
||||
|
||||
private static List loadStatGroups(Properties props) {
|
||||
List rv = new ArrayList(8);
|
||||
int groupNum = 0;
|
||||
while (true) {
|
||||
String description = props.getProperty("statGroup." + groupNum + ".name");
|
||||
if (description == null) break;
|
||||
int detailNum = 0;
|
||||
StatGroup group = new StatGroup(description);
|
||||
while (true) {
|
||||
String detailPrefix = "statGroup." + groupNum + ".detail." + detailNum + '.';
|
||||
String name = props.getProperty(detailPrefix + "name");
|
||||
if (name == null) break;
|
||||
String option = props.getProperty(detailPrefix + "option");
|
||||
if (option == null) break;
|
||||
String field = props.getProperty(detailPrefix + "field");
|
||||
if (field == null) break;
|
||||
try {
|
||||
int fieldNum = Integer.parseInt(field);
|
||||
group.addStat(name, option, fieldNum);
|
||||
} catch (NumberFormatException nfe) {
|
||||
_log.warn("Unable to parse the field number from [" + field + "]", nfe);
|
||||
break;
|
||||
}
|
||||
detailNum++;
|
||||
}
|
||||
rv.add(group);
|
||||
groupNum++;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user