From 4dab595ed78feb67b8e79e8d89ef7bbf63df7eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 24 Sep 2018 15:58:22 +0200 Subject: [PATCH] rendering: Added concurrent rendering limits --- conf/defaults.ini | 2 ++ conf/sample.ini | 2 ++ pkg/services/alerting/notifier.go | 1 + pkg/services/alerting/result_handler.go | 2 +- pkg/services/rendering/interface.go | 1 + pkg/services/rendering/rendering.go | 33 ++++++++++++++---- pkg/setting/setting.go | 14 +++++--- public/img/rendering_error.png | Bin 0 -> 3161 bytes public/img/rendering_limit.png | Bin 0 -> 3859 bytes public/img/rendering_plugin_not_installed.png | Bin 0 -> 3651 bytes public/img/rendering_timeout.png | Bin 0 -> 3382 bytes 11 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 public/img/rendering_error.png create mode 100644 public/img/rendering_limit.png create mode 100644 public/img/rendering_plugin_not_installed.png create mode 100644 public/img/rendering_timeout.png diff --git a/conf/defaults.ini b/conf/defaults.ini index 15b8927e65a..caccebbd910 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -550,3 +550,5 @@ container_name = # Options to configure external image rendering server like https://github.com/grafana/grafana-image-renderer server_url = callback_url = +concurrent_limit = 10 +concurrent_limit_alerting = 5 diff --git a/conf/sample.ini b/conf/sample.ini index 2ef254f79b9..7a460faca0e 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -471,3 +471,5 @@ log_queries = # Options to configure external image rendering server like https://github.com/grafana/grafana-image-renderer ;server_url = ;callback_url = +;concurrent_limit = 10 +;concurrent_limit_alerting = 5 diff --git a/pkg/services/alerting/notifier.go b/pkg/services/alerting/notifier.go index 7fbd956f4f9..839893f3444 100644 --- a/pkg/services/alerting/notifier.go +++ b/pkg/services/alerting/notifier.go @@ -113,6 +113,7 @@ func (n *notificationService) uploadImage(context *EvalContext) (err error) { Timeout: alertTimeout / 2, OrgId: context.Rule.OrgId, OrgRole: m.ROLE_ADMIN, + IsAlert: true, } ref, err := context.GetDashboardUID() diff --git a/pkg/services/alerting/result_handler.go b/pkg/services/alerting/result_handler.go index 363d06d1132..893cca948f9 100644 --- a/pkg/services/alerting/result_handler.go +++ b/pkg/services/alerting/result_handler.go @@ -100,7 +100,7 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error { } } } - handler.notifier.SendIfNeeded(evalContext) + handler.notifier.SendIfNeeded(evalContext) return nil } diff --git a/pkg/services/rendering/interface.go b/pkg/services/rendering/interface.go index 85c139cfc04..856e6e683ff 100644 --- a/pkg/services/rendering/interface.go +++ b/pkg/services/rendering/interface.go @@ -22,6 +22,7 @@ type Opts struct { Path string Encoding string Timezone string + IsAlert bool } type RenderResult struct { diff --git a/pkg/services/rendering/rendering.go b/pkg/services/rendering/rendering.go index ecef83d74d9..2b9d91771e9 100644 --- a/pkg/services/rendering/rendering.go +++ b/pkg/services/rendering/rendering.go @@ -24,12 +24,13 @@ func init() { } type RenderingService struct { - log log.Logger - pluginClient *plugin.Client - grpcPlugin pluginModel.RendererPlugin - pluginInfo *plugins.RendererPlugin - renderAction renderFunc - domain string + log log.Logger + pluginClient *plugin.Client + grpcPlugin pluginModel.RendererPlugin + pluginInfo *plugins.RendererPlugin + renderAction renderFunc + domain string + inProgressCount int Cfg *setting.Cfg `inject:""` } @@ -89,7 +90,27 @@ func (rs *RenderingService) Run(ctx context.Context) error { return err } +func (rs *RenderingService) getLimit(isAlerting bool) int { + if isAlerting { + return rs.Cfg.RendererLimitAlerting + } else { + return rs.Cfg.RendererLimit + } +} + func (rs *RenderingService) Render(ctx context.Context, opts Opts) (*RenderResult, error) { + if rs.inProgressCount > rs.getLimit(opts.IsAlert) { + return &RenderResult{ + FilePath: filepath.Join(setting.HomePath, "public/img/rendering_limit.png"), + }, nil + } + + defer func() { + rs.inProgressCount -= 1 + }() + + rs.inProgressCount += 1 + if rs.renderAction != nil { return rs.renderAction(ctx, opts) } else { diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 1a253b9b238..71e499f9298 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -196,10 +196,13 @@ type Cfg struct { Smtp SmtpSettings // Rendering - ImagesDir string - PhantomDir string - RendererUrl string - RendererCallbackUrl string + ImagesDir string + PhantomDir string + RendererUrl string + RendererCallbackUrl string + RendererLimit int + RendererLimitAlerting int + DisableBruteForceLoginProtection bool TempDataLifetime time.Duration @@ -645,6 +648,9 @@ func (cfg *Cfg) Load(args *CommandLineArgs) error { // Rendering renderSec := iniFile.Section("rendering") + cfg.RendererLimit = renderSec.Key("concurrent_limit").MustInt(10) + cfg.RendererLimitAlerting = renderSec.Key("concurrent_limit").MustInt(5) + cfg.RendererUrl = renderSec.Key("server_url").String() cfg.RendererCallbackUrl = renderSec.Key("callback_url").String() if cfg.RendererCallbackUrl == "" { diff --git a/public/img/rendering_error.png b/public/img/rendering_error.png new file mode 100644 index 0000000000000000000000000000000000000000..cc327c267be865451f631737dbcbb7eda1af4a71 GIT binary patch literal 3161 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 H$HjjG5OI== literal 0 HcmV?d00001 diff --git a/public/img/rendering_limit.png b/public/img/rendering_limit.png new file mode 100644 index 0000000000000000000000000000000000000000..f2ba9aad0ba8047d6d770694dc6fb8fff9a4c646 GIT binary patch literal 3859 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 literal 0 HcmV?d00001 diff --git a/public/img/rendering_plugin_not_installed.png b/public/img/rendering_plugin_not_installed.png new file mode 100644 index 0000000000000000000000000000000000000000..f135ff7cc9f9b3898396404cfe1b510fd81bbc42 GIT binary patch literal 3651 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 UD64y-2ma-(&JfL*r##9320j&!NB{r; literal 0 HcmV?d00001 diff --git a/public/img/rendering_timeout.png b/public/img/rendering_timeout.png new file mode 100644 index 0000000000000000000000000000000000000000..07a87eb5de3f7d288899b0835a5f81205d15e27c GIT binary patch literal 3382 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 c|9=4X#!