renderer.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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/middleware"
  13. "github.com/grafana/grafana/pkg/setting"
  14. "github.com/grafana/grafana/pkg/util"
  15. )
  16. type RenderOpts struct {
  17. Path string
  18. Width string
  19. Height string
  20. Timeout string
  21. OrgId int64
  22. }
  23. var rendererLog log.Logger = log.New("png-renderer")
  24. func RenderToPng(params *RenderOpts) (string, error) {
  25. rendererLog.Info("Rendering", "path", params.Path)
  26. var executable = "phantomjs"
  27. if runtime.GOOS == "windows" {
  28. executable = executable + ".exe"
  29. }
  30. localDomain := "localhost"
  31. if setting.HttpAddr != setting.DEFAULT_HTTP_ADDR {
  32. localDomain = setting.HttpAddr
  33. }
  34. url := fmt.Sprintf("%s://%s:%s/%s", setting.Protocol, localDomain, setting.HttpPort, params.Path)
  35. binPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, executable))
  36. scriptPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, "render.js"))
  37. pngPath, _ := filepath.Abs(filepath.Join(setting.ImagesDir, util.GetRandomString(20)))
  38. pngPath = pngPath + ".png"
  39. renderKey := middleware.AddRenderAuthKey(params.OrgId)
  40. defer middleware.RemoveRenderAuthKey(renderKey)
  41. cmdArgs := []string{
  42. "--ignore-ssl-errors=true",
  43. "--web-security=false",
  44. scriptPath,
  45. "url=" + url,
  46. "width=" + params.Width,
  47. "height=" + params.Height,
  48. "png=" + pngPath,
  49. "domain=" + localDomain,
  50. "renderKey=" + renderKey,
  51. }
  52. cmd := exec.Command(binPath, cmdArgs...)
  53. stdout, err := cmd.StdoutPipe()
  54. if err != nil {
  55. return "", err
  56. }
  57. stderr, err := cmd.StderrPipe()
  58. if err != nil {
  59. return "", err
  60. }
  61. err = cmd.Start()
  62. if err != nil {
  63. return "", err
  64. }
  65. go io.Copy(os.Stdout, stdout)
  66. go io.Copy(os.Stdout, stderr)
  67. done := make(chan error)
  68. go func() {
  69. cmd.Wait()
  70. close(done)
  71. }()
  72. timeout, err := strconv.Atoi(params.Timeout)
  73. if err != nil {
  74. timeout = 15
  75. }
  76. select {
  77. case <-time.After(time.Duration(timeout) * time.Second):
  78. if err := cmd.Process.Kill(); err != nil {
  79. rendererLog.Error("failed to kill", "error", err)
  80. }
  81. return "", fmt.Errorf("PhantomRenderer::renderToPng timeout (>%vs)", timeout)
  82. case <-done:
  83. }
  84. rendererLog.Debug("Image rendered", "path", pngPath)
  85. return pngPath, nil
  86. }