rendering.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package rendering
  2. import (
  3. "context"
  4. "fmt"
  5. "net/url"
  6. "os"
  7. "path/filepath"
  8. plugin "github.com/hashicorp/go-plugin"
  9. pluginModel "github.com/grafana/grafana-plugin-model/go/renderer"
  10. "github.com/grafana/grafana/pkg/infra/log"
  11. "github.com/grafana/grafana/pkg/middleware"
  12. "github.com/grafana/grafana/pkg/models"
  13. "github.com/grafana/grafana/pkg/plugins"
  14. "github.com/grafana/grafana/pkg/registry"
  15. "github.com/grafana/grafana/pkg/setting"
  16. "github.com/grafana/grafana/pkg/util"
  17. )
  18. func init() {
  19. registry.RegisterService(&RenderingService{})
  20. }
  21. type RenderingService struct {
  22. log log.Logger
  23. pluginClient *plugin.Client
  24. grpcPlugin pluginModel.RendererPlugin
  25. pluginInfo *plugins.RendererPlugin
  26. renderAction renderFunc
  27. domain string
  28. inProgressCount int
  29. Cfg *setting.Cfg `inject:""`
  30. }
  31. func (rs *RenderingService) Init() error {
  32. rs.log = log.New("rendering")
  33. // ensure ImagesDir exists
  34. err := os.MkdirAll(rs.Cfg.ImagesDir, 0700)
  35. if err != nil {
  36. return err
  37. }
  38. // set value used for domain attribute of renderKey cookie
  39. if rs.Cfg.RendererUrl != "" {
  40. // RendererCallbackUrl has already been passed, it won't generate an error.
  41. u, _ := url.Parse(rs.Cfg.RendererCallbackUrl)
  42. rs.domain = u.Hostname()
  43. } else if setting.HttpAddr != setting.DEFAULT_HTTP_ADDR {
  44. rs.domain = setting.HttpAddr
  45. } else {
  46. rs.domain = "localhost"
  47. }
  48. return nil
  49. }
  50. func (rs *RenderingService) Run(ctx context.Context) error {
  51. if rs.Cfg.RendererUrl != "" {
  52. rs.log.Info("Backend rendering via external http server")
  53. rs.renderAction = rs.renderViaHttp
  54. <-ctx.Done()
  55. return nil
  56. }
  57. if plugins.Renderer == nil {
  58. rs.renderAction = rs.renderViaPhantomJS
  59. <-ctx.Done()
  60. return nil
  61. }
  62. rs.pluginInfo = plugins.Renderer
  63. if err := rs.startPlugin(ctx); err != nil {
  64. return err
  65. }
  66. rs.renderAction = rs.renderViaPlugin
  67. err := rs.watchAndRestartPlugin(ctx)
  68. if rs.pluginClient != nil {
  69. rs.log.Debug("Killing renderer plugin process")
  70. rs.pluginClient.Kill()
  71. }
  72. return err
  73. }
  74. func (rs *RenderingService) Render(ctx context.Context, opts Opts) (*RenderResult, error) {
  75. if rs.inProgressCount > opts.ConcurrentLimit {
  76. return &RenderResult{
  77. FilePath: filepath.Join(setting.HomePath, "public/img/rendering_limit.png"),
  78. }, nil
  79. }
  80. defer func() {
  81. rs.inProgressCount -= 1
  82. }()
  83. rs.inProgressCount += 1
  84. if rs.renderAction != nil {
  85. return rs.renderAction(ctx, opts)
  86. }
  87. return nil, fmt.Errorf("No renderer found")
  88. }
  89. func (rs *RenderingService) getFilePathForNewImage() string {
  90. pngPath, _ := filepath.Abs(filepath.Join(rs.Cfg.ImagesDir, util.GetRandomString(20)))
  91. return pngPath + ".png"
  92. }
  93. func (rs *RenderingService) getURL(path string) string {
  94. if rs.Cfg.RendererUrl != "" {
  95. // The backend rendering service can potentially be remote.
  96. // So we need to use the root_url to ensure the rendering service
  97. // can reach this Grafana instance.
  98. // &render=1 signals to the legacy redirect layer to
  99. return fmt.Sprintf("%s%s&render=1", rs.Cfg.RendererCallbackUrl, path)
  100. }
  101. // &render=1 signals to the legacy redirect layer to
  102. return fmt.Sprintf("%s://%s:%s/%s&render=1", setting.Protocol, rs.domain, setting.HttpPort, path)
  103. }
  104. func (rs *RenderingService) getRenderKey(orgId, userId int64, orgRole models.RoleType) string {
  105. return middleware.AddRenderAuthKey(orgId, userId, orgRole)
  106. }