From 95c3ee7388794cb97cccf09d5a77e87c7b4135f7 Mon Sep 17 00:00:00 2001 From: Gang Chen Date: Tue, 8 Jan 2013 17:30:30 +0800 Subject: [PATCH 1/9] Optimize date + timezone calculation and rendering at client side. Also: * Fix bug of #timeto in #graphheader div * Add missing semicolons * Deleting trailing whitespace --- static/lib/js/ajax.js | 291 ++++++++++++++++++++-------------------- static/lib/js/shared.js | 65 +++++---- 2 files changed, 177 insertions(+), 179 deletions(-) diff --git a/static/lib/js/ajax.js b/static/lib/js/ajax.js index a0baa3876..2546e4d1d 100644 --- a/static/lib/js/ajax.js +++ b/static/lib/js/ajax.js @@ -1,11 +1,11 @@ $(document).ready(function () { // Bind all click/change/whatever handlers - bind_clicks() - popover_setup() + bind_clicks(); + popover_setup(); // Common color profile. - window.graph_colors = ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"] + window.graph_colors = ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"]; // Hide sidebar by default sbctl('hide',false); @@ -61,7 +61,7 @@ function pageload(hash) { if(typeof window.hashjson.time == 'undefined') window.hashjson.time = {user_interval:0}; else if (typeof window.hashjson.time.user_interval == 'undefined') - window.hashjson.time.user_interval = 0; + window.hashjson.time.user_interval = 0; switch (window.hashjson.mode) { case 'terms': @@ -132,7 +132,7 @@ function getPage() { // Determine fields to be displayed var fields = window.hashjson.fields.length == 0 ? - resultjson.kibana.default_fields : window.hashjson.fields + resultjson.kibana.default_fields : window.hashjson.fields; // Create 'Columns' section $('#fields').html("
" + @@ -140,7 +140,7 @@ function getPage() { "
" + ""); - var all_fields = array_unique(get_all_fields(resultjson).concat(fields)) + var all_fields = array_unique(get_all_fields(resultjson).concat(fields)); // Create sidebar field list var fieldstr = ''; @@ -148,10 +148,10 @@ function getPage() { var field_name = all_fields[index].toString(); var afield = field_alias(field_name) + "_field"; var mode = $.inArray(field_name,window.hashjson.fields) >= 0 ? - 'selected' : 'unselected' + 'selected' : 'unselected'; fieldstr += sidebar_field_string(field_name,mode); } - $('#fields ul.unselected').append(fieldstr) + $('#fields ul.unselected').append(fieldstr); // Store list of fields for filter use window.field_list = $('#fields > ul > li'); @@ -183,7 +183,7 @@ function getPage() { Date.parse(window.resultjson.kibana.time.to), 100, window.hashjson.time.user_interval - ) + ); if (typeof window.sb == 'undefined') { sbctl('show',false); @@ -246,7 +246,7 @@ function getGraph(interval) { } else { if(typeof window.segment !== 'undefined') window['segment'] = undefined; - try { delete window['segment'] } catch (e) {} + try { delete window['segment']; } catch (e) {} } } @@ -282,7 +282,7 @@ function pieChart(data,selector){ $("#tooltip").remove(); var label = (!item.series.label) ? "missing" : item.series.label; showTooltip( - pos.pageX+30, pos.pageY, + pos.pageX+30, pos.pageY, ""+label+"" + " " + Math.round(item.series.percent) + "%" ); } @@ -309,8 +309,8 @@ function getID() { type: "GET", cache: false, success: function (json) { - window.resultjson = JSON.parse(json) - var hit = resultjson.hits.hits[0] + window.resultjson = JSON.parse(json); + var hit = resultjson.hits.hits[0]; blank_page(); setMeta(1); @@ -320,14 +320,14 @@ function getID() { "

Details for log ID: "+hit._id+" in "+hit._index+"


"+str); } }); - sbctl('hide',false) + sbctl('hide',false); window.hashjson.id = undefined; - window.hashjson.index = undefined - window.hashjson.mode = undefined + window.hashjson.index = undefined; + window.hashjson.mode = undefined; try{ delete window.hashjson.id; - delete window.hashjson.index - delete window.hashjson.mode + delete window.hashjson.index; + delete window.hashjson.mode; }catch(e){} } @@ -369,7 +369,7 @@ function getAnalysis() { Date.parse(window.resultjson.kibana.time.to), 100, window.hashjson.time.user_interval - ) + ); if(resultjson.hits.total == 0) { setMeta(resultjson.hits.total); @@ -412,9 +412,9 @@ function getAnalysis() { $('#logs').html( title+CreateTableView(termsTable(resultjson),'logs analysis')); - sbctl('hide',false) + sbctl('hide',false); graphLoading(); - window.hashjson.graphmode = 'count' + window.hashjson.graphmode = 'count'; getGraph(window.interval); // Calculate data for pie chart @@ -422,19 +422,19 @@ function getAnalysis() { $.each(resultjson.facets.terms.terms,function(i,term) { data[i] = { label: term['term'], data: term['count'], color: window.graph_colors[i] }; }); - var remain = data.slice(window.graph_colors.length,data.length) - var r = 0 + var remain = data.slice(window.graph_colors.length,data.length); + var r = 0; for (var x in remain) { r += remain[x].data; } - data = data.slice(0,window.graph_colors.length) - data.push({ label: "The Rest", data: r, color: '#AAA' }) - pieChart(data,'#piechart') + data = data.slice(0,window.graph_colors.length); + data.push({ label: "The Rest", data: r, color: '#AAA' }); + pieChart(data,'#piechart'); break; case 'score': if (resultjson.hits.count == resultjson.hits.total) { var basedon = "all " - + resultjson.hits.count + "" + + resultjson.hits.count + ""; } else { var basedon = 'the ' + resultjson.hits.count + ' most recent'; @@ -449,9 +449,9 @@ function getAnalysis() { ' events for your query in your selected timeframe.

'; $('#logs').html( title+CreateTableView(analysisTable(resultjson),'logs analysis')); - sbctl('hide',false) + sbctl('hide',false); graphLoading(); - window.hashjson.graphmode = 'count' + window.hashjson.graphmode = 'count'; getGraph(window.interval); break; case 'trend': @@ -466,9 +466,9 @@ function getAnalysis() { ' and end of the selected timeframe for your query.

