@Override public String createCsvData(String rrdFilename, long startTime, long endTime) throws IOException, MetricsGraphException { LOGGER.trace("ENTERING: createCsvData"); MetricData metricData = getMetricData(rrdFilename, startTime, endTime); StringBuffer csv = new StringBuffer(""); csv.append("Timestamp,Value\n"); List<Long> timestamps = metricData.getTimestamps(); List<Double> values = metricData.getValues(); for (int i = 0; i < timestamps.size(); i++) { String timestamp = getCalendarTime(timestamps.get(i)); csv.append(timestamp + "," + new Double(values.get(i)).longValue() + "\n"); } LOGGER.debug("csv = " + csv.toString()); LOGGER.trace("EXITING: createCsvData"); return csv.toString(); }
/** * Adds a slide containing the metric's graph to the PowerPoint slide deck. The title is usually * the metric's name and is usually in camelCase format. This will be converted to individual, * capitalized words to the slide's title. The metric's data is used to determine the total count * across all of the metric's data, which is displayed at the bottom of the slide, under the * graph. * * @param ppt the PowerPoint slide deck to add this slide to * @param title the title for this slide * @param graph the metric's graph to be added to this slide * @param metricData the metric's data * @throws IOException * @throws MetricsGraphException */ private void createSlide(SlideShow ppt, String title, byte[] graph, MetricData metricData) throws IOException, MetricsGraphException { LOGGER.trace("ENTERING: createSlide"); if (LOGGER.isDebugEnabled()) { java.awt.Dimension pgsize = ppt.getPageSize(); int pgx = pgsize.width; // slide width (720) int pgy = pgsize.height; // slide height (540) LOGGER.debug("ppt page width = " + pgx); LOGGER.debug("ppt page height = " + pgy); } // Convert title, if it is in camelCase, to individual words with each word // starting with a capital letter String slideTitle = convertCamelCase(title); // String[] titleParts = StringUtils.splitByCharacterTypeCamelCase(title); // String slideTitle = ""; // for (String titlePart : titleParts) // { // slideTitle += titlePart + " "; // } // slideTitle = StringUtils.capitalize(slideTitle); Slide slide = ppt.createSlide(); // Add the title to the slide TextBox titleTextBox = slide.addTitle(); TextRun textRun = titleTextBox.getTextRun(); textRun.getRichTextRuns()[0].setFontSize(32); titleTextBox.setText(slideTitle); titleTextBox.setHorizontalAlignment(TextBox.AlignCenter); // Add the metric's graph to the slide int idx = ppt.addPicture(graph, Picture.PNG); Picture pict = new Picture(idx); // set graph's position and size in the slide // (Be sure to maintain aspect ratio for the image when specifying the // width and height. Refer to width and height values used in createGraph()) pict.setAnchor(new Rectangle(20, 100, 650, 325)); slide.addShape(pict); // If metric has a total count, add it under the graph on the slide if (metricData.hasTotalCount()) { TextBox totalCountTextBox = new TextBox(); textRun = totalCountTextBox.getTextRun(); textRun.getRichTextRuns()[0].setFontSize(14); totalCountTextBox.setText("Total Count: " + metricData.getTotalCount()); totalCountTextBox.setHorizontalAlignment(TextBox.AlignLeft); // x,y values determined relative to x,y of graph's anchor position // and the height of the graph totalCountTextBox.setAnchor(new Rectangle(20, 450, 250, 80)); slide.addShape(totalCountTextBox); } LOGGER.trace("EXITING: createSlide"); }
@Override public String createJsonData(String metricName, String rrdFilename, long startTime, long endTime) throws IOException, MetricsGraphException { LOGGER.trace("ENTERING: createJsonData"); JSONObject obj = new JSONObject(); String displayableMetricName = convertCamelCase(metricName); MetricData metricData = getMetricData(rrdFilename, startTime, endTime); String title = displayableMetricName + " for " + getCalendarTime(startTime) + " to " + getCalendarTime(endTime); obj.put("title", title); List<Long> timestamps = metricData.getTimestamps(); List<Double> values = metricData.getValues(); JSONArray samples = new JSONArray(); for (int i = 0; i < timestamps.size(); i++) { String timestamp = getCalendarTime(timestamps.get(i)); JSONObject sample = new JSONObject(); sample.put("timestamp", timestamp); // convert value to a long to prevent fractional values sample.put("value", new Double(values.get(i)).longValue()); samples.add(sample); } obj.put("data", samples); if (metricData.hasTotalCount()) { obj.put("totalCount", metricData.getTotalCount()); } JsonWriter writer = new JsonWriter(); obj.writeJSONString(writer); String jsonText = writer.toString(); LOGGER.debug("jsonText = " + jsonText); LOGGER.trace("EXITING: createJsonData"); return jsonText; }
private List<MetricDatum> validateMetricData(MetricData metricData) throws CloudWatchException { List<MetricDatum> metricDataCollection = null; if (metricData != null) { metricDataCollection = metricData.getMember(); ; } if (metricDataCollection == null) { throw new MissingParameterException("The parameter MetricData is required."); } if (metricDataCollection.size() < 1) { throw new MissingParameterException("The parameter MetricData is required."); } if (metricDataCollection.size() > 20) { throw new InvalidParameterValueException( "The collection MetricData must not have a size greater than 20."); } int ctr = 1; for (MetricDatum metricDatum : metricDataCollection) { validateMetricDatum(metricDatum, "MetricData.member." + ctr); ctr++; } return metricDataCollection; }
/** * 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 */ private 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); // Extract the data source (should always only be one data source per RRD file - otherwise 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 (COUNTER or GAUGE) 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) { // 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++) { // Filter out the RRD values that have not yet been sampled (they will // have been set to NaN as a placeholder when the RRD file was created) if (!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(timestamps[i]); 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++) { // Filter out the RRD values that have not yet been sampled (they will // have been set to NaN as a placeholder when the RRD file was created) if (!Double.toString(values[i]).equals("NaN")) { validTimestamps.add(timestamps[i]); validValues.add(values[i]); } } } metricData.setTimestamps(validTimestamps); metricData.setValues(validValues); metricData.setTotalCount(totalCount); LOGGER.trace("EXITING: getMetricData"); return metricData; }
/** * Creates an Excel worksheet containing the metric's data (timestamps and values) for the * specified time range. This worksheet is titled with the trhe metric's name and added to the * specified Workbook. * * @param wb the workbook to add this worksheet to * @param metricName the name of the metric whose data is being rendered in this worksheet * @param rrdFilename the name of the RRD file to retrieve the metric's data from * @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 * @throws IOException * @throws MetricsGraphException */ private void createSheet( Workbook wb, String metricName, String rrdFilename, long startTime, long endTime) throws IOException, MetricsGraphException { LOGGER.trace("ENTERING: createSheet"); MetricData metricData = getMetricData(rrdFilename, startTime, endTime); String displayableMetricName = convertCamelCase(metricName); String title = displayableMetricName + " for " + getCalendarTime(startTime) + " to " + getCalendarTime(endTime); Sheet sheet = wb.createSheet(displayableMetricName); sheet.autoSizeColumn(0); sheet.autoSizeColumn(1); Font headerFont = wb.createFont(); headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD); CellStyle columnHeadingsStyle = wb.createCellStyle(); columnHeadingsStyle.setFont(headerFont); CellStyle bannerStyle = wb.createCellStyle(); bannerStyle.setFont(headerFont); bannerStyle.setFillForegroundColor(HSSFColor.PALE_BLUE.index); bannerStyle.setFillPattern(CellStyle.SOLID_FOREGROUND); int rowCount = 0; Row row = sheet.createRow((short) rowCount); Cell cell = row.createCell(0); cell.setCellValue(title); cell.setCellStyle(bannerStyle); rowCount++; // Blank row for spacing/readability row = sheet.createRow((short) rowCount); cell = row.createCell(0); cell.setCellValue(""); rowCount++; row = sheet.createRow((short) rowCount); cell = row.createCell(0); cell.setCellValue("Timestamp"); cell.setCellStyle(columnHeadingsStyle); cell = row.createCell(1); cell.setCellValue("Value"); cell.setCellStyle(columnHeadingsStyle); rowCount++; List<Long> timestamps = metricData.getTimestamps(); List<Double> values = metricData.getValues(); for (int i = 0; i < timestamps.size(); i++) { String timestamp = getCalendarTime(timestamps.get(i)); row = sheet.createRow((short) rowCount); row.createCell(0).setCellValue(timestamp); // convert value to a long to prevent fractional values row.createCell(1).setCellValue(new Double(values.get(i)).longValue()); rowCount++; } if (metricData.hasTotalCount()) { // Blank row for spacing/readability row = sheet.createRow((short) rowCount); cell = row.createCell(0); cell.setCellValue(""); rowCount++; row = sheet.createRow((short) rowCount); cell = row.createCell(0); cell.setCellValue("Total Count: "); cell.setCellStyle(columnHeadingsStyle); row.createCell(1).setCellValue(metricData.getTotalCount()); } LOGGER.trace("EXITING: createSheet"); }
@Override public String createXmlData(String metricName, String rrdFilename, long startTime, long endTime) throws IOException, MetricsGraphException { LOGGER.trace("ENTERING: createXmlData"); MetricData metricData = getMetricData(rrdFilename, startTime, endTime); StringWriter sw = new StringWriter(); String displayableMetricName = convertCamelCase(metricName); String title = displayableMetricName + " for " + getCalendarTime(startTime) + " to " + getCalendarTime(endTime); try { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); // root elements Document doc = docBuilder.newDocument(); Element rootElement = doc.createElement(metricName); doc.appendChild(rootElement); Element titleElement = doc.createElement("title"); titleElement.appendChild(doc.createTextNode(title)); rootElement.appendChild(titleElement); Element dataElement = doc.createElement("data"); rootElement.appendChild(dataElement); List<Long> timestamps = metricData.getTimestamps(); List<Double> values = metricData.getValues(); for (int i = 0; i < timestamps.size(); i++) { Element sampleElement = doc.createElement("sample"); dataElement.appendChild(sampleElement); String timestamp = getCalendarTime(timestamps.get(i)); Element timestampElement = doc.createElement("timestamp"); timestampElement.appendChild(doc.createTextNode(timestamp)); sampleElement.appendChild(timestampElement); Element valueElement = doc.createElement("value"); long value = new Double(values.get(i)).longValue(); valueElement.appendChild(doc.createTextNode(String.valueOf(value))); sampleElement.appendChild(valueElement); } if (metricData.hasTotalCount()) { Element totalCountElement = doc.createElement("totalCount"); totalCountElement.appendChild( doc.createTextNode(Long.toString(metricData.getTotalCount()))); dataElement.appendChild(totalCountElement); } // write the content into xml stringwriter TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); DOMSource source = new DOMSource(doc); StreamResult result = new StreamResult(sw); transformer.transform(source, result); } catch (ParserConfigurationException pce) { pce.printStackTrace(); } catch (TransformerException tfe) { tfe.printStackTrace(); } LOGGER.debug("xml = " + sw.toString()); LOGGER.trace("EXITING: createXmlData"); return sw.toString(); }