use of ddf.metrics.reporting.internal.MetricsGraphException in project ddf by codice.
the class MetricsEndpoint method getMetricsData.
/**
* Retrieve data for the specified metric over the given time range. The URL to access this
* method is of the form http://<host>:<port>/<metricName>.<outputFormat> So the desired metric
* filename is specified in the URL, e.g., catalogQueryCount.png, where the filename extension
* defines the desired output format returned for the metric's data. Currently supported formats
* are png, csv, xls, ppt, xml, and json.
* <p>
* Note that the time range can be specified as either a start and end date (in RFC3339 format,
* i.e., YYYY-MM-DD'T'hh:mm:ssZ), or as an offset in seconds from the current time. These 2 time
* range mechanisms cannot be combined, e.g., you cannot specify an end date and an offset to be
* applied from that end date.
* <p>
* By default, the metric's name will be used for the y-axis label on the PNG graph, and the
* metric name and time range will be used for the graph's title. Both of these can be
* optionally specified with the yAxisLabel and title parameters. These 2 parameters do not
* apply for the other formats.
*
* @param metricName Name of the metric being graphed, e.g., queryCount
* @param outputFormat output format of the metric, e.g. csv
* @param startDate Specifies the start of the time range of the search on the metric's data (RFC-3339
* - Date and Time format, i.e. YYYY-MM-DDTHH:mm:ssZ). Cannot be used with dateOffset
* parameter.
* @param endDate Specifies the end of the time range of the search on the metric's data (RFC-3339 -
* Date and Time format, i.e. YYYY-MM-DDTHH:mm:ssZ). Cannot be used with dateOffset
* parameter.
* @param dateOffset Specifies an offset, backwards from the current time, to search on the modified
* time field for entries. Defined in seconds. Cannot be used with startDate and
* endDate parameters.
* @param yAxisLabel (optional) the label to apply to the graph's y-axis
* @param title (optional) the title to be applied to the graph
* @param uriInfo
* @return Response containing the metric's data in the specified outputFormat
* @throws MetricsEndpointException
*/
@GET
@Path("/{metricName}.{outputFormat}")
public Response getMetricsData(@PathParam("metricName") String metricName, @PathParam("outputFormat") String outputFormat, @QueryParam("startDate") String startDate, @QueryParam("endDate") String endDate, @QueryParam("dateOffset") String dateOffset, @QueryParam("yAxisLabel") String yAxisLabel, @QueryParam("title") String title, @Context UriInfo uriInfo) throws MetricsEndpointException {
LOGGER.trace("ENTERING: getMetricsData - metricName = {}, outputFormat = {}", metricName, outputFormat);
LOGGER.trace("request url: {}", uriInfo.getRequestUri());
LOGGER.trace("startDate = {}, endDate = {}", startDate, endDate);
LOGGER.trace("dateOffset = {}", dateOffset);
Response response = null;
// Client must specify *either* startDate and/or endDate *OR* dateOffset
if (!StringUtils.isBlank(dateOffset) && (!StringUtils.isBlank(startDate) || !StringUtils.isBlank(endDate))) {
throw new MetricsEndpointException("Cannot specify dateOffset and startDate or endDate, must specify either dateOffset only or startDate and/or endDate", Response.Status.BAD_REQUEST);
}
long endTime;
if (!StringUtils.isBlank(endDate)) {
endTime = parseDate(endDate);
LOGGER.trace("Parsed endTime = {}", endTime);
} else {
// Default end time for metrics graphing to now (in seconds)
Calendar now = getCalendar();
endTime = now.getTimeInMillis() / MILLISECONDS_PER_SECOND;
LOGGER.trace("Defaulted endTime to {}", endTime);
// Set endDate to new calculated endTime (so that endDate is displayed properly
// in graph's title)
endDate = dateFormatter.format(now.getTime());
}
long startTime;
if (!StringUtils.isBlank(startDate)) {
startTime = parseDate(startDate);
LOGGER.trace("Parsed startTime = {}", startTime);
} else if (!StringUtils.isBlank(dateOffset)) {
startTime = endTime - Long.parseLong(dateOffset);
LOGGER.trace("Offset-computed startTime = {}", startTime);
// Set startDate to new calculated startTime (so that startDate is displayed properly
// in graph's title)
Calendar cal = getCalendar();
cal.setTimeInMillis(startTime * MILLISECONDS_PER_SECOND);
startDate = dateFormatter.format(cal.getTime());
} else {
// Default start time for metrics graphing to end time last 24 hours (in seconds)
startTime = endTime - ONE_DAY_IN_SECONDS;
LOGGER.trace("Defaulted startTime to {}", startTime);
// Set startDate to new calculated startTime (so that startDate is displayed properly
// in graph's title)
Calendar cal = getCalendar();
cal.setTimeInMillis(startTime * MILLISECONDS_PER_SECOND);
startDate = dateFormatter.format(cal.getTime());
}
LOGGER.trace("startDate = {}, endDate = {}", startDate, endDate);
if (StringUtils.isBlank(yAxisLabel)) {
yAxisLabel = RrdMetricsRetriever.convertCamelCase(metricName);
}
if (StringUtils.isBlank(title)) {
title = RrdMetricsRetriever.convertCamelCase(metricName) + " for " + startDate + " to " + endDate;
}
// Convert metric filename to rrd filename (because RRD file required by MetricRetriever to
// generate graph)
String rrdFilename = metricsDir + metricName + RRD_FILE_EXTENSION;
if (outputFormat.equalsIgnoreCase(PNG_FORMAT)) {
LOGGER.trace("Retrieving PNG-formatted data for metric {}", metricName);
try {
byte[] metricsGraphBytes = metricsRetriever.createGraph(metricName, rrdFilename, startTime, endTime, yAxisLabel, title);
ByteArrayInputStream bis = new ByteArrayInputStream(metricsGraphBytes);
response = Response.ok(bis, PNG_MIME_TYPE).build();
} catch (IOException | MetricsGraphException e) {
LOGGER.info("Could not create graph for metric {}", metricName);
throw new MetricsEndpointException("Cannot create metrics graph for specified metric.", Response.Status.BAD_REQUEST);
}
} else if (outputFormat.equalsIgnoreCase("csv")) {
try {
String csv = metricsRetriever.createCsvData(rrdFilename, startTime, endTime);
ResponseBuilder responseBuilder = Response.ok(csv);
responseBuilder.type("text/csv");
response = responseBuilder.build();
} catch (IOException | MetricsGraphException e) {
LOGGER.info("Could not create CSV data for metric {}", metricName);
throw new MetricsEndpointException("Cannot create CSV data for specified metric.", Response.Status.BAD_REQUEST);
}
} else if (outputFormat.equalsIgnoreCase("xls")) {
LOGGER.trace("Retrieving XLS-formatted data for metric {}", metricName);
try {
OutputStream os = metricsRetriever.createXlsData(metricName, rrdFilename, startTime, endTime);
InputStream is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray());
ResponseBuilder responseBuilder = Response.ok(is);
responseBuilder.type("application/vnd.ms-excel");
response = responseBuilder.build();
} catch (IOException | MetricsGraphException e) {
LOGGER.info("Could not create XLS data for metric {}", metricName);
throw new MetricsEndpointException("Cannot create XLS data for specified metric.", Response.Status.BAD_REQUEST);
}
} else if (outputFormat.equalsIgnoreCase("ppt")) {
LOGGER.trace("Retrieving PPT-formatted data for metric {}", metricName);
try {
OutputStream os = metricsRetriever.createPptData(metricName, rrdFilename, startTime, endTime);
InputStream is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray());
ResponseBuilder responseBuilder = Response.ok(is);
responseBuilder.type("application/vnd.ms-powerpoint");
response = responseBuilder.build();
} catch (IOException | MetricsGraphException e) {
LOGGER.info("Could not create PPT data for metric {}", metricName);
throw new MetricsEndpointException("Cannot create PPT data for metric for specified metric.", Response.Status.BAD_REQUEST);
}
} else if (outputFormat.equalsIgnoreCase("xml")) {
LOGGER.trace("Retrieving XML-formatted data for metric {}", metricName);
try {
String xmlData = metricsRetriever.createXmlData(metricName, rrdFilename, startTime, endTime);
ResponseBuilder responseBuilder = Response.ok(xmlData);
responseBuilder.type("text/xml");
response = responseBuilder.build();
} catch (IOException | MetricsGraphException e) {
LOGGER.info("Could not create XML data for metric {}", metricName);
throw new MetricsEndpointException("Cannot create XML data for specified metric.", Response.Status.BAD_REQUEST);
}
} else if (outputFormat.equalsIgnoreCase("json")) {
LOGGER.trace("Retrieving JSON-formatted data for metric {}", metricName);
try {
String jsonData = metricsRetriever.createJsonData(metricName, rrdFilename, startTime, endTime);
ResponseBuilder responseBuilder = Response.ok(jsonData);
responseBuilder.type("application/json");
response = responseBuilder.build();
} catch (IOException | MetricsGraphException e) {
LOGGER.info("Could not create JSON data for metric {}", metricName);
throw new MetricsEndpointException("Cannot create JSON data for specified metric.", Response.Status.BAD_REQUEST);
}
}
LOGGER.trace("EXITING: getMetricsData");
return response;
}
use of ddf.metrics.reporting.internal.MetricsGraphException in project ddf by codice.
the class RrdMetricsRetriever method getMetricData.
/**
* Retrieves the RRD stored data for the specified metric over the specified time range.
*
* @param rrdFilename the name of the RRD file containing the metric's data
* @param startTime start time, in seconds since Unix epoch, to fetch metric's data
* @param endTime end time, in seconds since Unix epoch, to fetch metric's data
* @return domain object containing the metric's sampled data, which consists of the timestamps
* and their associated values, and the total count of the sampled data
* @throws IOException
* @throws MetricsGraphException
*/
public MetricData getMetricData(String rrdFilename, long startTime, long endTime) throws IOException, MetricsGraphException {
LOGGER.trace("ENTERING: getMetricData");
// Create RRD DB in read-only mode for the specified RRD file
RrdDb rrdDb = new RrdDb(rrdFilename, true);
// we have a problem)
if (rrdDb.getDsCount() != 1) {
throw new MetricsGraphException("Only one data source per RRD file is supported - RRD file " + rrdFilename + " has " + rrdDb.getDsCount() + " data sources.");
}
// The step (sample) interval that determines how often RRD collects the metric's data
long rrdStep = rrdDb.getRrdDef().getStep();
// Retrieve the RRD file's data source type to determine how (later)
// to store the metric's data for presentation.
DsType dataSourceType = rrdDb.getDatasource(0).getType();
// Fetch the metric's data from the RRD file for the specified time range
FetchRequest fetchRequest = rrdDb.createFetchRequest(ConsolFun.TOTAL, startTime, endTime);
FetchData fetchData = fetchRequest.fetchData();
long[] timestamps = fetchData.getTimestamps();
double[] values = fetchData.getValues(0);
// Done retrieving data from the RRD database - close it, otherwise no one else will
// be able to access it later.
rrdDb.close();
// The lists of the metric's timestamps and their associated values that have non-"NaN"
// values
List<Long> validTimestamps = new ArrayList<Long>();
List<Double> validValues = new ArrayList<Double>();
long totalCount = 0;
MetricData metricData = new MetricData();
if (dataSourceType == DsType.COUNTER || dataSourceType == DsType.DERIVE) {
// Counters are for constantly incrementing data, hence they can
// have a summation of their totals
metricData.setHasTotalCount(true);
for (int i = 0; i < timestamps.length; i++) {
long timestamp = timestamps[i];
// have been set to NaN as a placeholder when the RRD file was created)
if (timestamp >= startTime && timestamp <= endTime && !Double.toString(values[i]).equals("NaN")) {
// RRD averages the collected samples over the step interval.
// To "undo" this averaging and get the actual count, need to
// multiply the sampled data value by the RRD step interval.
double nonAveragedValue = (double) (values[i] * rrdStep);
validTimestamps.add(timestamp);
validValues.add(nonAveragedValue);
totalCount += (long) nonAveragedValue;
}
}
} else if (dataSourceType == DsType.GAUGE) {
// Gauges are for data that waxes and wanes, hence no total count
metricData.setHasTotalCount(false);
for (int i = 0; i < timestamps.length; i++) {
long timestamp = timestamps[i];
// have been set to NaN as a placeholder when the RRD file was created)
if (timestamp >= startTime && timestamp <= endTime && !Double.toString(values[i]).equals("NaN")) {
validTimestamps.add(timestamp);
validValues.add(values[i]);
}
}
}
metricData.setTimestamps(validTimestamps);
metricData.setValues(validValues);
metricData.setTotalCount(totalCount);
LOGGER.trace("EXITING: getMetricData");
return metricData;
}
use of ddf.metrics.reporting.internal.MetricsGraphException in project ddf by codice.
the class MetricsEndpoint method getMetricsReport.
/**
* Retrieve data for the all metrics over the given time range. The URL to access this method is
* of the form http://<host>:<port>/report.<outputFormat> The filename extension defines the
* desired output format returned for the report's data. Currently supported formats are xls and
* ppt.
* <p>
* The XLS-formatted report will be one spreadsheet (workbook) with a worksheet per metric. The
* PPT-formatted report will be one PowerPoint slide deck with a slide per metric. Each slide
* will contain the metric's PNG graph.
* <p>
* If a summary interval is requested, the XSL report will instead contain a single table, with
* the summarized values for each interval and metric. Cannot be used with PPT format.
* <p>
* Note that the time range can be specified as either a start and end date (in RFC3339 format,
* i.e., YYYY-MM-DD'T'hh:mm:ssZ), or as an offset in seconds from the current time. These 2 time
* range mechanisms cannot be combined, e.g., you cannot specify an end date and an offset to be
* applied from that end date.
* <p>
* By default, the metric's name will be used for the y-axis label, and the metric name and time
* range will be used for the graph's title for the report in PPT format.
*
* @param startDate Specifies the start of the time range of the search on the metric's data (RFC-3339
* - Date and Time format, i.e. YYYY-MM-DDTHH:mm:ssZ). Cannot be used with dateOffset
* parameter.
* @param endDate Specifies the end of the time range of the search on the metric's data (RFC-3339 -
* Date and Time format, i.e. YYYY-MM-DDTHH:mm:ssZ). Cannot be used with dateOffset
* parameter.
* @param dateOffset Specifies an offset, backwards from the current time, to search on the modified
* time field for entries. Defined in seconds. Cannot be used with startDate or
* endDate parameters.
* @param summaryInterval One of {@link ddf.metrics.reporting.internal.rrd4j.RrdMetricsRetriever.SUMMARY_INTERVALS}
* @param uriInfo
* @return Response containing the report as a stream in either XLS or PPT format
* @throws MetricsEndpointException
*/
@GET
@Path("/report.{outputFormat}")
public Response getMetricsReport(@PathParam("outputFormat") String outputFormat, @QueryParam("startDate") String startDate, @QueryParam("endDate") String endDate, @QueryParam("dateOffset") String dateOffset, @QueryParam("summaryInterval") String summaryInterval, @Context UriInfo uriInfo) throws MetricsEndpointException {
LOGGER.debug("ENTERING: getMetricsReport - outputFormat = {}", outputFormat);
LOGGER.debug("request url: {}", uriInfo.getRequestUri());
LOGGER.debug("startDate = {}, endDate = {}", startDate, endDate);
LOGGER.debug("dateOffset = {}", dateOffset);
Response response = null;
// Client must specify *either* startDate and/or endDate *OR* dateOffset
if (!StringUtils.isBlank(dateOffset) && (!StringUtils.isBlank(startDate) || !StringUtils.isBlank(endDate))) {
throw new MetricsEndpointException("Cannot specify dateOffset and startDate or endDate, must specify either dateOffset only or startDate and/or endDate", Response.Status.BAD_REQUEST);
}
long endTime;
if (!StringUtils.isBlank(endDate)) {
endTime = parseDate(endDate);
LOGGER.debug("Parsed endTime = {}", endTime);
} else {
// Default end time for metrics graphing to now (in seconds)
Calendar now = getCalendar();
endTime = now.getTimeInMillis() / MILLISECONDS_PER_SECOND;
LOGGER.debug("Defaulted endTime to {}", endTime);
// Set endDate to new calculated endTime (so that endDate is displayed properly
// in graph's title)
endDate = dateFormatter.format(now.getTime());
}
long startTime;
if (!StringUtils.isBlank(startDate)) {
startTime = parseDate(startDate);
LOGGER.debug("Parsed startTime = {}", startTime);
} else if (!StringUtils.isBlank(dateOffset)) {
startTime = endTime - Long.parseLong(dateOffset);
LOGGER.debug("Offset-computed startTime = {}", startTime);
// Set startDate to new calculated startTime (so that startDate is displayed properly
// in graph's title)
Calendar cal = getCalendar();
cal.setTimeInMillis(startTime * MILLISECONDS_PER_SECOND);
startDate = dateFormatter.format(cal.getTime());
} else {
// Default start time for metrics graphing to end time last 24 hours (in seconds)
startTime = endTime - ONE_DAY_IN_SECONDS;
LOGGER.debug("Defaulted startTime to {}", startTime);
// Set startDate to new calculated startTime (so that startDate is displayed properly
// in graph's title)
Calendar cal = getCalendar();
cal.setTimeInMillis(startTime * MILLISECONDS_PER_SECOND);
startDate = dateFormatter.format(cal.getTime());
}
LOGGER.debug("startDate = {}, endDate = {}", startDate, endDate);
List<String> metricNames = getMetricsNames();
// Generated name for metrics file (<DDF Sitename>_<Startdate>_<EndDate>.outputFormat)
String dispositionString = "attachment; filename=" + SystemInfo.getSiteName() + "_" + startDate.substring(0, 10) + "_" + endDate.substring(0, 10) + "." + outputFormat;
try {
if (outputFormat.equalsIgnoreCase("xls")) {
OutputStream os = metricsRetriever.createXlsReport(metricNames, metricsDir, startTime, endTime, summaryInterval);
InputStream is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray());
ResponseBuilder responseBuilder = Response.ok(is);
responseBuilder.type("application/vnd.ms-excel");
responseBuilder.header("Content-Disposition", dispositionString);
response = responseBuilder.build();
} else if (outputFormat.equalsIgnoreCase("ppt")) {
if (StringUtils.isNotEmpty(summaryInterval)) {
throw new MetricsEndpointException("Summary interval not allowed for ppt format", Response.Status.BAD_REQUEST);
}
OutputStream os = metricsRetriever.createPptReport(metricNames, metricsDir, startTime, endTime);
InputStream is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray());
ResponseBuilder responseBuilder = Response.ok(is);
responseBuilder.type("application/vnd.ms-powerpoint");
responseBuilder.header("Content-Disposition", dispositionString);
response = responseBuilder.build();
}
} catch (IOException | MetricsGraphException e) {
LOGGER.debug("Could not create {} report", outputFormat, e);
throw new MetricsEndpointException("Could not create report in specified output format.", Response.Status.BAD_REQUEST);
}
LOGGER.debug("EXITING: getMetricsReport");
return response;
}
use of ddf.metrics.reporting.internal.MetricsGraphException in project ddf by codice.
the class RrdMetricsRetriever method createGraph.
@Override
public byte[] createGraph(String metricName, String rrdFilename, long startTime, long endTime, String verticalAxisLabel, String title) throws IOException, MetricsGraphException {
// Create RRD DB in read-only mode for the specified RRD file
RrdDb rrdDb = new RrdDb(rrdFilename, true);
// we have a problem)
if (rrdDb.getDsCount() != 1) {
throw new MetricsGraphException("Only one data source per RRD file is supported - RRD file " + rrdFilename + " has " + rrdDb.getDsCount() + " data sources.");
}
// Define attributes of the graph to be created for this metric
RrdGraphDef graphDef = new RrdGraphDef();
graphDef.setTimeSpan(startTime, endTime);
graphDef.setImageFormat("PNG");
graphDef.setShowSignature(false);
graphDef.setStep(RRD_STEP);
graphDef.setVerticalLabel(verticalAxisLabel);
graphDef.setHeight(500);
graphDef.setWidth(1000);
graphDef.setTitle(title);
// Since we have verified only one datasource in RRD file/RRDb, then know
// that we can index by zero safely and get the metric's data
Datasource dataSource = rrdDb.getDatasource(0);
DsType dataSourceType = dataSource.getType();
// generated graph by default will show data per rrdStep interval)
if (dataSourceType == DsType.COUNTER || dataSourceType == DsType.DERIVE) {
if (LOGGER.isTraceEnabled()) {
dumpData(ConsolFun.TOTAL, "TOTAL", rrdDb, dataSourceType.name(), startTime, endTime);
}
// If we ever needed to adjust the metric's data collected by RRD by the archive step
// (which is the rrdStep * archiveSampleCount) this is how to do it.
// FetchRequest fetchRequest = rrdDb.createFetchRequest(ConsolFun.AVERAGE, startTime,
// endTime);
// Archive archive = rrdDb.findMatchingArchive(fetchRequest);
// long archiveStep = archive.getArcStep();
// LOGGER.debug("archiveStep = " + archiveStep);
long rrdStep = rrdDb.getRrdDef().getStep();
LOGGER.debug("rrdStep = {}", rrdStep);
// Still TBD if we want to graph the AVERAGE data on the same graph
// graphDef.comment(metricName + " ");
// graphDef.datasource("myAverage", rrdFilename, "data", ConsolFun.AVERAGE);
// graphDef.datasource("realAverage", "myAverage," + rrdStep + ",*");
// graphDef.line("realAverage", Color.GREEN, "Average", 2);
// Multiplied by the rrdStep to "undo" the automatic averaging that RRD does
// when it collects TOTAL data - we want the actual totals for the step, not
// the average of the totals.
graphDef.datasource("myTotal", rrdFilename, dataSource.getName(), ConsolFun.TOTAL);
graphDef.datasource("realTotal", "myTotal," + rrdStep + ",*");
// If real total exceeds the threshold value used to constrain/filter spike data out,
// then set total to UNKNOWN, which means this sample will not be graphed. This prevents
// spike data that is typically 4.2E+09 (graphed as 4.3G) from corrupting the RRD graph.
graphDef.datasource("constrainedTotal", "realTotal," + metricsMaxThreshold + ",GT,UNKN,realTotal,IF");
graphDef.line("constrainedTotal", Color.BLUE, convertCamelCase(metricName), 2);
// Add some spacing between the graph and the summary stats shown beneath the graph
graphDef.comment("\\s");
graphDef.comment("\\s");
graphDef.comment("\\c");
// Average, Min, and Max over all of the TOTAL data - displayed at bottom of the graph
graphDef.gprint("constrainedTotal", ConsolFun.AVERAGE, "Average = %.3f%s");
graphDef.gprint("constrainedTotal", ConsolFun.MIN, "Min = %.3f%s");
graphDef.gprint("constrainedTotal", ConsolFun.MAX, "Max = %.3f%s");
} else if (dataSourceType == DsType.GAUGE) {
if (LOGGER.isTraceEnabled()) {
dumpData(ConsolFun.AVERAGE, "AVERAGE", rrdDb, dataSourceType.name(), startTime, endTime);
}
graphDef.datasource("myAverage", rrdFilename, dataSource.getName(), ConsolFun.AVERAGE);
graphDef.line("myAverage", Color.RED, convertCamelCase(metricName), 2);
// Add some spacing between the graph and the summary stats shown beneath the graph
graphDef.comment("\\s");
graphDef.comment("\\s");
graphDef.comment("\\c");
// Average, Min, and Max over all of the AVERAGE data - displayed at bottom of the graph
graphDef.gprint("myAverage", ConsolFun.AVERAGE, "Average = %.3f%s");
graphDef.gprint("myAverage", ConsolFun.MIN, "Min = %.3f%s");
graphDef.gprint("myAverage", ConsolFun.MAX, "Max = %.3f%s");
} else {
rrdDb.close();
throw new MetricsGraphException("Unsupported data source type " + dataSourceType.name() + " in RRD file " + rrdFilename + ", only DERIVE, COUNTER and GAUGE data source types supported.");
}
rrdDb.close();
// Use "-" as filename so that RRD creates the graph only in memory (no file is
// created, hence no file locking problems due to race conditions between multiple clients)
graphDef.setFilename("-");
RrdGraph graph = new RrdGraph(graphDef);
return graph.getRrdGraphInfo().getBytes();
}
use of ddf.metrics.reporting.internal.MetricsGraphException in project ddf by codice.
the class RrdMetricsRetrieverTest method testRrdFileWithMultipleDataSources.
@Test
public // (expected = MetricsGraphException.class)
void testRrdFileWithMultipleDataSources() throws Exception {
String rrdFilename = TEST_DIR + "dummy" + RRD_FILE_EXTENSION;
long endTime = new RrdFileBuilder().rrdFileName(rrdFilename).numSamples(4).secondDataSource(true).build();
MetricsRetriever metricsRetriever = new RrdMetricsRetriever();
try {
metricsRetriever.createGraph("Dummy", rrdFilename, START_TIME, endTime);
fail();
} catch (MetricsGraphException e) {
}
}
Aggregations