浏览代码

Merge pull request #10610 from grafana/phantomjs_fix

fixes broken phantomjs rendering
Carl Bergquist 8 年之前
父节点
当前提交
ac2b36c271

+ 2 - 2
.gitignore

@@ -10,8 +10,8 @@ awsconfig
 /public_gen
 /public/vendor/npm
 /tmp
-vendor/phantomjs/phantomjs
-vendor/phantomjs/phantomjs.exe
+tools/phantomjs/phantomjs
+tools/phantomjs/phantomjs.exe
 profile.out
 coverage.txt
 

+ 1 - 1
docs/sources/reference/sharing.md

@@ -39,7 +39,7 @@ Click a panel title to open the panel menu, then click share in the panel menu t
 
 ### Direct Link Rendered Image
 
-You also get a link to service side rendered PNG of the panel. Useful if you want to share an image of the panel. Please note that for OSX and Windows, you will need to ensure that a `phantomjs` binary is available under `vendor/phantomjs/phantomjs`. For Linux, a `phantomjs` binary is included - however, you should ensure that any requisite libraries (e.g. libfontconfig) are available.
+You also get a link to service side rendered PNG of the panel. Useful if you want to share an image of the panel. Please note that for OSX and Windows, you will need to ensure that a `phantomjs` binary is available under `tools/phantomjs/phantomjs`. For Linux, a `phantomjs` binary is included - however, you should ensure that any requisite libraries (e.g. libfontconfig) are available.
 
 Example of a link to a server-side rendered PNG:
 

+ 1 - 1
pkg/setting/setting.go

@@ -578,7 +578,7 @@ func NewConfigContext(args *CommandLineArgs) error {
 
 	// PhantomJS rendering
 	ImagesDir = filepath.Join(DataPath, "png")
-	PhantomDir = filepath.Join(HomePath, "vendor/phantomjs")
+	PhantomDir = filepath.Join(HomePath, "tools/phantomjs")
 
 	analytics := Cfg.Section("analytics")
 	ReportingEnabled = analytics.Key("reporting_enabled").MustBool(true)

+ 1 - 1
scripts/grunt/options/phantomjs.js

@@ -3,7 +3,7 @@ module.exports = function(config,grunt) {
 
   grunt.registerTask('phantomjs', 'Copy phantomjs binary to vendor/', function() {
 
-    var dest = './vendor/phantomjs/phantomjs';
+    var dest = './tools/phantomjs/phantomjs';
     var confDir = './node_modules/phantomjs-prebuilt/lib/';
 
     if (process.platform === "win32") {

+ 1 - 1
scripts/grunt/release_task.js

@@ -26,7 +26,7 @@ module.exports = function(grunt) {
     });
     grunt.config('copy.backend_files', {
       expand: true,
-      src: ['conf/**', 'vendor/phantomjs/*', 'scripts/*'],
+      src: ['conf/**', 'tools/phantomjs/*', 'scripts/*'],
       options: { mode: true},
       dest: '<%= tempDir %>'
     });

+ 86 - 0
tools/phantomjs/render.js

@@ -0,0 +1,86 @@
+(function() {
+    'use strict';
+  
+    var page = require('webpage').create();
+    var args = require('system').args;
+    var params = {};
+    var regexp = /^([^=]+)=([^$]+)/;
+  
+    args.forEach(function(arg) {
+      var parts = arg.match(regexp);
+      if (!parts) { return; }
+      params[parts[1]] = parts[2];
+    });
+  
+    var usage = "url=<url> png=<filename> width=<width> height=<height> renderKey=<key>";
+  
+    if (!params.url || !params.png ||  !params.renderKey || !params.domain) {
+      console.log(usage);
+      phantom.exit();
+    }
+  
+    phantom.addCookie({
+      'name': 'renderKey',
+      'value': params.renderKey,
+      'domain': params.domain,
+    });
+  
+    page.viewportSize = {
+      width: params.width || '800',
+      height: params.height || '400'
+    };
+  
+    var timeoutMs = (parseInt(params.timeout) || 10) * 1000;
+    var waitBetweenReadyCheckMs = 50;
+    var totalWaitMs = 0;
+  
+    page.open(params.url, function (status) {
+      console.log('Loading a web page: ' + params.url + ' status: ' + status, timeoutMs);
+  
+      page.onError = function(msg, trace) {
+        var msgStack = ['ERROR: ' + msg];
+        if (trace && trace.length) {
+          msgStack.push('TRACE:');
+          trace.forEach(function(t) {
+            msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
+          });
+        }
+        console.error(msgStack.join('\n'));
+      };
+  
+      function checkIsReady() {
+        var panelsRendered = page.evaluate(function() {
+          if (!window.angular) { return false; }
+          var body = window.angular.element(document.body);
+          if (!body.injector) { return false; }
+          if (!body.injector()) { return false; }
+  
+          var rootScope = body.injector().get('$rootScope');
+          if (!rootScope) {return false;}
+          var panels = angular.element('div.panel:visible').length;
+          return rootScope.panelsRendered >= panels;
+        });
+  
+        if (panelsRendered || totalWaitMs > timeoutMs) {
+          var bb = page.evaluate(function () {
+            return document.getElementsByClassName("main-view")[0].getBoundingClientRect();
+          });
+  
+          page.clipRect = {
+            top:    bb.top,
+            left:   bb.left,
+            width:  bb.width,
+            height: bb.height
+          };
+  
+          page.render(params.png);
+          phantom.exit();
+        } else {
+          totalWaitMs += waitBetweenReadyCheckMs;
+          setTimeout(checkIsReady, waitBetweenReadyCheckMs);
+        }
+      }
+  
+      setTimeout(checkIsReady, waitBetweenReadyCheckMs);
+    });
+  })();