summaryrefslogtreecommitdiffstats
path: root/library/Graphite/Web/Widget/GraphImage.php
diff options
context:
space:
mode:
Diffstat (limited to 'library/Graphite/Web/Widget/GraphImage.php')
-rw-r--r--library/Graphite/Web/Widget/GraphImage.php143
1 files changed, 143 insertions, 0 deletions
diff --git a/library/Graphite/Web/Widget/GraphImage.php b/library/Graphite/Web/Widget/GraphImage.php
new file mode 100644
index 0000000..af64e69
--- /dev/null
+++ b/library/Graphite/Web/Widget/GraphImage.php
@@ -0,0 +1,143 @@
+<?php
+
+namespace Icinga\Module\Graphite\Web\Widget;
+
+use Icinga\Module\Graphite\Graphing\Chart;
+use Icinga\Web\Url;
+use Icinga\Web\UrlParams;
+use Icinga\Web\Widget\AbstractWidget;
+use RuntimeException;
+
+class GraphImage extends AbstractWidget
+{
+ /**
+ * The chart to be rendered
+ *
+ * @var Chart
+ */
+ protected $chart;
+
+ /**
+ * The rendered PNG image
+ *
+ * @var string|null
+ */
+ protected $rendered;
+
+ /**
+ * Constructor
+ *
+ * @param Chart $chart The chart to be rendered
+ */
+ public function __construct(Chart $chart)
+ {
+ $this->chart = $chart;
+ }
+
+ /**
+ * Render the graph lazily
+ *
+ * @return string
+ */
+ public function render()
+ {
+ if ($this->rendered === null) {
+ $now = time();
+
+ $from = (int) $this->chart->getFrom();
+ if ($from < 0) {
+ $from += $now;
+ }
+
+ $until = (string) $this->chart->getUntil();
+
+ if ($until === '') {
+ $until = $now;
+ } else {
+ $until = (int) $until;
+ if ($until < 0) {
+ $until += $now;
+ }
+ }
+
+ $variables = $this->chart->getMetricVariables();
+ $template = $this->chart->getTemplate();
+ $graphiteWebClient = $this->chart->getGraphiteWebClient();
+ $params = (new UrlParams())->addValues([
+ 'from' => $from,
+ 'until' => $until,
+ 'bgcolor' => $this->chart->getBackgroundColor() ?? 'black',
+ 'fgcolor' => $this->chart->getForegroundColor() ?? 'white',
+ 'majorGridLineColor' => $this->chart->getMajorGridLineColor() ?? '0000003F',
+ 'minorGridLineColor' => $this->chart->getMinorGridLineColor() ?? 'black',
+ 'width' => $this->chart->getWidth(),
+ 'height' => $this->chart->getHeight(),
+ 'hideLegend' => (string) ! $this->chart->getShowLegend(),
+ 'tz' => date_default_timezone_get(),
+ '_salt' => "$now.000",
+ 'vTitle' => 'Percent',
+ 'lineMode' => 'connected',
+ 'drawNullAsZero' => 'false',
+ 'graphType' => 'line',
+ '_ext' => 'whatever.svg'
+ ]);
+
+ foreach ($template->getUrlParams() as $key => $value) {
+ $params->set($key, $value->resolve($variables));
+ }
+
+ $metrics = $this->chart->getMetrics();
+ $allVars = [];
+
+ foreach ($template->getCurves() as $curveName => $curve) {
+ if (!isset($metrics[$curveName])) {
+ continue;
+ }
+
+ $vars = $curve[0]->reverseResolve($metrics[$curveName]);
+
+ if ($vars !== false) {
+ $allVars = array_merge($allVars, $vars);
+ }
+ }
+
+ foreach ($metrics as $curveName => $metric) {
+ $allVars['metric'] = $metric;
+ $params->add('target', $template->getCurves()[$curveName][1]->resolve($allVars));
+ }
+
+ $url = Url::fromPath('/render')->setParams($params);
+ $headers = [
+ 'Accept-language' => 'en',
+ 'Content-type' => 'application/x-www-form-urlencoded'
+ ];
+
+ for (;;) {
+ try {
+ $this->rendered = $graphiteWebClient->request($url, 'GET', $headers);
+ } catch (RuntimeException $e) {
+ if (preg_match('/\b500\b/', $e->getMessage())) {
+ // A 500 Internal Server Error, probably because of
+ // a division by zero because of a too low time range to render.
+
+ $until = (int) $url->getParam('until');
+ $diff = $until - (int) $url->getParam('from');
+
+ // Try to render a higher time range, but give up
+ // once our default (1h) has been reached (non successfully).
+ if ($diff < 3600) {
+ $url->setParam('from', $until - $diff * 2);
+ continue;
+ }
+ }
+
+ throw $e;
+ }
+
+ break;
+ }
+ }
+
+ return $this->rendered;
+ }
+}