diff --git a/docs/api.rst b/docs/api.rst index 5d4a936..8137ebe 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -211,7 +211,7 @@ than one metric in a single path. match ``servers.ix02ehssvc04v.cpu.total.user``, while ``servers.*.*.*.*`` will. - + Examples ^^^^^^^^ @@ -571,7 +571,7 @@ mode to use: plus the value of the current line. .. _param-bgcolor: - + bgcolor ``````` @@ -647,7 +647,7 @@ drawNullAsZero Converts any None (null) values in the displayed metrics to zero at render time. -.. _param-fgcolor: +.. _param-fgcolor: fgcolor ``````` @@ -981,7 +981,7 @@ max maxDataPoints ````````````` -Set the maximum numbers of datapoints returned when using json content. +Set the maximum numbers of datapoints returned when using json content. If the number of datapoints in a selected range exceeds the maxDataPoints value then the datapoints over the whole period are consolidated. @@ -1125,8 +1125,7 @@ template *Default: default* -Used to specify a template from ``graphTemplates.conf`` to use for default -colors and graph styles. +Used to specify a template to use for default colors and graph styles. Example:: @@ -1155,7 +1154,7 @@ Example:: &title=Apache Busy Threads, All Servers, Past 24h .. _param-tz: - + tz `` @@ -1270,7 +1269,7 @@ the X-axis. See `datetime.date.strftime() format specification details. .. _param-yAxisSide: - + yAxisSide ````````` @@ -1280,7 +1279,7 @@ Sets the side of the graph on which to render the Y-axis. Accepts values of ``left`` or ``right``. .. _param-yDivisors: - + yDivisors ````````` @@ -1377,7 +1376,7 @@ yMinRight In dual Y-axis mode, sets the lower bound of the right Y-Axis (see: `yMin`_). .. _param-yStep: - + yStep ````` diff --git a/docs/configuration.rst b/docs/configuration.rst index 3d63e41..7cd9700 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -190,6 +190,32 @@ Extra sections If ``True`` (default), full tracebacks are returned in the HTTP response in case of application errors. +*templates* + + To define color/styling, of graphs, like so: + * values under the 'default' template key serve to override + the built-in defaults (see glyph.py). + * Other template keys provide further styling which will be used + via the http parameter ``template=``. + The defaults are used for unspecified values. + +Example:: + + templates: + default: + background: 'white' + foreground: 'black' + minorLine: 'grey' + majorLine: 'rose' + linecolors: 'blue,green,red,purple,brown,yellow,aqua,grey,magenta,pink,gold,rose' + fontname: 'Sans' + fontsize: 10 + fontbold: 'false' + fontitalic: 'false' + my_template: + background: 'pink' + + Custom location --------------- diff --git a/graphite_api/config.py b/graphite_api/config.py index 1759309..4c194de 100644 --- a/graphite_api/config.py +++ b/graphite_api/config.py @@ -153,6 +153,9 @@ def configure(app): else: Sentry(app, dsn=config['sentry_dsn']) + if 'templates' in config: + app.config['templates'] = config['templates'] + app.wsgi_app = TrailingSlash(CORS(app.wsgi_app, config.get('allowed_origins'))) if config.get('render_errors', True): diff --git a/graphite_api/render/glyph.py b/graphite_api/render/glyph.py index 7b8e9c9..3d36631 100644 --- a/graphite_api/render/glyph.py +++ b/graphite_api/render/glyph.py @@ -56,7 +56,7 @@ 'darkgrey': (111, 111, 111), } -# This gets overridden by graphTemplates.conf +# This gets overridden by your graph templates defaultGraphOptions = dict( background='white', foreground='black', @@ -995,7 +995,13 @@ def encodeHeader(self, text): self.ctx.restore() def loadTemplate(self, template): + from ..app import app + conf = app.config.get('templates', {}) + opts = defaults = defaultGraphOptions + defaults.update(conf.get('default', {})) + if template != 'default': + opts.update(conf.get(template, {})) self.defaultBackground = opts.get('background', defaults['background']) self.defaultForeground = opts.get('foreground', defaults['foreground']) diff --git a/graphite_api/utils.py b/graphite_api/utils.py index 149a34d..1d55819 100644 --- a/graphite_api/utils.py +++ b/graphite_api/utils.py @@ -69,6 +69,8 @@ def keys(self): keys.update(request.form.keys()) keys.update(request.args.keys()) return keys + + RequestParams = RequestParams() diff --git a/tests/test_render.py b/tests/test_render.py index 192c990..d302df4 100644 --- a/tests/test_render.py +++ b/tests/test_render.py @@ -3,6 +3,7 @@ import os import time +from graphite_api.app import app from graphite_api._vendor import whisper from . import TestCase, WHISPER_DIR @@ -451,6 +452,37 @@ def test_render_validation(self): }) self.assertEqual(response.status_code, 200) + def test_graph_templates(self): + def get_metadata(svg): + prefix = 'metadata = ' + metadata = {} + for line in svg.split('\n'): + line = line.strip() + if line.startswith(prefix): + metadata = json.loads(line[len(prefix):]) + return metadata + + whisper.create(self.db, [(1, 60)]) + app.config['templates'] = { + 'default': {'linecolors': 'white,blue,red'}, + 'my_template': {'linecolors': 'blue,red,white'} + } + response = self.app.get(self.url, query_string={'target': 'test', + 'format': 'svg'}) + svg = response.data.decode('utf-8') + metadata = get_metadata(svg) + self.assertEqual(metadata['series'][0]['name'], 'test') + self.assertEqual(metadata['series'][0]['color'], 'white') + + response = self.app.get(self.url, + query_string={'target': 'test', + 'format': 'svg', + 'template': 'my_template'}) + svg = response.data.decode('utf-8') + metadata = get_metadata(svg) + self.assertEqual(metadata['series'][0]['name'], 'test') + self.assertEqual(metadata['series'][0]['color'], 'blue') + def test_raw_data(self): whisper.create(self.db, [(1, 60)])