renderer.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. package renderer
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. "os/exec"
  7. "path/filepath"
  8. "runtime"
  9. "time"
  10. "strconv"
  11. "github.com/grafana/grafana/pkg/log"
  12. "github.com/grafana/grafana/pkg/setting"
  13. "github.com/grafana/grafana/pkg/util"
  14. )
  15. type RenderOpts struct {
  16. Url string
  17. Width string
  18. Height string
  19. SessionId string
  20. Timeout string
  21. }
  22. var rendererLog log.Logger = log.New("png-renderer")
  23. func RenderToPng(params *RenderOpts) (string, error) {
  24. rendererLog.Info("Rendering", "url", params.Url)
  25. var executable = "phantomjs"
  26. if runtime.GOOS == "windows" {
  27. executable = executable + ".exe"
  28. }
  29. binPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, executable))
  30. scriptPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, "render.js"))
  31. pngPath, _ := filepath.Abs(filepath.Join(setting.ImagesDir, util.GetRandomString(20)))
  32. pngPath = pngPath + ".png"
  33. cmd := exec.Command(binPath, "--ignore-ssl-errors=true", scriptPath, "url="+params.Url, "width="+params.Width,
  34. "height="+params.Height, "png="+pngPath, "cookiename="+setting.SessionOptions.CookieName,
  35. "domain="+setting.Domain, "sessionid="+params.SessionId)
  36. stdout, err := cmd.StdoutPipe()
  37. if err != nil {
  38. return "", err
  39. }
  40. stderr, err := cmd.StderrPipe()
  41. if err != nil {
  42. return "", err
  43. }
  44. err = cmd.Start()
  45. if err != nil {
  46. return "", err
  47. }
  48. go io.Copy(os.Stdout, stdout)
  49. go io.Copy(os.Stdout, stderr)
  50. done := make(chan error)
  51. go func() {
  52. cmd.Wait()
  53. close(done)
  54. }()
  55. timeout, err := strconv.Atoi(params.Timeout)
  56. if err != nil {
  57. timeout = 15
  58. }
  59. select {
  60. case <-time.After(time.Duration(timeout) * time.Second):
  61. if err := cmd.Process.Kill(); err != nil {
  62. rendererLog.Error("failed to kill", "error", err)
  63. }
  64. return "", fmt.Errorf("PhantomRenderer::renderToPng timeout (>%vs)", timeout)
  65. case <-done:
  66. }
  67. rendererLog.Debug("Image rendered", "path", pngPath)
  68. return pngPath, nil
  69. }