You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chukwa.apache.org by ey...@apache.org on 2009/08/24 02:21:19 UTC
svn commit: r807034 - in /hadoop/chukwa/trunk: CHANGES.txt
src/java/org/apache/hadoop/chukwa/hicc/Chart.java src/web/hicc/js/base64.js
src/web/hicc/js/canvas2image.js src/web/hicc/js/flot.extend.js
Author: eyang
Date: Mon Aug 24 00:21:18 2009
New Revision: 807034
URL: http://svn.apache.org/viewvc?rev=807034&view=rev
Log:
CHUKWA-382. Added export button to export HICC graph as static image. (Eric Yang)
Added:
hadoop/chukwa/trunk/src/web/hicc/js/base64.js
hadoop/chukwa/trunk/src/web/hicc/js/canvas2image.js
Modified:
hadoop/chukwa/trunk/CHANGES.txt
hadoop/chukwa/trunk/src/java/org/apache/hadoop/chukwa/hicc/Chart.java
hadoop/chukwa/trunk/src/web/hicc/js/flot.extend.js
Modified: hadoop/chukwa/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/chukwa/trunk/CHANGES.txt?rev=807034&r1=807033&r2=807034&view=diff
==============================================================================
--- hadoop/chukwa/trunk/CHANGES.txt (original)
+++ hadoop/chukwa/trunk/CHANGES.txt Mon Aug 24 00:21:18 2009
@@ -4,6 +4,10 @@
NEW FEATURES
+ CHUKWA-383. Added embed mode for HICC. (Eric Yang)
+
+ CHUKWA-382. Added export button to export HICC graph as static image. (Eric Yang)
+
CHUKWA-366. Custom tags. (asrabkin)
CHUKWA-358. Real-time monitoring at collector. (asrabkin)
Modified: hadoop/chukwa/trunk/src/java/org/apache/hadoop/chukwa/hicc/Chart.java
URL: http://svn.apache.org/viewvc/hadoop/chukwa/trunk/src/java/org/apache/hadoop/chukwa/hicc/Chart.java?rev=807034&r1=807033&r2=807034&view=diff
==============================================================================
--- hadoop/chukwa/trunk/src/java/org/apache/hadoop/chukwa/hicc/Chart.java (original)
+++ hadoop/chukwa/trunk/src/java/org/apache/hadoop/chukwa/hicc/Chart.java Mon Aug 24 00:21:18 2009
@@ -228,6 +228,10 @@
.append("<script type=\"text/javascript\" src=\"/hicc/js/flexigrid.pack.js\"></script>\n");
output
.append("<script type=\"text/javascript\" src=\"/hicc/js/excanvas.pack.js\"></script>\n");
+ output
+ .append("<script type=\"text/javascript\" src=\"/hicc/js/base64.js\"></script>\n");
+ output
+ .append("<script type=\"text/javascript\" src=\"/hicc/js/canvas2image.js\"></script>\n");
output.append("<div id=\"placeholderTitle\"><center>" + title
+ "</center></div>\n");
output.append("<div id=\"placeholder\" style=\"width:" + this.width
@@ -438,6 +442,7 @@
output.append(" $(window).resize(function() { wholePeriod(); });\n");
output.append("});\n");
output.append("</script>\n");
+ output.append("<input type=\"button\" value=\"Export\" onclick=\"javascript:saveReport();\">\n");
output.append("</body></html>\n");
} else {
output.append("chartTitle=\"<center>" + this.title + "</center>\";");
Added: hadoop/chukwa/trunk/src/web/hicc/js/base64.js
URL: http://svn.apache.org/viewvc/hadoop/chukwa/trunk/src/web/hicc/js/base64.js?rev=807034&view=auto
==============================================================================
--- hadoop/chukwa/trunk/src/web/hicc/js/base64.js (added)
+++ hadoop/chukwa/trunk/src/web/hicc/js/base64.js Mon Aug 24 00:21:18 2009
@@ -0,0 +1,113 @@
+/* Copyright (C) 1999 Masanao Izumo <iz...@onicos.co.jp>
+ * Version: 1.0
+ * LastModified: Dec 25 1999
+ * This library is free. You can redistribute it and/or modify it.
+ */
+
+/*
+ * Interfaces:
+ * b64 = base64encode(data);
+ * data = base64decode(b64);
+ */
+
+(function() {
+
+var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+var base64DecodeChars = new Array(
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
+
+function base64encode(str) {
+ var out, i, len;
+ var c1, c2, c3;
+
+ len = str.length;
+ i = 0;
+ out = "";
+ while(i < len) {
+ c1 = str.charCodeAt(i++) & 0xff;
+ if(i == len)
+ {
+ out += base64EncodeChars.charAt(c1 >> 2);
+ out += base64EncodeChars.charAt((c1 & 0x3) << 4);
+ out += "==";
+ break;
+ }
+ c2 = str.charCodeAt(i++);
+ if(i == len)
+ {
+ out += base64EncodeChars.charAt(c1 >> 2);
+ out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
+ out += base64EncodeChars.charAt((c2 & 0xF) << 2);
+ out += "=";
+ break;
+ }
+ c3 = str.charCodeAt(i++);
+ out += base64EncodeChars.charAt(c1 >> 2);
+ out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
+ out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));
+ out += base64EncodeChars.charAt(c3 & 0x3F);
+ }
+ return out;
+}
+
+function base64decode(str) {
+ var c1, c2, c3, c4;
+ var i, len, out;
+
+ len = str.length;
+ i = 0;
+ out = "";
+ while(i < len) {
+ /* c1 */
+ do {
+ c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
+ } while(i < len && c1 == -1);
+ if(c1 == -1)
+ break;
+
+ /* c2 */
+ do {
+ c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
+ } while(i < len && c2 == -1);
+ if(c2 == -1)
+ break;
+
+ out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
+
+ /* c3 */
+ do {
+ c3 = str.charCodeAt(i++) & 0xff;
+ if(c3 == 61)
+ return out;
+ c3 = base64DecodeChars[c3];
+ } while(i < len && c3 == -1);
+ if(c3 == -1)
+ break;
+
+ out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
+
+ /* c4 */
+ do {
+ c4 = str.charCodeAt(i++) & 0xff;
+ if(c4 == 61)
+ return out;
+ c4 = base64DecodeChars[c4];
+ } while(i < len && c4 == -1);
+ if(c4 == -1)
+ break;
+ out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
+ }
+ return out;
+}
+
+if (!window.btoa) window.btoa = base64encode;
+if (!window.atob) window.atob = base64decode;
+
+})();
\ No newline at end of file
Added: hadoop/chukwa/trunk/src/web/hicc/js/canvas2image.js
URL: http://svn.apache.org/viewvc/hadoop/chukwa/trunk/src/web/hicc/js/canvas2image.js?rev=807034&view=auto
==============================================================================
--- hadoop/chukwa/trunk/src/web/hicc/js/canvas2image.js (added)
+++ hadoop/chukwa/trunk/src/web/hicc/js/canvas2image.js Mon Aug 24 00:21:18 2009
@@ -0,0 +1,236 @@
+/*
+ * Canvas2Image v0.1
+ * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+var Canvas2Image = (function() {
+
+ // check if we have canvas support
+ var bHasCanvas = false;
+ var oCanvas = document.createElement("canvas");
+ if (oCanvas.getContext("2d")) {
+ bHasCanvas = true;
+ }
+
+ // no canvas, bail out.
+ if (!bHasCanvas) {
+ return {
+ saveAsBMP : function(){},
+ saveAsPNG : function(){},
+ saveAsJPEG : function(){}
+ }
+ }
+
+ var bHasImageData = !!(oCanvas.getContext("2d").getImageData);
+ var bHasDataURL = !!(oCanvas.toDataURL);
+ var bHasBase64 = !!(window.btoa);
+
+ var strDownloadMime = "image/octet-stream";
+
+ // ok, we're good
+ var readCanvasData = function(oCanvas) {
+ var iWidth = parseInt(oCanvas.width);
+ var iHeight = parseInt(oCanvas.height);
+ return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight);
+ }
+
+ // base64 encodes either a string or an array of charcodes
+ var encodeData = function(data) {
+ var strData = "";
+ if (typeof data == "string") {
+ strData = data;
+ } else {
+ var aData = data;
+ for (var i=0;i<aData.length;i++) {
+ strData += String.fromCharCode(aData[i]);
+ }
+ }
+ return btoa(strData);
+ }
+
+ // creates a base64 encoded string containing BMP data
+ // takes an imagedata object as argument
+ var createBMP = function(oData) {
+ var aHeader = [];
+
+ var iWidth = oData.width;
+ var iHeight = oData.height;
+
+ aHeader.push(0x42); // magic 1
+ aHeader.push(0x4D);
+
+ var iFileSize = iWidth*iHeight*3 + 54; // total header size = 54 bytes
+ aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
+ aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
+ aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
+ aHeader.push(iFileSize % 256);
+
+ aHeader.push(0); // reserved
+ aHeader.push(0);
+ aHeader.push(0); // reserved
+ aHeader.push(0);
+
+ aHeader.push(54); // dataoffset
+ aHeader.push(0);
+ aHeader.push(0);
+ aHeader.push(0);
+
+ var aInfoHeader = [];
+ aInfoHeader.push(40); // info header size
+ aInfoHeader.push(0);
+ aInfoHeader.push(0);
+ aInfoHeader.push(0);
+
+ var iImageWidth = iWidth;
+ aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
+ aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
+ aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
+ aInfoHeader.push(iImageWidth % 256);
+
+ var iImageHeight = iHeight;
+ aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
+ aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
+ aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
+ aInfoHeader.push(iImageHeight % 256);
+
+ aInfoHeader.push(1); // num of planes
+ aInfoHeader.push(0);
+
+ aInfoHeader.push(24); // num of bits per pixel
+ aInfoHeader.push(0);
+
+ aInfoHeader.push(0); // compression = none
+ aInfoHeader.push(0);
+ aInfoHeader.push(0);
+ aInfoHeader.push(0);
+
+ var iDataSize = iWidth*iHeight*3;
+ aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
+ aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
+ aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
+ aInfoHeader.push(iDataSize % 256);
+
+ for (var i=0;i<16;i++) {
+ aInfoHeader.push(0); // these bytes not used
+ }
+
+ var iPadding = (4 - ((iWidth * 3) % 4)) % 4;
+
+ var aImgData = oData.data;
+
+ var strPixelData = "";
+ var y = iHeight;
+ do {
+ var iOffsetY = iWidth*(y-1)*4;
+ var strPixelRow = "";
+ for (var x=0;x<iWidth;x++) {
+ var iOffsetX = 4*x;
+
+ strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+2]);
+ strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+1]);
+ strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX]);
+ }
+ for (var c=0;c<iPadding;c++) {
+ strPixelRow += String.fromCharCode(0);
+ }
+ strPixelData += strPixelRow;
+ } while (--y);
+
+ var strEncoded = encodeData(aHeader.concat(aInfoHeader)) + encodeData(strPixelData);
+
+ return strEncoded;
+ }
+
+
+ // sends the generated file to the client
+ var saveFile = function(strData) {
+ document.location.href = strData;
+ }
+
+ var makeDataURI = function(strData, strMime) {
+ return "data:" + strMime + ";base64," + strData;
+ }
+
+ // generates a <img> object containing the imagedata
+ var makeImageObject = function(strSource) {
+ var oImgElement = document.createElement("img");
+ oImgElement.src = strSource;
+ return oImgElement;
+ }
+
+ var scaleCanvas = function(oCanvas, iWidth, iHeight) {
+ if (iWidth && iHeight) {
+ var oSaveCanvas = document.createElement("canvas");
+ oSaveCanvas.width = iWidth;
+ oSaveCanvas.height = iHeight;
+ oSaveCanvas.style.width = iWidth+"px";
+ oSaveCanvas.style.height = iHeight+"px";
+
+ var oSaveCtx = oSaveCanvas.getContext("2d");
+
+ oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iWidth);
+ return oSaveCanvas;
+ }
+ return oCanvas;
+ }
+
+ return {
+
+ saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) {
+ if (!bHasDataURL) {
+ return false;
+ }
+ var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
+ var strData = oScaledCanvas.toDataURL("image/png");
+ if (bReturnImg) {
+ return makeImageObject(strData);
+ } else {
+ saveFile(strData.replace("image/png", strDownloadMime));
+ }
+ return true;
+ },
+
+ saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) {
+ if (!bHasDataURL) {
+ return false;
+ }
+
+ var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
+ var strMime = "image/jpeg";
+ var strData = oScaledCanvas.toDataURL(strMime);
+
+ // check if browser actually supports jpeg by looking for the mime type in the data uri.
+ // if not, return false
+ if (strData.indexOf(strMime) != 5) {
+ return false;
+ }
+
+ if (bReturnImg) {
+ return makeImageObject(strData);
+ } else {
+ saveFile(strData.replace(strMime, strDownloadMime));
+ }
+ return true;
+ },
+
+ saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) {
+
+ if (!(bHasImageData && bHasBase64)) {
+ return false;
+ }
+
+ var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
+
+ var oData = readCanvasData(oScaledCanvas);
+ var strImgData = createBMP(oData);
+ if (bReturnImg) {
+ return makeImageObject(makeDataURI(strImgData, "image/bmp"));
+ } else {
+ saveFile(makeDataURI(strImgData, strDownloadMime));
+ }
+ return true;
+ }
+ };
+
+})();
\ No newline at end of file
Modified: hadoop/chukwa/trunk/src/web/hicc/js/flot.extend.js
URL: http://svn.apache.org/viewvc/hadoop/chukwa/trunk/src/web/hicc/js/flot.extend.js?rev=807034&r1=807033&r2=807034&view=diff
==============================================================================
--- hadoop/chukwa/trunk/src/web/hicc/js/flot.extend.js (original)
+++ hadoop/chukwa/trunk/src/web/hicc/js/flot.extend.js Mon Aug 24 00:21:18 2009
@@ -262,3 +262,30 @@
}
return true;
}
+
+function saveReport() {
+ var pattern = /https?:\/\/(.*?)\//;
+ var baseUrl = pattern.exec(location.href)[0];
+ var chart = document.getElementById('placeholder').cloneNode(true);
+ var canvas = document.getElementById('placeholder').getElementsByTagName('canvas')[0];
+ chart.getElementsByTagName('canvas')[0].style.display="none";
+ chart.getElementsByTagName('canvas')[1].style.display="none";
+ var legend = document.getElementById('placeholderLegend');
+ var tableLegend = document.getElementById('statisLegend');
+ var data="data:text/html,";
+ data+="<!doctype html>";
+ data+="<link type=\"text/css\" rel=\"stylesheet\" href=\""+baseUrl+"hicc/css/default.css\" />";
+ data+="<link type=\"text/css\" rel=\"stylesheet\" href=\""+baseUrl+"hicc/css/iframe.css\" />";
+ data+="<link type=\"text/css\" rel=\"stylesheet\" href=\""+baseUrl+"hicc/css/flexigrid/flexigrid.css\" />";
+ data+="<center>";
+ data+="<div id=\"placeholder\" style=\"width:"+chart.style.width+"; height:"+chart.style.height+"; position: relative;\">";
+ data+="<img src=\""+canvas.toDataURL()+"\" style=\"position: absolute; left: 0px; top: 0px\">";
+ data+="<center>";
+ data+=chart.innerHTML;
+ data+="</center>";
+ data+="</div>";
+ data+=legend.innerHTML;
+ data+=tableLegend.innerHTML;
+ data+="</center>";
+ return window.open(data);
+}