Graphite & JSONP

These days I’m discovering Graphite more in depth. To be honest, I saw this slide from Zach Holman and immediately thought I needed the same kind of dashboard.

This future dashboard will be served from a different host than the one hosting Graphite. I want to load data from Graphite into the page through Javascript. Hence standard AJAX calls are impossible because of Same Origin Policy, yet another security rule everyone suffer and no one (at least not me :)) understand.

Before I declare this measure totally stupid and finally take the time to launch lolsecurity.org, let’s have a look at JSONP. The principle is well described on the Wikipedia page. Instead of getting {"a json": "object"} through XMLHttpRequest and AJAX-y friends, this technique inserts a new <script> tag in the DOM and evaluate its content. The client waits for something like callbackFunction({"a json": "object"}) and the resulting JSON object is processed client-side with the callbackFunction() function. This function name should be supplied by the client as a parameter to the URL, though it’s not normalized. As it doesn’t make use of XMLHttpRequest to retrieve the content, it’s not subject to the Same Origin Policy Hell ©.

If you look at jQuery, the $.ajax functions galaxy allow you to use JSONP by setting dataType: "jsonp" in the request configuration. The callback name is often passed through ?callback=blah or jsoncallback=blah in the URL. For Graphite, it should be passed as jsonp=blah though it’s not really well documented^W^W^W^W not documented at all (it took me nearly 2 hours to make it work, the time to be fed up enough to look at the Python source code :/). The final result looks like this :

//graphite host
var url = "http://graphite-server/render/";
//add target and everything needed by graphite URL API...
url = url + "?target=<graph-data-etc.>";
//set "json" as the response format
url = url + "&format=json";
//set "jsonp" parameter to set the callback name
//the "?" will automagically be replaced by jQuery
url = url + "&jsonp=?";
//finally go!
$.getJSON(url, function(data){
  //do whatever you want with the result
  console.log(data);
});

It should work out of the box, though a look at your favorite browser’s inspector won’t hurt.

Since Graphite URL generation can be hard, I recommend you use the graphitejs plugin if you use jQuery.