De corresponderende JAR file die aangemaakt is voor de nieuwe API werd gebruikt tijdens de tests. Gebruikers verstrekken slechts één simpele class en de gewenste monitor zal direct aangemaakt worden.
Om de resultaten te bekijken, voegt men een Custom Monitor widget toe aan uw Monitis account door middel van het Monitis menu: Manage Monitors à Custom Monitors. Selecteer daarna de custom monitor die is aangemaakt en klik op ‘Add to Window’. (zie bijlage)
Het is ook mogelijk om alle gemeten kolommen weer te geven in een grafiek.
Bovenstaande metingen laten zien dat de gemonitorde Memchaced server perfect werkt. Er is genoeg laadcapaciteit om op te lopen naar 160 verzoeken per minuut.
/**
* Abstract class that provides definitions for Generic Custom Monitor.
* User should extend it for implementing of own custom monitor
*/
public abstract class IGenericCustomMonitor {
/**
* For Monitis API calls you need API key.
* To get your keys log in to your Monitis account
* go to Tools -> API -> API key
*
* get_apiKey() should keep and return your apiKey
* @return - your apiKey
*/
public String get_apiKey() {return null;}
/**
* For Monitis API calls you need Secret key.
* To get your keys log in to your Monitis account
* go to Tools -> API -> API key
*
* get_secretKey() should keep and return your secretKey
* @return - your apiKey
*/
public String get_secretKey() {return null;}
/**
* @return - existing or new custom monitor name
*/
public String get_monitor_name() {return null;}
/**
* @return - existing or new custom monitor tag value
*/
public String get_monitor_tag_value() {return null;}
/**
* The duration interval between sending monitoring result
*
* @return processing time [ms]
*/
public long get_processingTime() {return 60000;/*default - 1 min*/}
/**
* The duration for custom monitor test
*
* @return test duration [ms] (infinitely if returns <= 0)
*/
public long get_testDuration() {return 300000;/*default - 5 min*/}
/**
* The new monitor can have some parameters
*
* Example for preparing parameters
* <pre>
* List<MonitorParameter> monitorParams =
new ArrayList<MonitorParameter>();
* monitorParams.add(new MonitorParameter("Quantity of servers",
"ServersNumber", "5", DataType.INTEGER, true));
* monitorParams.add(new MonitorParameter("password", "Password",
"mypass",
DataType.STRING, true))
* </pre>
*
* @return - new custom monitor list of parameters
* @see MonitorParameter class for details
*/
public List<MonitorParameter> get_monitorParams() {return null;}
/**
* The resulting parameters should be defined for new custom monitor
*
* Example of preparing custom monitor result parameters
* <pre>
* List<MonResultParameter> resultParams =
new ArrayList<MonResultParameter>();
* resultParams.add(new MonResultParameter("cpu", "CPU", "%", DataType.FLOAT));
* resultParams.add(new MonResultParameter("mem", "MEM", "MB", DataType.INTEGER));
* </pre>
*
* @return - new custom monitor list of resulting parameters
* @see MonitorParameter class for details
*/
public List<MonResultParameter> get_resultParams() {return null;}
/**
* The current set of custom monitor results
*
* Example of generating custom monitor results
* <pre>
* String cpu = String.format("%3.1f", (Min + (Math.random() * (Max - Min))));
* String mem = String.format("%2d", (int)(Min + (Math.random() * (Max - Min))));
* List<MonResult> results = new ArrayList<MonResult>();
* results.add(new MonResult("cpu", cpu));
* results.add(new MonResult("mem", mem));
* </pre>
*
* @return custom monitor list of current results set
* @see MonResult class for details
*/
public List<MonResult> get_results() {return null;}
/**
* Monitor can be deleted after series of tests
*
* @return true if custom monitor have to be deleted after test
*/
public boolean deleteMonitor() {return true;/* default value – delete monitor*/}
/**
* Test class will inform about ending test
* by calling this method
*/
public void signal_testEnded(int err_code){ }
}
public class MemcachedMonitor extends IGenericCustomMonitor {
private static final String apiKey = "4DURRI9JDEG5QN394DO14Q9C0D";
private static final String secretKey = "1Q89OGT6BO95J4TH58A56S73T9";
private static final String monitor_name = "Custom_monitor";//Name
private static final String monitor_tag_value = "Memcached_monitor";//Monitor Group
private static String servers = "localhost:11211";//local memcached server
private static final long processingTime = 60;//default value - 60 sec (1 min)
private static final long testDuration = 600;//default value - 600 sec (10 min)
MemcachedClient cache = null;
//storage of previous measured statistics
Map<InetSocketAddress,Map<String,String>> stats_ = new HashMap<InetSocketAddress, Map<String, String>>();
public MemcachedMonitor () throws Exception {
cache = buildMemcachedClient(servers);
}
private MemcachedClient buildMemcachedClient(String servers) throws Exception {
MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(servers));
builder.setCommandFactory(new BinaryCommandFactory());// use binary protocol
return builder.build();
}
public void signal_testEnded(int err_code){
System.exit(err_code);
}
public String get_apiKey() {
return apiKey;
}
public String get_secretKey() {
return secretKey;
}
public String get_monitor_name() {
return monitor_name;
}
public String get_monitor_tag_value() {
return monitor_tag_value;
}
public long get_processingTime() {
return processingTime * 1000;//ms
}
public long get_testDuration() {
return testDuration * 1000;//ms
}
public boolean deleteMonitor() {
return false;
}
public List<MonitorParameter> get_monitorParams() {
return null;
}
public List<MonResultParameter> get_resultParams() {
List<MonResultParameter> resultParams = new ArrayList<MonResultParameter>();
resultParams.add(new MonResultParameter("server", "server", "", DataType.STRING));
resultParams.add(new MonResultParameter("conns", "conns", "", DataType.INTEGER));
resultParams.add(new MonResultParameter("get_hits", "gets [per/s]", "", DataType.INTEGER));
resultParams.add(new MonResultParameter("get_misses", "misses [per/s]", "", DataType.INTEGER));
resultParams.add(new MonResultParameter("reqs", "reqs [per/s]", "", DataType.INTEGER));
resultParams.add(new MonResultParameter("hitratio", "hitratio [%]", "", DataType.FLOAT));
resultParams.add(new MonResultParameter("bytes", "usage [MB]", "MB", DataType.INTEGER));
resultParams.add(new MonResultParameter("usage", "usage [%]", "%", DataType.FLOAT));
resultParams.add(new MonResultParameter("curr_items", "items cached", "",
DataType.INTEGER));
resultParams.add(new MonResultParameter("bytes_read", "bytes read [per/s]", "", DataType.INTEGER));
resultParams.add(new MonResultParameter("bytes_written", "bytes written [per/s]", "", DataType.INTEGER));
resultParams.add(new MonResultParameter("evictions", "evictions [%]", "%",
DataType.FLOAT));
resultParams.add(new MonResultParameter("threads", "threads", "",
DataType.INTEGER));
return resultParams;
}
public List<MonResult> get_results() {
Map<InetSocketAddress,Map<String,String>> stats = null;
int curr_connections, curr_connections_;
int threads, threads_;
int curr_items, curr_items_;
long get_hits, get_hits_;
long get_misses, get_misses_;
long limit_maxbytes, limit_maxbytes_;
long bytes, bytes_;
long bytes_read, bytes_read_;
long bytes_written, bytes_written_;
long evictions, evictions_;
String res;
try {
stats = cache.getStats();// Get current statistics
} catch (Exception e) {
e.printStackTrace();
}
Iterator<InetSocketAddress> it = stats.keySet().iterator();
StringBuffer buf = new StringBuffer();
List<MonResult> results = new ArrayList<MonResult>();
while (it.hasNext()) {
SocketAddress s = it.next();
results.add(new MonResult("server", s.toString()));
buf.append("\n---- Statistics for server ").append(s.toString()).append("\n");
buf.append(TimeUtility.format(TimeUtility.getNowByGMT().getTime(), "yyyy-MM-dd HH:mm:ss"));
//Current results
Map<String, String> stat = stats.get(s);
curr_connections = Integer.parseInt(stat.get("curr_connections")); /*Number of open
connections*/
threads = Integer.parseInt(stat.get("threads")); /*Number of worker threads requested*/
get_hits = Long.parseLong(stat.get("get_hits")); /*Number of keys that have been
requested and found present*/
get_misses = Long.parseLong(stat.get("get_misses")); /*Number of items that have been requested and not found*/
limit_maxbytes = Long.parseLong(stat.get("limit_maxbytes")); /*Number of bytes this
server is allowed to use for storage*/
bytes = Long.parseLong(stat.get("bytes")); /*Current number of bytes used to store items*/
curr_items = Integer.parseInt(stat.get("curr_items")); /*Current number of items
stored*/
bytes_read = Long.parseLong(stat.get("bytes_read"));/*Total number of bytes read
by this server from network*/
bytes_written = Long.parseLong(stat.get("bytes_written"));/*Total number of bytes
sent by this server to network*/
evictions = Long.parseLong(stat.get("evictions"));/*Number of valid items removed
from cache to free memory for new items*/
//previous results
if (stats_.size() <= 0) {
curr_connections_ = threads_ = curr_items_ = 0;
get_hits_ = get_misses_ = limit_maxbytes_ = bytes_ = bytes_read_ = bytes_written_ = evictions_ = 0;
} else {
Map<String, String> stat_ = stats_.get(s);
curr_connections_ = Integer.parseInt(stat_.get("curr_connections")); /*Number of open connections*/
threads_ = Integer.parseInt(stat_.get("threads")); /*Number of worker threads
requested*/
get_hits_ = Long.parseLong(stat_.get("get_hits")); /*Number of keys that have been requested and found present*/
get_misses_ = Long.parseLong(stat_.get("get_misses")); /*Number of items that
have been requested and not found*/
limit_maxbytes_ = Long.parseLong(stat_.get("limit_maxbytes")); /*Number of bytes this server is allowed to use for storage*/
bytes_ = Long.parseLong(stat_.get("bytes")); /*Current number of bytes used to
store items*/
curr_items_ = Integer.parseInt(stat_.get("curr_items")); /*Current number of items stored*/
bytes_read_ = Long.parseLong(stat_.get("bytes_read"));/*Total number of bytes
read by this server from network*/
bytes_written_ = Long.parseLong(stat_.get("bytes_written"));/*Total number of bytes sent by this server to network*/
evictions_ = Long.parseLong(stat_.get("evictions"));/*Number of valid items
removed from cache to free memory for new items*/
}
//Number of open connections
results.add(new MonResult("conns", String.valueOf(curr_connections)));
buf.append("\tconns: ").append(String.valueOf(curr_connections));
//Number of keys that have been requested and found present per sec.
res = String.valueOf((get_hits - get_hits_) / processingTime);
results.add(new MonResult("get_hits", res));
buf.append("\tget_hits: ").append(res);
//Number of items that have been requested and not found per sec.
res = String.valueOf((get_misses - get_misses_) / processingTime);
results.add(new MonResult("get_misses", res));
buf.append("\tget_misses: ").append(res);
//Total number of keys that have been requested per sec.
res = String.valueOf(((get_hits + get_misses)-(get_hits_ + get_misses_)) /
processingTime);
results.add(new MonResult("reqs", res));
buf.append("\treqs: ").append(res);
//Percent of number of keys that have been requested and found present to total
number of keys that have been requested
res = String.format("%3.1f", (get_hits < 1?1: get_hits) * 100.0 / ((get_hits + get_misses) < 1? 1:(get_hits + get_misses)));
results.add(new MonResult("hitratio", res));
buf.append("\thitratio: ").append(res);
//Current number of bytes used to store items [MB]
res = String.format("%5.1f", bytes / 1024.0/1024.0);
results.add(new MonResult("bytes", res));
buf.append("\tbytes: ").append(res);
// Storage usage in percents
res = String.format("%3.1f", (bytes * 100.0) / limit_maxbytes);
results.add(new MonResult("usage", res));
buf.append("\tusage: ").append(res);
//Current number of items stored
results.add(new MonResult("curr_items", String.valueOf(curr_items)));
buf.append("\tcurr_items: ").append(String.valueOf(curr_items));
//Total number of bytes read by this server from network per sec.
res = String.valueOf((bytes_read - bytes_read_) / processingTime);
results.add(new MonResult("bytes_read", res));
buf.append("\tbytes_read: ").append(res);
//Total number of bytes sent by this server to network per sec.
res = String.valueOf((bytes_written - bytes_written_) / processingTime);
results.add(new MonResult("bytes_written", res));
buf.append("\tbytes_written: ").append(res);
// Percent of valid items removed from cache to free memory to current number of items stored
res = String.format("%3.1f", evictions * 100.0 / (curr_items < 1?1:curr_items));
results.add(new MonResult("evictions", res));
buf.append("\tevictions: ").append(res);
//Number of worker threads requested
results.add(new MonResult("threads", String.valueOf(threads)));
buf.append("\tthreads: ").append(String.valueOf(threads));
}
System.out.println(buf.toString());
stats_.putAll(stats);
return results;
}
public static void main(String[] args) {
try {
GenericCustomMonitorRunner tst = new GenericCustomMonitorRunner(new
MemcachedMonitor());
} catch (Exception e) {
System.err.println("Exception while test custom monitor: "+ e.getMessage());
System.exit(0);
}
}
}