'; $('#logs').html( title+CreateTableView(analysisTable(resultjson),'logs analysis')); - sbctl('hide',false) + sbctl('hide',false); graphLoading(); - window.hashjson.graphmode = 'count' + window.hashjson.graphmode = 'count'; getGraph(window.interval); break; case 'mean': @@ -487,7 +487,7 @@ function getAnalysis() { resultjson.facets.stats._type = undefined; try{ - delete resultjson.facets.stats._type + delete resultjson.facets.stats._type; }catch(e){} for (var obj in resultjson.facets.stats) { @@ -498,9 +498,9 @@ function getAnalysis() { i++; } $('#logs').html(title+CreateTableView(tbl,'logs')); - sbctl('hide',false) + sbctl('hide',false); graphLoading(); - window.hashjson.graphmode = 'mean' + window.hashjson.graphmode = 'mean'; getGraph(window.interval); break; } @@ -527,7 +527,7 @@ function analysisTable(resultjson) { for (var count = 0; count < fields.length; count++) { metric[fields[count]]=xmlEnt(idv[count]); } - var analyze_field = fields.join(' ') + var analyze_field = fields.join(' '); metric['Count'] = object.count; metric['Percent'] = Math.round( metric['Count'] / resultjson.hits.count * 10000 @@ -559,7 +559,7 @@ function termsTable(resultjson) { for (var obj in resultjson.facets.terms.terms) { var object = resultjson.facets.terms.terms[obj]; var metric = {}; - var color = i < window.graph_colors.length ? + var color = i < window.graph_colors.length ? " " : ''; metric['Rank'] = (i + 1) + color; @@ -568,13 +568,13 @@ function termsTable(resultjson) { for (var count = 0; count < fields.length; count++) { // TODO: This is so wrong, really shouldn't be matching a string here if (typeof termv[count] === 'undefined' || termv[count] == "null" ) { - var value = '' + var value = ''; } else { - var value = xmlEnt(termv[count]) + var value = xmlEnt(termv[count]); } metric[fields[count]] = value; } - var analyze_field = fields.join(' ') + var analyze_field = fields.join(' '); metric['Count'] = addCommas(object.count); metric['Percent'] = Math.round( object.count / resultjson.hits.total * 10000 @@ -617,10 +617,10 @@ function popover_setup() { $(document).click(function(e) { if(popover_visible & popover_clickedaway & !$(e.target).is("a.micro")) { - $('.popover').remove() - popover_visible = popover_clickedaway = false + $('.popover').remove(); + popover_visible = popover_clickedaway = false; } else { - popover_clickedaway = true + popover_clickedaway = true; } }); } @@ -641,7 +641,7 @@ function enable_popovers() { " "+ "(" + - objids.length+" events on this page)"; + objids.length+" events on this page)"; return str; }, content: function() { @@ -649,10 +649,10 @@ function enable_popovers() { var field = $(this).attr('data-field'); var objids = get_objids_with_field(window.resultjson,field); var counts = get_related_fields(window.resultjson,field); - var str = '' + var str = ''; if(counts.length > 0) { - str = 'Related fields:
' + str = 'Related fields:
'; var i = 0 $.each(counts, function(index,value) { var display = i < related_limit ? 'inline-block' : 'none'; @@ -666,7 +666,7 @@ function enable_popovers() { str += "
"; } - str = microAnalysisTable(window.resultjson,field,5) + + str = microAnalysisTable(window.resultjson,field,5) + ""+ str + "
" + @@ -686,28 +686,28 @@ function enable_popovers() { $('.popover').remove(); } $(this).popover('show'); - var data = top_field_values(window.resultjson,$(this).attr('data-field'),5) + var data = top_field_values(window.resultjson,$(this).attr('data-field'),5); var i = 0, chart = []; for (var point in data) { chart.push([[data[point][1],0]]) i = i + 1; } - tiny_bar(chart,'#micrograph') - popover_clickedaway = false - popover_visible = true - e.preventDefault() + tiny_bar(chart,'#micrograph'); + popover_clickedaway = false; + popover_visible = true; + e.preventDefault(); }); } function microAnalysisTable (json,field,count) { - var counts = top_field_values(json,field,count) - var table = [] + var counts = top_field_values(json,field,count); + var table = []; var colors = window.graph_colors; var i = 0; $.each(counts, function(index,value){ var show_val = value[0] == '' ? 'blank' : xmlEnt(value[0]); - var objids = get_objids_with_field_value(window.resultjson,field,value[0]) + var objids = get_objids_with_field_value(window.resultjson,field,value[0]); var field_val = " "+ ""+show_val+""; @@ -722,18 +722,18 @@ function microAnalysisTable (json,field,count) { i = i+1; }); return CreateTableView(table, - 'table table-condensed table-bordered micro',false,['99%','30px','30px']) + 'table table-condensed table-bordered micro',false,['99%','30px','30px']); } function pageLinks() { // Pagination - var perpage = window.resultjson.kibana.per_page + var perpage = window.resultjson.kibana.per_page; var str = ""; var end = window.hashjson.offset + window.resultjson.hits.hits.length; if (end < resultjson.hits.total) { - //str += " " - str += "" + //str += " "; + str += ""; } str += ""; if (window.hashjson.offset - perpage >= 0) { @@ -751,7 +751,7 @@ function pageLinks() { // This is very ugly function blank_page() { var selectors = ['#graph','#graphheader','#feedlinks','#logs','.pagelinks', - '#fields','#analyze'] + '#fields','#analyze']; for (var selector in selectors) { $(selectors[selector]).text(""); @@ -853,20 +853,20 @@ function CreateLogTable(objArray, fields, theme, enableHeader) { } var id = object._id; - var alt = i % 2 == 0 ? '' : 'alt' + var alt = i % 2 == 0 ? '' : 'alt'; var time = prettyDateString( - Date.parse(get_field_value(object,'@timestamp')) + tOffset); + Date.parse(get_field_value(object,'@timestamp'))); str += ''; str += ''; for (var index in fields) { var field = fields[index]; - if (typeof hlfield === "undefined") + if (typeof hlfield === "undefined") var value = get_field_value(object,field); else { - if ( field.toString() == hlfield.toString() ) + if ( field.toString() == hlfield.toString() ) var value = hlvalue; else var value = get_field_value(object,field); @@ -898,7 +898,7 @@ function details_table(objid,theme) { var obj = window.resultjson.hits.hits[objid]; //obj_fields = get_object_fields(obj); - var obj_fields = flatten_json(obj['_source']) + var obj_fields = flatten_json(obj['_source']); var str = "" + ""; @@ -907,7 +907,7 @@ function details_table(objid,theme) { var i = 1; for (index in obj_fields) { - var field = index + var field = index; var value = obj_fields[index]; var field_id = field.replace('@', 'ATSYM'); //var value = get_field_value(obj,field); @@ -922,16 +922,20 @@ function details_table(objid,theme) { // Are URLs clickable ? if (resultjson.kibana.clickable_urls) { - var value = value === undefined ? "-" : value.toString(); + //var value = value === undefined ? "-" : value.toString(); + value = value === undefined ? "-" : value.toString(); // Detect URLs and inserts delimiters - var value = value.replace(RegExp("(https?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?)", "g"), - function (all, text, char) { + //var value = value.replace(RegExp("(https?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?)", "g"), + value = value.replace(RegExp("(https?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?)", "g"), + function (all, text, ch) { return "@KIBANA_LINK_START@" + text + "@KIBANA_LINK_END@"; } ); - var value = xmlEnt(wbr(value),10); + //var value = xmlEnt(wbr(value),10); + value = xmlEnt(wbr(value),10); // Replace delimiters by HTML code - var value = value.replace(RegExp("@KIBANA_LINK_START@(.*?)@KIBANA_LINK_END@", "g"), + //var value = value.replace(RegExp("@KIBANA_LINK_START@(.*?)@KIBANA_LINK_END@", "g"), + value = value.replace(RegExp("@KIBANA_LINK_START@(.*?)@KIBANA_LINK_END@", "g"), function (all, text) { // Clean link var stripped = text.replace( new RegExp("","g"),""); @@ -973,13 +977,13 @@ function mSearch(field, value, mode) { var fields = $.trim(results[2]).split(/\s+/).slice(1); var values = value.toString().split('||'); var query = ''; - var glue = '' + var glue = ''; // TODO: This only works if a query already exists I think? for (var count = 0;count < fields.length;count++) { value = values[count]; if (value == "null" || typeof value === "undefined") { value = fields[count]; - field = '_missing_' + field = '_missing_'; } else { field = fields[count]; } @@ -1024,7 +1028,7 @@ function mFields(field) { // Add column $('#logs').find('tr.logrow').each(function(){ var obj = window.resultjson.hits.hits[$(this).attr('data-object')]; - var value = get_field_value(obj,field) + var value = get_field_value(obj,field); $(this).find('td').last().after( ''); }); @@ -1054,7 +1058,7 @@ function mFields(field) { $.each(window.resultjson.kibana.default_fields, function(index,field){ $('#logs').find('tr.logrow').each(function(){ var obj = window.resultjson.hits.hits[$(this).attr('data-object')]; - var value = get_field_value(obj,field) + var value = get_field_value(obj,field); $(this).find('td').last().after( ''); @@ -1084,7 +1088,7 @@ function feedLinks(obj) { "export " + " "+ "stream " + - "" + ""; } $(function () { @@ -1111,7 +1115,7 @@ $(function () { window.hashjson.mode = mode; if (mode == 'columns') - window.hashjson.fields = field.split(',,') + window.hashjson.fields = field.split(',,'); else window.hashjson.analyze_field = field; } @@ -1148,78 +1152,73 @@ function datepickers(from,to) { " grouped by " + "" + - ""); - var from_date = utc_date_obj(new Date(from - tOffset)) - var to_date = utc_date_obj(new Date(to - tOffset)); + var from_date = new Date(from); + var to_date = new Date(to); $('#timefrom').datetimeEntry({ maxDatetime : to_date, datetimeFormat: 'Y-O-D H:M:S', spinnerImage: '' }); - $('#timefrom').datetimeEntry('setDatetime',from_date) + $('#timefrom').datetimeEntry('setDatetime',from_date); $('#timeto').datetimeEntry({ minDatetime: $('#timefrom').datetimeEntry('getDatetime'), - maxDatetime: utc_date_obj(new Date()), + maxDateTime: new Date(), datetimeFormat: 'Y-O-D H:M:S', spinnerImage: '' - },to); - $('#timeto').datetimeEntry('setDatetime',to_date) + }); + $('#timeto').datetimeEntry('setDatetime',to_date); - // LOL Wat? o_from and o_to are globals?! I should be beaten with a hose for + // LOL Wat? o_from and o_to are globals?! I should be beaten with a hose for // the horrid way time is handled in this application. Stupid FLOT. $('#timefrom,#timeto').datepicker({ format: 'yyyy-mm-dd' }).on('show', function(ev) { - o_from = local_date_obj( - new Date($('#timefrom').datetimeEntry('getDatetime').getTime() - tOffset)); - o_to = local_date_obj( - new Date($('#timeto').datetimeEntry('getDatetime').getTime() - tOffset)); + o_from = $('#timefrom').datetimeEntry('getDatetime'); + o_to = $('#timeto').datetimeEntry('getDatetime'); }); } // Render the date/time picker // Must make this pretty function renderDateTimePicker(from, to, force) { - $('.datepicker').remove() - - from = from + tOffset - to = to + tOffset + $('.datepicker').remove(); if (!$('#timechange').length || force == true) { - datepickers(from,to) + datepickers(from,to); $('#timefrom').datepicker().on('changeDate', function(ev) { - o_from.setUTCFullYear(ev.date.getFullYear()) - o_from.setUTCMonth(ev.date.getMonth()) - o_from.setUTCDate(ev.date.getDate()) - $('.datepicker').remove() + o_from.setFullYear(ev.date.getFullYear()); + o_from.setMonth(ev.date.getMonth()); + o_from.setDate(ev.date.getDate()); + $('.datepicker').remove(); renderDateTimePicker( - o_from.getTime() + tOffset, - o_to.getTime() + tOffset, + o_from.getTime(), + o_to.getTime(), true ); - window.hashjson.timeframe = 'custom' + window.hashjson.timeframe = 'custom'; $('#timeinput').val('custom'); - }) + }); $('#timeto').datepicker().on('changeDate', function(ev) { - o_to.setUTCFullYear(ev.date.getFullYear()) - o_to.setUTCMonth(ev.date.getMonth()) - o_to.setUTCDate(ev.date.getDate()) - $('.datepicker').remove() + o_to.setFullYear(ev.date.getFullYear()); + o_to.setMonth(ev.date.getMonth()); + o_to.setDate(ev.date.getDate()); + $('.datepicker').remove(); renderDateTimePicker( o_from.getTime() + tOffset, o_to.getTime() + tOffset, true ); - window.hashjson.timeframe = 'custom' + window.hashjson.timeframe = 'custom'; $('#timeinput').val('custom'); - }) + }); $('input.datetimeRange').datetimeEntry({datetimeFormat: 'Y-O-D H:M:S'}). change(function() { @@ -1229,7 +1228,7 @@ function renderDateTimePicker(from, to, force) { }); $('#user_interval').change(function () { - var interval = $('#user_interval').val() + var interval = $('#user_interval').val(); if(typeof window.hashjson.time == 'undefined') window.hashjson.time = {user_interval:interval}; else @@ -1265,9 +1264,8 @@ function renderDateTimePicker(from, to, force) { function field_time(selector) { var tz_offset = int_to_tz(window.tOffset); - var str = ISODateString( - new Date($(selector).datetimeEntry('getDatetime').getTime()) - ) + tz_offset; + var str = ISODateString($(selector).datetimeEntry('getDatetime')) + + tz_offset; return str; } @@ -1281,7 +1279,7 @@ function tiny_bar(data,selector) { }, xaxis: {show:false, max: window.resultjson.kibana.per_page}, yaxis: {show:false}, - grid: {show:false}, + grid: {show:false} }); } @@ -1304,26 +1302,24 @@ function logGraph(data, interval, metric) { if(typeof window.resultjson.kibana.time !== 'undefined') { // add null value at time from. if(window.hashjson.timeframe != 'all') { - from = Date.parse(window.resultjson.kibana.time.from) + tOffset - array.push( - Array(from, null)); + from = Date.parse(window.resultjson.kibana.time.from); + array.push(Array(from, null)); } } for (var index in data) { var value = data[index][metric]; - array.push(Array(data[index].time + tOffset, value)); + array.push(Array(data[index].time, value)); } if(typeof window.resultjson.kibana.time !== 'undefined') { // add null value at time to. - to = Date.parse(window.resultjson.kibana.time.to) + tOffset - array.push( - Array(to, null)); + to = Date.parse(window.resultjson.kibana.time.to); + array.push(Array(to, null)); } from = array[0][0]; - to = array[array.length -1][0] + to = array[array.length -1][0]; renderDateTimePicker(from,to,true); @@ -1336,8 +1332,8 @@ function logGraph(data, interval, metric) { $('#graph').bind("plotselected", function (event, ranges) { if (!intset) { intset = true; - var from = utc_date_obj(new Date(parseInt(ranges.xaxis.from.toFixed(0)))) - var to = utc_date_obj(new Date(parseInt(ranges.xaxis.to.toFixed(0)))) + var from = new Date(parseInt(ranges.xaxis.from.toFixed(0))); + var to = new Date(parseInt(ranges.xaxis.to.toFixed(0))); var time = { "from": ISODateString(from)+int_to_tz(window.tOffset), "to": ISODateString(to)+int_to_tz(window.tOffset) @@ -1396,9 +1392,12 @@ function logGraph(data, interval, metric) { }, xaxis: { mode: "time", - timeformat: "%H:%M:%S
%m-%d", + tickFormatter: function (val, axis) { + var d = new Date(parseInt(val)); + return d.format("HH:MM:ss
mm-dd"); + }, label: "Datetime", - color: "#000", + color: "#000" }, yaxis: { min: 0, @@ -1473,22 +1472,22 @@ function sbctl(mode,user_selected) { } function move_column(field,dir) { - var x = dir == 'right' ? 1 : -2 - var len = $('#logs thead th').length + var x = dir == 'right' ? 1 : -2; + var len = $('#logs thead th').length; if (len == 2) - return - var thi = $('#logs th.column[data-field="'+field+'"]').index() + return; + var thi = $('#logs th.column[data-field="'+field+'"]').index(); - dest = thi+x + dest = thi+x; if (x == -2 && thi == 1) - dest = len-1 + dest = len-1; if (x == 1 && thi == (len-1)) - dest = 0 + dest = 0; - var th1 = $('#logs thead th:eq('+thi+')') - var th2 = $('#logs thead th:eq('+dest+')') - th1.detach().insertAfter(th2) + var th1 = $('#logs thead th:eq('+thi+')'); + var th2 = $('#logs thead th:eq('+dest+')'); + th1.detach().insertAfter(th2); $('#logs tr.logrow').each(function() { var tr = $(this); @@ -1500,7 +1499,7 @@ function move_column(field,dir) { window.hashjson.fields = $('#logs th.column').map( function(){return $(this).attr("data-field");} - ).get() + ).get(); } function showError(title,text) { @@ -1518,7 +1517,7 @@ function showError(title,text) { Date.parse(window.hashjson.time.to)+tOffset ); } - sbctl('hide') + sbctl('hide'); } function getGraphColor(mode) { @@ -1549,13 +1548,13 @@ function resetAll() { function highlight_events(objids) { for (objid in objids) { - $('#logs tr#logrow_'+objids[objid]).addClass('highlight') + $('#logs tr#logrow_'+objids[objid]).addClass('highlight'); } } function unhighlight_events(objids) { for (objid in objids) { - $('#logs tr#logrow_'+objids[objid]).removeClass('highlight') + $('#logs tr#logrow_'+objids[objid]).removeClass('highlight'); } } @@ -1567,7 +1566,7 @@ function bind_clicks() { $('body').delegate("i.shift_column", "click", function () { - move_column($(this).parent().attr('data-field'),$(this).attr('data-mode')) + move_column($(this).parent().attr('data-field'),$(this).attr('data-mode')); }); // Side bar expand/collapse @@ -1591,7 +1590,7 @@ function bind_clicks() { window.hashjson.timeframe = $(this).val(); if (window.hashjson.timeframe == "custom") { //Initialize the date picker with a 15 minute window into the past - var d = new Date() + var d = new Date(); var startDate = new Date(d - (15 * 60 * 1000)); renderDateTimePicker( startDate, d); @@ -1626,7 +1625,7 @@ function bind_clicks() { $("#logs").delegate("a.page", "click", function () { var per_page = window.resultjson.kibana.per_page; - var action = $(this).attr('data-action') + var action = $(this).attr('data-action'); switch (action) { case 'nextpage': window.hashjson.offset += per_page; @@ -1646,7 +1645,7 @@ function bind_clicks() { window.hashjson.offset = 0; var mode = $(this).attr('rel'); var field = $(this).attr('data-field'); - analyzeField(field, mode) + analyzeField(field, mode); }); // Analysis table rescore @@ -1674,18 +1673,18 @@ function bind_clicks() { if (!search || e.keyCode == 27) { //esc key $(this).val(''); window.field_list.show(); - return; + return; } - + window.field_list.hide(); var shown = window.field_list.filter(function(index) { return ($(this).attr('data-field').toLowerCase().indexOf(search) !== -1); }).show(); - + if (shown.length == 1 && e.keyCode == 13) { // enter key shown.children('i').click(); //toggle column $(this).val(''); - window.field_list.show(); + window.field_list.show(); } }); diff --git a/static/lib/js/shared.js b/static/lib/js/shared.js index fb7a25c02..74cf4187f 100644 --- a/static/lib/js/shared.js +++ b/static/lib/js/shared.js @@ -1,6 +1,6 @@ function get_object_fields(obj) { var field_array = []; - obj = flatten_json(obj._source) + obj = flatten_json(obj._source); for (field in obj) { field_array.push(field); } @@ -39,7 +39,7 @@ function array_unique(arr) { results.push(sorted_arr[i]); } } - return results + return results; } function get_objids_with_field(json,field) { @@ -76,9 +76,9 @@ function get_objids_with_field_value(json,field,value) { } function get_related_fields(json,field) { - var field_array = [] + var field_array = []; for (hit in json.hits.hits) { - var obj_fields = get_object_fields(json.hits.hits[hit]) + var obj_fields = get_object_fields(json.hits.hits[hit]); //var obj_fields = jQuery.grep(get_object_fields(json.hits.hits[hit]), function(value){ // return (value.charAt(0) != '@'); //}); @@ -106,7 +106,7 @@ function get_field_value(object,field,opt) { var value = recurse_field_dots(object['_source'],field); if(value === null) - return '' + return ''; if($.isArray(value)) if (opt == 'raw') { return value; @@ -117,7 +117,7 @@ function get_field_value(object,field,opt) { if (typeof(el) == 'object') { complex = true; } - }) + }); if (complex) { return JSON.stringify(value, null, 4); } @@ -126,7 +126,7 @@ function get_field_value(object,field,opt) { if(typeof value === 'object' && value != null) // Leaving this out for now //return opt == 'raw' ? value : JSON.stringify(value,null,4) - return JSON.stringify(value,null,4) + return JSON.stringify(value,null,4); return (value != null) ? value.toString() : ''; } @@ -137,7 +137,7 @@ function get_field_value(object,field,opt) { function get_all_values_for_field(json,field) { var field_array = []; for (hit in json.hits.hits) { - var value = get_field_value(json.hits.hits[hit],field,'raw') + var value = get_field_value(json.hits.hits[hit],field,'raw'); if(typeof value === 'object' && value != null) { field_array.push.apply(field_array,value); } else { @@ -170,14 +170,14 @@ function count_values_in_array(array) { for (var i = 0; i < tuples.length; i++) { var key = tuples[i][0]; var value = tuples[i][1]; - count_array.push([key,value]) + count_array.push([key,value]); } return count_array; } function top_field_values(json,field,count) { var result = count_values_in_array(get_all_values_for_field(json,field)); - return result.slice(0,count) + return result.slice(0,count); } /** @@ -258,7 +258,7 @@ function ISODateString(d) { } function pad(n) { - return n < 10 ? '0' + n : n + return n < 10 ? '0' + n : n; } return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + @@ -269,25 +269,24 @@ function ISODateString(d) { } function pickDateString(d) { - return dateFormat(d,'yyyy-mm-dd HH:MM:ss') + return dateFormat(d,'yyyy-mm-dd HH:MM:ss'); } function prettyDateString(d) { d = new Date(parseInt(d)); - d = utc_date_obj(d); return dateFormat(d,window.time_format); } function utc_date_obj(d) { return new Date( - d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), + d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds()); } function local_date_obj(d) { return new Date(Date.UTC( - d.getFullYear(), d.getMonth(), d.getDate(), + d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds())); } @@ -301,17 +300,17 @@ function is_int(value) { function flatten_json(object,root,array) { if (typeof array === 'undefined') - var array = {}; + array = {}; if (typeof root === 'undefined') - var root = ''; + root = ''; for(var index in object) { - var obj = object[index] + var obj = object[index]; var rootname = root.length == 0 ? index : root + '.' + index; if(typeof obj == 'object' ) { if($.isArray(obj)) array[rootname] = typeof obj === 'undefined' ? null : obj.join(','); else - flatten_json(obj,rootname,array) + flatten_json(obj,rootname,array); } else { array[rootname] = typeof obj === 'undefined' ? null : obj; } @@ -330,9 +329,9 @@ function xmlEnt(value) { .replace(/ /g, '  ') .replace(/<del>/g, '') .replace(/<\/del>/g, ''); - return stg1 + return stg1; } else { - return value + return value; } } @@ -356,25 +355,25 @@ function sortObj(arr) { // WTF. Has to be a better way to do this. Hi Tyler. function int_to_tz(offset) { - var hour = offset / 1000 / 3600 - var str = "" + var hour = offset / 1000 / 3600; + var str = ""; if (hour == 0) { - str = "+0000" + str = "+0000"; } if (hour < 0) { if (hour > -10) - str = "-0" + (hour * -100) + str = "-0" + (hour * -100); else - str = "-" + (hour * -100) + str = "-" + (hour * -100); } if (hour > 0) { if (hour < 10) - str = "+0" + (hour * 100) + str = "+0" + (hour * 100); else - str = "+" + (hour * 100) + str = "+" + (hour * 100); } str = str.substring(0,3) + ":" + str.substring(3); - return str + return str; } // Sets #hash, thus refreshing results @@ -401,11 +400,11 @@ function addCommas(nStr) { function wbr(str, num) { str = htmlEntities(str); return str.replace(RegExp("(@?\\w{" + num + "}|[:;,])([\\w\"'])([\\w@]*)", "g"), - function (all, text, char, trailer) { + function (all, text, ch, trailer) { if (/@KIBANA_\w+_(START|END)@/.test(all)) { - return text + char + trailer; + return text + ch + trailer; } else { - return text + "" + char + trailer; + return text + "" + ch + trailer; } } ); @@ -413,4 +412,4 @@ function wbr(str, num) { function htmlEntities(str) { return String(str).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); -} \ No newline at end of file +} From ac6365ac54d4bee51dd308d2edd15b644e89e039 Mon Sep 17 00:00:00 2001 From: Gang Chen Date: Wed, 16 Jan 2013 18:19:22 +0900 Subject: [PATCH 2/9] Fix a bug from last merge commit --- static/lib/js/shared.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/lib/js/shared.js b/static/lib/js/shared.js index 5c43d6bae..c2e41d3ca 100644 --- a/static/lib/js/shared.js +++ b/static/lib/js/shared.js @@ -399,7 +399,7 @@ function wbr(str, num) { str = htmlEntities(str); return str.replace( RegExp("(@?\\w{" + num + "}|[:;,])([\\w\"'])([\\w@]*)", "g"), - function (all, text, char, trailer) { + function (all, text, ch, trailer) { if (/@KIBANA_\w+_(START|END)@/.test(all)) { return text + ch + trailer; } else { From bc2ee86e0e1362a84d57c492237879291c3a2add Mon Sep 17 00:00:00 2001 From: Gang Chen Date: Mon, 21 Jan 2013 18:15:45 +0900 Subject: [PATCH 3/9] Support timezone config in KibanaConfig.rb --- static/lib/js/ajax.js | 31 +++++++++++++++---------------- static/lib/js/shared.js | 4 ++-- views/timezone.erb | 12 ++++++++---- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/static/lib/js/ajax.js b/static/lib/js/ajax.js index a76b2460a..ad51a3823 100644 --- a/static/lib/js/ajax.js +++ b/static/lib/js/ajax.js @@ -653,7 +653,7 @@ function enable_popovers() { if(counts.length > 0) { str = 'Related fields:
'; - var i = 0 + var i = 0; $.each(counts, function(index,value) { var display = i < related_limit ? 'inline-block' : 'none'; str += "'+i+''; @@ -1156,8 +1156,8 @@ function datepickers(from,to) { ""); - var from_date = new Date(from); - var to_date = new Date(to); + var from_date = new Date(from + window.ltOffset); + var to_date = new Date(to + window.ltOffset); $('#timefrom').datetimeEntry({ maxDatetime : to_date, datetimeFormat: 'Y-O-D H:M:S', @@ -1167,7 +1167,7 @@ function datepickers(from,to) { $('#timeto').datetimeEntry({ minDatetime: $('#timefrom').datetimeEntry('getDatetime'), - maxDateTime: new Date(), + maxDateTime: new Date(new Date().getTime() + window.ltOffset), datetimeFormat: 'Y-O-D H:M:S', spinnerImage: '' }); @@ -1199,8 +1199,8 @@ function renderDateTimePicker(from, to, force) { o_from.setDate(ev.date.getDate()); $('.datepicker').remove(); renderDateTimePicker( - o_from.getTime(), - o_to.getTime(), + o_from.getTime() - window.ltOffset, + o_to.getTime() - window.ltOffset, true ); window.hashjson.timeframe = 'custom'; @@ -1213,8 +1213,8 @@ function renderDateTimePicker(from, to, force) { o_to.setDate(ev.date.getDate()); $('.datepicker').remove(); renderDateTimePicker( - o_from.getTime() + tOffset, - o_to.getTime() + tOffset, + o_from.getTime() - window.ltOffset, + o_to.getTime() - window.ltOffset, true ); window.hashjson.timeframe = 'custom'; @@ -1333,17 +1333,16 @@ function logGraph(data, interval, metric) { $('#graph').bind("plotselected", function (event, ranges) { if (!intset) { intset = true; - var from = new Date(parseInt(ranges.xaxis.from.toFixed(0))); - var to = new Date(parseInt(ranges.xaxis.to.toFixed(0))); + var from = parseInt(ranges.xaxis.from.toFixed(0)); + var to = parseInt(ranges.xaxis.to.toFixed(0)); var time = { - "from": ISODateString(from)+int_to_tz(window.tOffset), - "to": ISODateString(to)+int_to_tz(window.tOffset) + "from": ISODateString(from + window.ltOffset)+int_to_tz(window.tOffset), + "to": ISODateString(to + window.ltOffset)+int_to_tz(window.tOffset) }; window.hashjson.offset = 0; window.hashjson.time = time; window.hashjson.timeframe = "custom"; setHash(window.hashjson); - } }); @@ -1394,7 +1393,7 @@ function logGraph(data, interval, metric) { xaxis: { mode: "time", tickFormatter: function (val, axis) { - var d = new Date(parseInt(val)); + var d = new Date(parseInt(val) + window.ltOffset); return d.format("HH:MM:ss
mm-dd"); }, label: "Datetime", diff --git a/static/lib/js/shared.js b/static/lib/js/shared.js index c2e41d3ca..4ae1dd94f 100644 --- a/static/lib/js/shared.js +++ b/static/lib/js/shared.js @@ -57,7 +57,7 @@ function get_objids_with_field_value(json,field,value) { for (hit in json.hits.hits) { var hit_obj = json.hits.hits[hit]; if(has_field(hit_obj,field)) { - var field_val = get_field_value(hit_obj,field,'raw') + var field_val = get_field_value(hit_obj,field,'raw'); if($.isArray(field_val)) { if($.inArray(value,field_val) >= 0) { objid_array.push(hit); @@ -271,7 +271,7 @@ function pickDateString(d) { } function prettyDateString(d) { - d = new Date(parseInt(d)); + d = new Date(parseInt(d) + window.ltOffset); return dateFormat(d,window.time_format); } diff --git a/views/timezone.erb b/views/timezone.erb index a235136be..667277753 100644 --- a/views/timezone.erb +++ b/views/timezone.erb @@ -1,13 +1,17 @@ var tmp_offset = "<%="#{ KibanaConfig::Timezone == 'user' ? 'user' : ((TZInfo::Timezone.get(KibanaConfig::Timezone).current_period.offset.utc_total_offset).to_f / 3600.0).to_s -}"%>" +}"%>"; -window.time_format = "<%= defined?(KibanaConfig::Time_format) ? KibanaConfig::Time_format : "mm/dd HH:MM:ss" %>" +window.time_format = "<%= defined?(KibanaConfig::Time_format) ? KibanaConfig::Time_format : "mm/dd HH:MM:ss" %>"; +// window.tOffset = KibanaConfig::Timezone - local timezone if (tmp_offset == 'user') { - var d = new Date() + var d = new Date(); window.tOffset = -d.getTimezoneOffset() * 60 * 1000; } else { window.tOffset = parseFloat(tmp_offset) * 3600 * 1000; -} \ No newline at end of file +} + +window.ltOffset = window.tOffset - + (- new Date().getTimezoneOffset() * 60 * 1000); From c11c0a2dee9ed9c49074649998daf6a34bc1647e Mon Sep 17 00:00:00 2001 From: Gang Chen Date: Tue, 22 Jan 2013 12:15:36 +0900 Subject: [PATCH 4/9] Render datepicker when timeinput change to 'Custom' --- public/lib/js/ajax.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/public/lib/js/ajax.js b/public/lib/js/ajax.js index ad51a3823..9471bf24d 100644 --- a/public/lib/js/ajax.js +++ b/public/lib/js/ajax.js @@ -1590,10 +1590,9 @@ function bind_clicks() { window.hashjson.timeframe = $(this).val(); if (window.hashjson.timeframe == "custom") { //Initialize the date picker with a 15 minute window into the past - var d = new Date(); - var startDate = new Date(d - (15 * 60 * 1000)); - renderDateTimePicker( - startDate, d); + var to = new Date().getTime(); + var from = to - (15 * 60 * 1000); + renderDateTimePicker(from, to, true); } }); From 8ffae5423547709228d65ef6d3d5754cae40f3e6 Mon Sep 17 00:00:00 2001 From: Gang Chen Date: Tue, 22 Jan 2013 15:07:45 +0900 Subject: [PATCH 5/9] Add content type of timezone.js --- lib/kibana-app.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/kibana-app.rb b/lib/kibana-app.rb index 7bd6df05c..ca9980747 100644 --- a/lib/kibana-app.rb +++ b/lib/kibana-app.rb @@ -327,6 +327,6 @@ def link_to url_fragment, mode=:full_url end get '/js/timezone.js' do - erb :timezone + erb :timezone, :content_type => "application/javascript" end end From 95044f75e2622237321937cf05612bed8a511a03 Mon Sep 17 00:00:00 2001 From: Gang Chen Date: Tue, 19 Feb 2013 18:06:36 +0900 Subject: [PATCH 6/9] Merge remote branch 'upstream/kibana-ruby' into kibana-ruby Conflicts: public/lib/js/ajax.js --- .gitignore | 1 + Gemfile.lock | 11 +++++++- KibanaConfig.rb | 20 ++++++++++---- README.md | 25 +++++++++++++++++ Rakefile | 4 ++- config/warble.rb | 7 +++++ kibana-daemon.rb | 28 ++++++++----------- kibana.gemspec | 5 ++-- lib/kelastic.rb | 2 +- lib/kibana-app.rb | 5 ++-- public/lib/js/ajax.js | 14 ++++------ sample/kibana | 48 ++++++++++++++++++++++++++------ sample/kibana.erb | 64 +++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 188 insertions(+), 46 deletions(-) create mode 100644 config/warble.rb create mode 100755 sample/kibana.erb diff --git a/.gitignore b/.gitignore index 4d124c8e5..c751bb25e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ KibanaConfig.rbackup.rb *.DS_Store /tmp/* +Kibana.war diff --git a/Gemfile.lock b/Gemfile.lock index 030368377..95179d3fc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -15,8 +15,10 @@ GEM diff-lcs (1.1.3) eventmachine (1.0.0) fastercsv (1.5.5) + jruby-jars (1.7.2) + jruby-rack (1.1.13.1) json (1.7.5) - rack (1.4.1) + rack (1.4.5) rack-protection (1.2.0) rack rake (10.0.3) @@ -28,6 +30,7 @@ GEM rspec-expectations (2.11.3) diff-lcs (~> 1.1.3) rspec-mocks (2.11.3) + rubyzip (0.9.9) sinatra (1.3.3) rack (~> 1.3, >= 1.3.6) rack-protection (~> 1.2) @@ -38,6 +41,11 @@ GEM rack (>= 1.0.0) tilt (1.3.3) tzinfo (0.3.35) + warbler (1.3.6) + jruby-jars (>= 1.4.0) + jruby-rack (>= 1.0.0) + rake (>= 0.8.7) + rubyzip (>= 0.9.4) PLATFORMS ruby @@ -47,3 +55,4 @@ DEPENDENCIES rake rspec rspec-mocks + warbler diff --git a/KibanaConfig.rb b/KibanaConfig.rb index 227935fc9..f59a39401 100644 --- a/KibanaConfig.rb +++ b/KibanaConfig.rb @@ -1,9 +1,5 @@ module KibanaConfig - # A Note: While the only option you really have to set is "Elasticsearch" it - # is HIGHLY recommended you glance over every option. I personally consider - # 'Facet_index_limit' really important. - # Your elastic search server(s). This may be set as an array for round robin # load balancing # Elasticsearch = ["elasticsearch1:9200","elasticsearch2:9200"] @@ -18,6 +14,17 @@ module KibanaConfig # The adress ip Kibana should listen on. Comment out or set to # 0.0.0.0 to listen on all interfaces. KibanaHost = '127.0.0.1' + + # Below is an example showing how to configure the same variables + # using environment variables, which can be set in an init script + # es_ip = ENV['ES_IP'] ? ENV['ES_IP'] : '127.0.0.1' + # es_port = ENV['ES_PORT'] ? ENV['ES_PORT'] : 9200 + # Elasticsearch = "#{es_ip}:#{es_port}" + # KibanaPort = ENV['KIBANA_PORT'] ? ENV['KIBANA_PORT'] : 5601 + # KibanaHost = ENV['KIBANA_HOST'] ? ENV['KIBANA_HOST'] : 'localhost' + + #Set the Net::HTTP read/open timeouts for the connection to the ES backend + ElasticsearchTimeout = 500 # The record type as defined in your logstash configuration. # Seperate multiple types with a comma, no spaces. Leave blank @@ -89,12 +96,15 @@ module KibanaConfig # turn this behavior off if you use something other than daily # indexing Smart_index = true - + # You can define your custom pattern here for index names if you # use something other than daily indexing. Pattern needs to have # date formatting like '%Y.%m.%d'. Will accept an array of smart # indexes. # Smart_index_pattern = ['logstash-web-%Y.%m.%d', 'logstash-mail-%Y.%m.%d'] + # Smart_index_pattern = 'logstash-%Y.%m.%d' + # here is an example of how to set the pattern using an environment variable + # Smart_index_pattern = ENV['SMART_INDEX'] ? ENV['SMART_INDEX'] : 'logstash-%Y.%m.%d' Smart_index_pattern = 'logstash-%Y.%m.%d' # Number of seconds between each index. 86400 = 1 day. diff --git a/README.md b/README.md index d6763742d..ec7739433 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,9 @@ bundler logstash >= 1.1.0 elasticsearch >= 0.18.0 +java >= 1.6 if you want to run Kibana in JRuby +warbler if you want to create an executable standalone war file + ## Installation Install: git clone --branch=kibana-ruby https://github.com/rashidkpc/Kibana.git @@ -33,6 +36,28 @@ Run: Use: Point your browser at http://localhost:5601 +## JRuby + +To run Kibana with JRuby, e.g. if you have to run in on a windows machine, you can create a (executable) WAR archive. + +``` +git clone --branch=kibana-ruby https://github.com/rashidkpc/Kibana.git +cd Kibana +jruby -S gem install bundler +jruby -S bundle install +``` + +Configure your environment (see above). +`jruby -S rake war ` +or +`jruby -S warble executable war ` +if you want to include a webserver (default: jetty). + +Run: +` java [-Djetty.port=5601] -jar Kibana.war` + +Todo: Externalize the configuration. Any help would be appreciated. + ## FAQ Q: Why is there no last button? A: ElasticSearch isn't so hot at going to the last result of a many million diff --git a/Rakefile b/Rakefile index 3f90482eb..75ca6db61 100644 --- a/Rakefile +++ b/Rakefile @@ -2,7 +2,9 @@ require 'bundler/gem_tasks' require 'rspec/core/rake_task' +require 'warbler' -RSpec::Core::RakeTask.new(:spec) +RSpec::Core::RakeTask.new(:spec) task :default => [:spec] +Warbler::Task.new diff --git a/config/warble.rb b/config/warble.rb new file mode 100644 index 000000000..d379415cf --- /dev/null +++ b/config/warble.rb @@ -0,0 +1,7 @@ +Warbler::Config.new do |config| + +config.dirs = %w(lib) +config.webserver = "jetty" +config.includes = FileList['*.rb'] + +end diff --git a/kibana-daemon.rb b/kibana-daemon.rb index 196e71f4e..6590dd342 100644 --- a/kibana-daemon.rb +++ b/kibana-daemon.rb @@ -9,24 +9,20 @@ # / just after forking.. scriptdir = Pathname.new(File.dirname(__FILE__)).realpath -# store pidfile -if ENV['PID_DIR'] - pid_dir=ENV['PID_DIR'] -else - pid_dir = File.join(scriptdir, "tmp") -end +# populate environment variables +pid_dir = !ENV['PID_DIR'].nil? ? ENV['PID_DIR'] : File.join(scriptdir, "tmp") +app_name = !ENV['KIBANA_APP'].nil? ? ENV['KIBANA_APP'] : "kibana" +log_output = !ENV['LOG_DIR'].nil? ? true : false +log_dir = log_output ? ENV['LOG_DIR'] : nil -if !File.directory?(pid_dir) - if ARGV[0] == "start" - puts "creating pid_dir #{pid_dir}" - FileUtils.mkdir(pid_dir) - else - $stderr.puts "pid_dir #{pid_dir} does not exist" - exit 1 - end -end +options = { + :dir_mode => :normal, + :dir => pid_dir, + :log_output => log_output, + :log_dir => log_dir + } -Daemons.run_proc('kibana.rb', {:dir_mode => :normal, :dir => pid_dir}) do +Daemons.run_proc(app_name, options) do Dir.chdir(scriptdir) exec "ruby kibana.rb" end diff --git a/kibana.gemspec b/kibana.gemspec index 6d4f2a7e7..11753bdf6 100644 --- a/kibana.gemspec +++ b/kibana.gemspec @@ -15,14 +15,15 @@ Gem::Specification.new do |gem| gem.version = Kibana::VERSION gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } - # Dependencies gem.add_runtime_dependency 'sinatra' gem.add_runtime_dependency 'json' gem.add_runtime_dependency 'fastercsv' + gem.add_runtime_dependency 'daemons' gem.add_runtime_dependency 'tzinfo' - gem.add_runtime_dependency 'thin' + gem.add_runtime_dependency 'thin' unless RUBY_PLATFORM =~ /java/i gem.add_development_dependency 'rake' gem.add_development_dependency 'rspec' gem.add_development_dependency 'rspec-mocks' + gem.add_development_dependency 'warbler' end diff --git a/lib/kelastic.rb b/lib/kelastic.rb index d2d2691d7..2eb445ce6 100644 --- a/lib/kelastic.rb +++ b/lib/kelastic.rb @@ -135,7 +135,7 @@ def collect_item_attributes(h,field) field = field.sub(".",".properties.") types = h.sort_by { |k,v| v }[0][1] types.each do | type | - r << field.split(".").inject(type[1]['properties']) { |hash, key| + r << field.split(".",3).inject(type[1]['properties']) { |hash, key| if defined?hash[key] hash[key] end diff --git a/lib/kibana-app.rb b/lib/kibana-app.rb index ca9980747..c820d7197 100644 --- a/lib/kibana-app.rb +++ b/lib/kibana-app.rb @@ -7,10 +7,11 @@ class KibanaApp < Sinatra::Base configure do + set :root, File.join(File.dirname(__FILE__), '..') set :bind, defined?(KibanaConfig::KibanaHost) ? KibanaConfig::KibanaHost : '0.0.0.0' set :port, KibanaConfig::KibanaPort - set :public_folder, File.join(File.dirname(__FILE__), '..', 'public') - set :views, File.join(File.dirname(__FILE__), '..', 'views') + set :public_folder, File.join(root, 'public') + set :views, File.join(root, 'views') enable :sessions end diff --git a/public/lib/js/ajax.js b/public/lib/js/ajax.js index 9471bf24d..af657ea91 100644 --- a/public/lib/js/ajax.js +++ b/public/lib/js/ajax.js @@ -923,20 +923,16 @@ function details_table(objid,theme) { // Are URLs clickable ? if (resultjson.kibana.clickable_urls) { - //var value = value === undefined ? "-" : value.toString(); - value = value === undefined ? "-" : value.toString(); + var value = value === undefined ? "-" : value.toString(); // Detect URLs and inserts delimiters - //var value = value.replace(RegExp("(https?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?)", "g"), - value = value.replace(RegExp("(https?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?)", "g"), - function (all, text, ch) { + var value = value.replace(RegExp("(https?://([-\\w\\.]+)+(:\\d+)?(/([-\\w/_\\.]*(\\?\\S+)?)?)?)", "g"), + function (all, text, char) { return "@KIBANA_LINK_START@" + text + "@KIBANA_LINK_END@"; } ); - //var value = xmlEnt(wbr(value),10); - value = xmlEnt(wbr(value),10); + var value = xmlEnt(wbr(value),10); // Replace delimiters by HTML code - //var value = value.replace(RegExp("@KIBANA_LINK_START@(.*?)@KIBANA_LINK_END@", "g"), - value = value.replace(RegExp("@KIBANA_LINK_START@(.*?)@KIBANA_LINK_END@", "g"), + var value = value.replace(RegExp("@KIBANA_LINK_START@(.*?)@KIBANA_LINK_END@", "g"), function (all, text) { // Clean link var stripped = text.replace( new RegExp("","g"),""); diff --git a/sample/kibana b/sample/kibana index 6b17f6b94..fa8810c49 100755 --- a/sample/kibana +++ b/sample/kibana @@ -1,17 +1,47 @@ #!/bin/bash +### BEGIN INIT INFO +# Provides: kibana +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Make sense of a mountain of logs. +### END INIT INFO -# Author - Matt Mencel - 2012 -# Borrowed heavily from Patrick McKenzie's example -# http://www.kalzumeus.com/2010/01/15/deploying-sinatra-on-ubuntu-in-which-i-employ-a-secretary/ # -# kibana-daemon Startup script for the Kibana Web UI running on sinatra # chkconfig: 2345 20 80 # -## Copy to /etc/init.d/kibana and make it executable -## Add to system startup through chkconfig (CentOS/RHEL) or Upstart (Ubuntu) -KIBANA_PATH="/var/www/Kibana" +KIBANA_PATH="/usr/share/kibana" -ruby $KIBANA_PATH/kibana-daemon.rb $1 -RETVAL=$? +case "$1" in +start) + ruby $KIBANA_PATH/kibana-daemon.rb $1 + RETVAL=$? +;; + +stop) + ruby $KIBANA_PATH/kibana-daemon.rb $1 + RETVAL=$? +;; + +restart) + ruby $KIBANA_PATH/kibana-daemon.rb $1 + RETVAL=$? +;; + +status) + ruby $KIBANA_PATH/kibana-daemon.rb $1 +;; + +force-reload) + ruby $KIBANA_PATH/kibana-daemon.rb zap + ruby $KIBANA_PATH/kibana-daemon.rb start + RETVAL=$? +;; + +*) + echo "Usage: $0 {start|stop|restart|status|force-reload}" + exit 1 +esac exit $RETVAL diff --git a/sample/kibana.erb b/sample/kibana.erb new file mode 100755 index 000000000..bbef65f2e --- /dev/null +++ b/sample/kibana.erb @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +### BEGIN INIT INFO +# Provides: kibana +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Make sense of a mountain of logs. +### END INIT INFO +# +# +# chkconfig: 2345 20 80 +# +# this is an example .erb template to be used with chef or puppet +# it assumes that you are using bundler and RVM to run the kibana-daemon + +KIBANA_HOME=<%= @kibana_home %> +USER=<%= @user %> +export PID_DIR="<%= @pid_dir %>" +export LOG_DIR="<%= @log_dir %>" +export ES_PORT="<%= @es_port %>" +export ES_IP="<%= @es_ip %>" +export KIBANA_HOST="<%= @server_name %>" +export SMART_INDEX="<%= @smart_index %>" +export KIBANA_APP="<%= @app_name %>" +export KIBANA_PORT="<%= @kibana_port %>" +export RACK_ENV="production" +mkdir -p $PID_DIR $LOG_DIR +chown -R kibana:kibana $PID_DIR $LOG_DIR + +KIBANA_CMD="cd $KIBANA_HOME && source ~/.bash_profile && bundle exec ruby kibana-daemon.rb $1" + +case "$1" in +start) + su kibana -c "$KIBANA_CMD" + RETVAL=$? +;; + +stop) + su kibana -c "$KIBANA_CMD" + RETVAL=$? +;; + +restart) + su kibana -c "$KIBANA_CMD" + RETVAL=$? +;; + +status) + su kibana -c "$KIBANA_CMD" +;; + +force-reload) + su kibana -c "cd $KIBANA_HOME && source ~/.bash_profile && bundle exec kibana-daemon.rb zap" + su kibana -c "cd $KIBANA_HOME && source ~/.bash_profile && bundle exec kibana-daemon.rb start" + RETVAL=$? +;; + +*) + echo "Usage: $0 {start|stop|restart|status|force-reload}" + exit 1 +esac + +exit $RETVAL From 544fa7b7f515c763adac7568727e61c0d0659ea8 Mon Sep 17 00:00:00 2001 From: Gang Chen Date: Wed, 20 Feb 2013 15:55:28 +0900 Subject: [PATCH 7/9] Fix timezone calc in `stream' and coding style --- public/lib/js/stream.js | 30 +++++++++++++++--------------- views/timezone.erb | 3 ++- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/public/lib/js/stream.js b/public/lib/js/stream.js index 729d1ea3c..1494d340f 100644 --- a/public/lib/js/stream.js +++ b/public/lib/js/stream.js @@ -50,7 +50,7 @@ function getStream() { var timeframe = window.freq; var maxEvents = 100; var b64json = encodeURIComponent(Base64.encode(JSON.stringify(window.hashjson))); - var from = "" + var from = ""; if (window.last_time != "") { from = "/" + window.last_time; @@ -59,17 +59,17 @@ function getStream() { $.getJSON("api/stream/" + b64json + from, null, function(data) { if (data != null) { window.i++; - var fields = window.hashjson.fields + var fields = window.hashjson.fields; var has_time = false; var id = ""; var hit = ""; var i = 0; data.hits.hits = data.hits.hits.reverse(); for (var obj in data.hits.hits) { - hit = data.hits.hits[obj] + hit = data.hits.hits[obj]; - id = hit['_id'] - index = hit['_index'] + id = hit['_id']; + index = hit['_index']; if (!(has_time)) { window.last_time = get_field_value(hit,'@timestamp'); has_time = true; @@ -90,7 +90,7 @@ function getStream() { var jlink = $('
').addClass('jlink').attr('href', "../#" + hash).html($('').addClass('icon-link')); var linkTableData = $("
FieldActionValue
' + xmlEnt(wbr(value, 10)) + '' + xmlEnt(wbr(value, 10)) + '").css('white-space', 'nowrap'); - linkTableData.text(prettyDateString(Date.parse(get_field_value(hit,'@timestamp')) + tOffset)).prepend(jlink); + linkTableData.text(prettyDateString(Date.parse(get_field_value(hit,'@timestamp')))).prepend(jlink); tableRow.append(linkTableData); for (var field in fields) { tableRow.append($("").text(get_field_value(hit,fields[field]))); @@ -114,19 +114,19 @@ function getStream() { } } - var now = new Date() + var now = new Date(); if (typeof window.stream_arr === 'undefined') { - var now = new Date - var range = 900 - window.stream_arr = [] + var now = new Date; + var range = 900; + window.stream_arr = []; while(range > 0) { - window.stream_arr.push([new Date(now.getTime() - range*1000).getTime(),0]) + window.stream_arr.push([new Date(now.getTime() - range*1000).getTime(),0]); range = range-10; } } - window.stream_arr.shift() - window.stream_arr.push([now.getTime(),rate]) + window.stream_arr.shift(); + window.stream_arr.push([now.getTime(),rate]); $.plot( $("#streamgraph"), [ @@ -143,7 +143,7 @@ function getStream() { }, xaxis: {show:false, mode: "time"}, yaxis: {show:false}, - grid: {show:false}, + grid: {show:false} } ); @@ -155,4 +155,4 @@ function getStream() { function field_slim(field) { return field.replace(/(.*)\.(.*)/,"$1.
$2"); -} \ No newline at end of file +} diff --git a/views/timezone.erb b/views/timezone.erb index 667277753..3bb9b23c2 100644 --- a/views/timezone.erb +++ b/views/timezone.erb @@ -5,7 +5,7 @@ var tmp_offset = "<%="#{ window.time_format = "<%= defined?(KibanaConfig::Time_format) ? KibanaConfig::Time_format : "mm/dd HH:MM:ss" %>"; -// window.tOffset = KibanaConfig::Timezone - local timezone + if (tmp_offset == 'user') { var d = new Date(); window.tOffset = -d.getTimezoneOffset() * 60 * 1000; @@ -13,5 +13,6 @@ if (tmp_offset == 'user') { window.tOffset = parseFloat(tmp_offset) * 3600 * 1000; } +// = KibanaConfig::Timezone - local timezone window.ltOffset = window.tOffset - (- new Date().getTimezoneOffset() * 60 * 1000); From 4bfd31fe9843118983a14b95e3255abbcd9d3c40 Mon Sep 17 00:00:00 2001 From: Gang Chen Date: Wed, 6 Mar 2013 14:41:00 +0900 Subject: [PATCH 8/9] Fix time input of from/to field --- public/lib/js/ajax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/lib/js/ajax.js b/public/lib/js/ajax.js index af657ea91..4513c9297 100644 --- a/public/lib/js/ajax.js +++ b/public/lib/js/ajax.js @@ -1588,7 +1588,7 @@ function bind_clicks() { //Initialize the date picker with a 15 minute window into the past var to = new Date().getTime(); var from = to - (15 * 60 * 1000); - renderDateTimePicker(from, to, true); + renderDateTimePicker(from, to); } }); From 959444e320b48b9bd5b6b7960133910be312c3ea Mon Sep 17 00:00:00 2001 From: Gang Chen Date: Thu, 11 Jul 2013 14:14:57 +0800 Subject: [PATCH 9/9] Bump to v0.2.0p1 --- lib/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/version.rb b/lib/version.rb index 745760649..c722ab83b 100644 --- a/lib/version.rb +++ b/lib/version.rb @@ -1,3 +1,3 @@ module Kibana - VERSION = "0.2.0" + VERSION = "0.2.0p1" end