lib/logstash/web/public/js/logstash.js in logstash-lite-0.2.20110206003603 vs lib/logstash/web/public/js/logstash.js in logstash-lite-0.2.20110329105411

- old
+ new

@@ -1,28 +1,88 @@ (function() { + // TODO(sissel): Write something that will use history.pushState and fall back + // to document.location.hash madness. var logstash = { params: { offset: 0, count: 50, }, - search: function(query) { + search: function(query, options) { if (query == undefined || query == "") { return; } - //console.log("Searching: " + query); + /* Default options */ + if (typeof(options) == 'undefined') { + options = { graph: true }; + } + var display_query = query.replace("<", "&lt;").replace(">", "&gt;") - $("#querystatus").html("Loading query '" + display_query + "'") + $("#querystatus, #results h1").html("Loading query '" + display_query + "' (offset:" + logstash.params.offset + ", count:" + logstash.params.count + ") <img class='throbber' src='/media/construction.gif'>") //console.log(logstash.params) logstash.params.q = query; document.location.hash = escape(JSON.stringify(logstash.params)); - $("#results").load("/search/ajax", logstash.params); + + /* Load the search results */ + $("#results").load("/api/search?format=html", logstash.params); + + if (options.graph != false) { + /* Load the default histogram graph */ + logstash.params.interval = 3600000; /* 1 hour, default */ + logstash.histogram(); + } /* if options.graph != false */ $("#query").val(logstash.params.q); }, /* search */ + histogram: function(tries) { + if (typeof(tries) == 'undefined') { + tries = 7; + } + + /* GeoCities mode on the graph while waiting ... + * This won't likely survive 1.0, but it's fun for now... */ + $("#visual").html("<center><img src='/media/truckconstruction.gif'><center>"); + + jQuery.getJSON("/api/histogram", logstash.params, function(histogram, text, jqxhr) { + /* Load the data into the graph */ + var flot_data = []; + // histogram is an array of { "key": ..., "count": ... } + for (var i in histogram) { + flot_data.push([parseInt(histogram[i]["key"]), histogram[i]["count"]]) + } + logstash.plot(flot_data, logstash.params.interval); + //console.log(histogram); + + /* Try to be intelligent about how we choose the histogram interval. + * If there are too few data points, try a smaller interval. + * If there are too many data points, try a larger interval. + * Give up after a few tries and go with the last result. + * + * This queries the backend several times, but should be reasonably + * speedy as this behaves roughly as a binary search. */ + //if (flot_data.length < 6 && flot_data.length > 0 && tries > 0) { + //console.log("Histogram bucket " + logstash.params.interval + " has only " + flot_data.length + " data points, trying smaller..."); + //logstash.params.interval /= 2; + //if (logstash.params.interval < 1000) { + //tries = 0; /* stop trying, too small... */ + //logstash.plot(flot_data, logstash.params.interval); + //return; + //} + //logstash.histogram(tries - 1); + //} else if (flot_data.length > 50 && tries > 0) { + //console.log("Histogram bucket " + logstash.params.interval + " too many (" + flot_data.length + ") data points, trying larger interval..."); + //logstash.params.interval *= 2; + //logstash.histogram(tries - 1); + //} else { + //console.log("Histo:" + logstash.params.interval); + //logstash.plot(flot_data, logstash.params.interval); + //} + }); + }, + parse_params: function(href) { var query = href.replace(/^[^?]*\?/, ""); if (query == href) { //console.log("No query params in link " + href); /* No query params */ @@ -46,18 +106,19 @@ var newquery = $("#query").val(); newquery += " " + query; logstash.search(newquery.trim()); }, /* appendquery */ - plot: function(data) { + plot: function(data, interval) { var target = $("#visual"); + target.css("display", "block"); var plot = $.plot(target, [ { /* data */ data: data, bars: { show: true, - barWidth: 3600000, + barWidth: interval, } } ], { /* options */ xaxis: { mode: "time" }, grid: { hoverable: true, clickable: true }, @@ -65,12 +126,16 @@ ); target.bind("plotclick", function(e, pos, item) { if (item) { start = logstash.ms_to_iso8601(item.datapoint[0]); - end = logstash.ms_to_iso8601(item.datapoint[0] + 3600000); + end = logstash.ms_to_iso8601(item.datapoint[0] + interval); + /* Clicking on the graph means a new search, means + * we probably don't want to keep the old offset since + * the search results will change. */ + logstash.params.offset = 0; logstash.appendquery("@timestamp:[" + start + " TO " + end + "]"); } }); }, /* plot */ @@ -123,17 +188,20 @@ var href = $(this).attr("href"); var params = logstash.parse_params(href); for (var p in params) { logstash.params[p] = params[p]; } - logstash.search(logstash.params.q) + logstash.search(logstash.params.q, { graph: false }) return false; }); var result_row_selector = "table.results tr.event"; $(result_row_selector).live("click", function() { - var data = eval($("td.message", this).data("full")); + var data = $("td.message", this).data("full"); + if (typeof(data) == "string") { + data = JSON.parse(data); + } /* Apply template to the dialog */ var query = $("#query").val().replace(/^\s+|\s+$/g, "") var sanitize = function(str) { if (!/^".*"$/.test(str)) { @@ -153,23 +221,23 @@ "{{/each}}" + "</li>"); /* TODO(sissel): recurse through the data */ var fields = new Array(); - for (var i in data._source["@fields"]) { - var value = data._source["@fields"][i] + for (var i in data["@fields"]) { + var value = data["@fields"][i] if (/^[, ]*$/.test(value)) { continue; /* Skip empty data fields */ } if (!(value instanceof Array)) { value = [value]; } fields.push( { type: "field", field: i, value: value }) } - for (var i in data._source) { + for (var i in data) { if (i == "@fields") continue; - var value = data._source[i] + var value = data[i] if (!(value instanceof Array)) { value = [value]; } if (i.charAt(0) == "@") { /* metadata */