plugin_mode.go 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. package rendering
  2. import (
  3. "context"
  4. "fmt"
  5. "os/exec"
  6. "path"
  7. "time"
  8. pluginModel "github.com/grafana/grafana-plugin-model/go/renderer"
  9. "github.com/grafana/grafana/pkg/plugins"
  10. plugin "github.com/hashicorp/go-plugin"
  11. )
  12. func (rs *RenderingService) startPlugin(ctx context.Context) error {
  13. cmd := plugins.ComposePluginStartCommmand("plugin_start")
  14. fullpath := path.Join(rs.pluginInfo.PluginDir, cmd)
  15. var handshakeConfig = plugin.HandshakeConfig{
  16. ProtocolVersion: 1,
  17. MagicCookieKey: "grafana_plugin_type",
  18. MagicCookieValue: "renderer",
  19. }
  20. rs.log.Info("Renderer plugin found, starting", "cmd", cmd)
  21. rs.pluginClient = plugin.NewClient(&plugin.ClientConfig{
  22. HandshakeConfig: handshakeConfig,
  23. Plugins: map[string]plugin.Plugin{
  24. plugins.Renderer.Id: &pluginModel.RendererPluginImpl{},
  25. },
  26. Cmd: exec.Command(fullpath),
  27. AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
  28. Logger: plugins.LogWrapper{Logger: rs.log},
  29. })
  30. rpcClient, err := rs.pluginClient.Client()
  31. if err != nil {
  32. return err
  33. }
  34. raw, err := rpcClient.Dispense(rs.pluginInfo.Id)
  35. if err != nil {
  36. return err
  37. }
  38. rs.grpcPlugin = raw.(pluginModel.RendererPlugin)
  39. return nil
  40. }
  41. func (rs *RenderingService) watchAndRestartPlugin(ctx context.Context) error {
  42. ticker := time.NewTicker(time.Second * 1)
  43. for {
  44. select {
  45. case <-ctx.Done():
  46. return ctx.Err()
  47. case <-ticker.C:
  48. if rs.pluginClient.Exited() {
  49. err := rs.startPlugin(ctx)
  50. rs.log.Debug("Render plugin existed, restarting...")
  51. if err != nil {
  52. rs.log.Error("Failed to start render plugin", err)
  53. }
  54. }
  55. }
  56. }
  57. }
  58. func (rs *RenderingService) renderViaPlugin(ctx context.Context, opts Opts) (*RenderResult, error) {
  59. pngPath := rs.getFilePathForNewImage()
  60. rsp, err := rs.grpcPlugin.Render(ctx, &pluginModel.RenderRequest{
  61. Url: rs.getURL(opts.Path),
  62. Width: int32(opts.Width),
  63. Height: int32(opts.Height),
  64. FilePath: pngPath,
  65. Timeout: int32(opts.Timeout.Seconds()),
  66. RenderKey: rs.getRenderKey(opts.OrgId, opts.UserId, opts.OrgRole),
  67. Encoding: opts.Encoding,
  68. Timezone: isoTimeOffsetToPosixTz(opts.Timezone),
  69. Domain: rs.domain,
  70. })
  71. if err != nil {
  72. return nil, err
  73. }
  74. if rsp.Error != "" {
  75. return nil, fmt.Errorf("Rendering failed: %v", rsp.Error)
  76. }
  77. return &RenderResult{FilePath: pngPath}, err
  78. }