diff --git a/pkg/api/render.go b/pkg/api/render.go index 4dbead23524..5284c7831bb 100644 --- a/pkg/api/render.go +++ b/pkg/api/render.go @@ -18,14 +18,18 @@ func RenderToPng(c *middleware.Context) { Width: queryReader.Get("width", "800"), Height: queryReader.Get("height", "400"), OrgId: c.OrgId, - Timeout: queryReader.Get("timeout", "30"), + Timeout: queryReader.Get("timeout", "60"), Timezone: queryReader.Get("tz", ""), } pngPath, err := renderer.RenderToPng(renderOpts) if err != nil { - c.Handle(500, "Failed to render to png", err) + if err == renderer.ErrTimeout { + c.Handle(500, err.Error(), err) + } + + c.Handle(500, "Rendering failed.", err) return } diff --git a/pkg/components/renderer/renderer.go b/pkg/components/renderer/renderer.go index c09c431a1df..db36054e76d 100644 --- a/pkg/components/renderer/renderer.go +++ b/pkg/components/renderer/renderer.go @@ -1,6 +1,7 @@ package renderer import ( + "errors" "fmt" "io" "os" @@ -28,6 +29,7 @@ type RenderOpts struct { Timezone string } +var ErrTimeout = errors.New("Timeout error. You can set timeout in seconds with &timeout url parameter") var rendererLog log.Logger = log.New("png-renderer") func isoTimeOffsetToPosixTz(isoOffset string) string { @@ -75,6 +77,11 @@ func RenderToPng(params *RenderOpts) (string, error) { renderKey := middleware.AddRenderAuthKey(params.OrgId) defer middleware.RemoveRenderAuthKey(renderKey) + timeout, err := strconv.Atoi(params.Timeout) + if err != nil { + timeout = 15 + } + cmdArgs := []string{ "--ignore-ssl-errors=true", "--web-security=false", @@ -84,6 +91,7 @@ func RenderToPng(params *RenderOpts) (string, error) { "height=" + params.Height, "png=" + pngPath, "domain=" + localDomain, + "timeout=" + strconv.Itoa(timeout), "renderKey=" + renderKey, } @@ -117,17 +125,12 @@ func RenderToPng(params *RenderOpts) (string, error) { close(done) }() - timeout, err := strconv.Atoi(params.Timeout) - if err != nil { - timeout = 15 - } - select { case <-time.After(time.Duration(timeout) * time.Second): if err := cmd.Process.Kill(); err != nil { rendererLog.Error("failed to kill", "error", err) } - return "", fmt.Errorf("PhantomRenderer::renderToPng timeout (>%vs)", timeout) + return "", ErrTimeout case <-done: } diff --git a/vendor/phantomjs/render.js b/vendor/phantomjs/render.js index 5fb9aef2a26..67d5e992c37 100644 --- a/vendor/phantomjs/render.js +++ b/vendor/phantomjs/render.js @@ -30,10 +30,12 @@ height: params.height || '400' }; - var tries = 0; + 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); + console.log('Loading a web page: ' + params.url + ' status: ' + status, timeoutMs); page.onError = function(msg, trace) { var msgStack = ['ERROR: ' + msg]; @@ -59,7 +61,7 @@ return rootScope.panelsRendered >= panels; }); - if (panelsRendered || tries === 1000) { + if (panelsRendered || totalWaitMs > timeoutMs) { var bb = page.evaluate(function () { return document.getElementsByClassName("main-view")[0].getBoundingClientRect(); }); @@ -73,13 +75,12 @@ page.render(params.png); phantom.exit(); - } - else { - tries++; - setTimeout(checkIsReady, 10); + } else { + totalWaitMs += waitBetweenReadyCheckMs; + setTimeout(checkIsReady, waitBetweenReadyCheckMs); } } - setTimeout(checkIsReady, 200); + setTimeout(checkIsReady, waitBetweenReadyCheckMs); }); })();