Skip to content

Instantly share code, notes, and snippets.

@markolson
Last active August 29, 2015 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markolson/ecd6e46a9bea9878b3d1 to your computer and use it in GitHub Desktop.
Save markolson/ecd6e46a9bea9878b3d1 to your computer and use it in GitHub Desktop.
Embed Metrics in Graphite Renders
From 23c9be81e4f00040018deec19c73b9484a5fa50e Mon Sep 17 00:00:00 2001
From: Mark Olson <theothermarkolson@gmail.com>
Date: Sun, 2 Nov 2014 16:11:39 -0500
Subject: [PATCH] If PIL is available, embed the metrics used to generate the
graph in the PNG. For reasons.
---
webapp/graphite/render/views.py | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/webapp/graphite/render/views.py b/webapp/graphite/render/views.py
index 62ad20e..1b18640 100644
--- a/webapp/graphite/render/views.py
+++ b/webapp/graphite/render/views.py
@@ -27,6 +27,12 @@
except ImportError:
import pickle
+try:
+ from PIL import PngImagePlugin, Image
+ PNGEMBED_AVAILABLE = True
+except ImportError:
+ PNGEMBED_AVAILABLE = False
+
from graphite.compat import HttpResponse
from graphite.util import getProfileByUsername, json, unpickle
from graphite.remote_storage import HTTPConnectionWithTimeout
@@ -409,17 +415,31 @@ def renderMyGraphView(request,username,graphName):
url = graph.url
return HttpResponseRedirect(url)
-
def doImageRender(graphClass, graphOptions):
pngData = StringIO()
t = time()
img = graphClass(**graphOptions)
img.output(pngData)
+ if PNGEMBED_AVAILABLE:
+ imageData = addMetadata(pngData, graphOptions['data'])
+ else:
+ imageData = pngData.getvalue()
log.rendering('Rendered PNG in %.6f seconds' % (time() - t))
- imageData = pngData.getvalue()
- pngData.close()
return imageData
+def addMetadata(pngData, graphData):
+ pngData.seek(0)
+ ix = Image.open(pngData)
+ meta = PngImagePlugin.PngInfo()
+ for series in graphData:
+ timestamps = range(int(series.start), int(series.end) + 1, int(series.step))
+ datapoints = zip(series, timestamps)
+ meta.add_text("graphite::%s" % series.name, json.dumps(datapoints))
+ imageWithMeta = StringIO()
+ ix.save(imageWithMeta, "png", pnginfo=meta)
+ imageData = imageWithMeta.getvalue()
+ imageWithMeta.close()
+ return imageData
def buildResponse(imageData, content_type="image/png"):
return HttpResponse(imageData, content_type=content_type)
f = File.open(ARGV[0])
check = f.read(8).unpack('C*').to_a
while(!f.eof?) do
header_size = f.read(4).unpack('L>').first.to_i
header_type = f.read(4)
data = f.read(header_size)
if(header_type == 'tEXt')
name,value = data.split(0.chr)
puts "#{name} == #{value}"
end
crc = f.read(4)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment