SOLR-3367: adding log viewer page

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1335204 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Ryan McKinley 2012-05-07 19:13:24 +00:00
parent aa0c9fba28
commit 5a79b09dc8
4 changed files with 412 additions and 13 deletions

View File

@ -1,3 +1,17 @@
#content #logging #navigation
{
width: 8%;
}
#content #logging #navigation .viewer a { background-image: url( ../../img/ico/document-text.png ); }
#content #logging #navigation .level a { background-image: url( ../../img/ico/gear.png ); }
#content #logging #frame
{
float: right;
width: 90%;
}
#content #logging .loader #content #logging .loader
{ {
background-position: 0 50%; background-position: 0 50%;
@ -17,6 +31,120 @@
margin-left: 10px; margin-left: 10px;
} }
#content #logging #viewer
{
position: relative;
}
#content #logging #viewer #state
{
background-position: 0 50%;
color: #c0c0c0;
margin-top: 20px;
padding-left: 21px;
}
#content #logging #viewer table
{
border-collapse: collapse;
width: 100%;
}
#content #logging #viewer th,
#content #logging #viewer td a,
#content #logging #viewer tbody .trace td
{
padding: 3px 10px;
}
#content #logging #viewer td
{
vertical-align: top;
}
#content #logging #viewer td a
{
display: block;
}
#content #logging #viewer thead th
{
font-weight: bold;
text-align: left;
}
#content #logging #viewer tbody td,
#content #logging #viewer tfoot td
{
border-top: 1px solid #f0f0f0;
}
#content #logging #viewer thead th.message
{
width:100%;
}
#content #logging #viewer tbody td.span a
{
padding-left: 0;
padding-right: 0;
}
#content #logging #viewer tbody span
{
display: block;
padding-left: 10px;
padding-right: 10px;
}
#content #logging #viewer tbody .level-info .level span { background-color: #ebf5eb; }
#content #logging #viewer tbody .level-warning span { background-color: #d5dd00; }
#content #logging #viewer tbody .level-severe span { background-color: #c43c35; color: #fff; }
#content #logging #viewer tbody .has-trace a
{
cursor: pointer;
}
#content #logging #viewer tbody .has-trace a:hover
{
color: #008;
}
#content #logging #viewer tbody .has-trace .message a
{
background-image: url( ../../img/ico/information.png );
background-position: 100% 50%;
display: block;
padding-right: 21px;
}
#content #logging #viewer tbody .has-trace.open .message a
{
background-image: url( ../../img/ico/information-white.png );
}
#content #logging #viewer tbody .trace
{
display: none;
}
#content #logging #viewer tbody .trace td
{
border-top: 0;
color: #c0c0c0;
}
#content #logging #viewer .has-data tfoot
{
display: none;
}
#content #logging #viewer tfoot td
{
color: #c0c0c0;
}
#content #logging .jstree > li #content #logging .jstree > li
{ {
margin-left: 0; margin-left: 0;

View File

@ -82,6 +82,12 @@ var sammy = $.sammy
{}, {},
function( context ) function( context )
{ {
if( app.timeout )
{
console.debug( 'Clearing Timeout #' + app.timeout );
clearTimeout( app.timeout );
}
var menu_wrapper = $( '#menu-wrapper' ); var menu_wrapper = $( '#menu-wrapper' );
$( 'li[id].active', menu_wrapper ) $( 'li[id].active', menu_wrapper )
@ -140,6 +146,8 @@ var solr_admin = function( app_config )
this.menu_element = $( '#menu-selector' ); this.menu_element = $( '#menu-selector' );
this.config = config; this.config = config;
this.timeout = null;
this.run = function() this.run = function()
{ {
$.ajax $.ajax

View File

@ -16,6 +16,8 @@
*/ */
var loglevel_path = null; var loglevel_path = null;
var frame_element = null;
var logging_handler = function( response, text_status, xhr ) var logging_handler = function( response, text_status, xhr )
{ {
var self = this; var self = this;
@ -248,6 +250,136 @@ var logging_handler = function( response, text_status, xhr )
}; };
var format_time = function( time )
{
time = time ? new Date( time ) : new Date();
return '<abbr title="' + time.toLocaleString().esc() + '">' + time.toTimeString().split( ' ' ).shift().esc() + '</abbr>';
}
var load_logging_viewer = function()
{
var table = $( 'table', frame_element );
var state = $( '#state', frame_element );
var since = table.data( 'latest' ) || 0;
var sticky_mode = null;
$.ajax
(
{
url : loglevel_path + '?wt=json&since=' + since,
dataType : 'json',
beforeSend : function( xhr, settings )
{
// initial request
if( 0 === since )
{
sticky_mode = true;
}
// state element is in viewport
else if( state.position().top <= $( window ).scrollTop() + $( window ).height() - ( $( 'body' ).height() - state.position().top ) )
{
sticky_mode = true;
}
else
{
sticky_mode = false;
}
},
success : function( response, text_status, xhr )
{
var docs = response.history.docs;
var docs_count = docs.length;
var table = $( 'table', frame_element );
$( 'h2 span', frame_element )
.text( response.watcher.esc() );
state
.html( 'Last Check: ' + format_time() );
app.timeout = setTimeout
(
load_logging_viewer,
10000
);
if( 0 === docs_count )
{
table.trigger( 'update' );
return false;
}
var content = '<tbody>';
for( var i = 0; i < docs_count; i++ )
{
var doc = docs[i];
var has_trace = 'undefined' !== typeof( doc.trace );
doc.logger = '<abbr title="' + doc.logger.esc() + '">' + doc.logger.split( '.' ).pop().esc() + '</abbr>';
var classes = [ 'level-' + doc.level.toLowerCase().esc() ];
if( has_trace )
{
classes.push( 'has-trace' );
}
content += '<tr class="' + classes.join( ' ' ) + '">' + "\n";
content += '<td class="span"><a><span>' + format_time( doc.time ) + '</span></a></td>' + "\n";
content += '<td class="level span"><a><span>' + doc.level.esc() + '</span></span></a></td>' + "\n";
content += '<td class="span"><a><span>' + doc.logger + '</span></a></td>' + "\n";
content += '<td class="message span"><a><span>' + doc.message.replace( /,/g, ',&#8203;' ).esc() + '</span></a></td>' + "\n";
content += '</tr>' + "\n";
if( has_trace )
{
content += '<tr class="trace">' + "\n";
// (1) with colspan
content += '<td colspan="4"><pre>' + doc.trace.esc() + '</pre></td>' + "\n";
// (2) without colspan
//content += '<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>';
//content += '<td>' + doc.trace.esc().replace( /\n/g, '<br>' ) + '</td>' + "\n";
content += '</tr>' + "\n";
}
}
content += '</tbody>';
$( 'table', frame_element )
.append( content );
table
.data( 'latest', response.info.last )
.removeClass( 'has-data' )
.trigger( 'update' );
if( sticky_mode )
{
$( 'body' )
.animate
(
{ scrollTop: state.position().top },
1000
);
}
},
error : function( xhr, text_status, error_thrown)
{
},
complete : function( xhr, text_status )
{
}
}
);
}
// #/~logging // #/~logging
sammy.get sammy.get
( (
@ -257,22 +389,121 @@ sammy.get
var core_basepath = $( 'li[data-basepath]', app.menu_element ).attr( 'data-basepath' ); var core_basepath = $( 'li[data-basepath]', app.menu_element ).attr( 'data-basepath' );
loglevel_path = core_basepath + '/admin/logging'; loglevel_path = core_basepath + '/admin/logging';
var content_element = $( '#content' ); var content_element = $( '#content' );
content_element
.html( '<div id="logging"></div>' );
$.ajax $.get
( (
'tpl/logging.html',
function( template )
{ {
url : loglevel_path + '?wt=json', content_element
dataType : 'json', .html( template );
context : $( '#logging', content_element ),
beforeSend : function( xhr, settings ) $( '#navigation a[href="' + context.path + '"]', content_element )
{ .parent().addClass( 'current' );
this
.html( '<div class="loader">Loading ...</div>' ); frame_element = $( '#frame', content_element );
}, frame_element
success : logging_handler .html
(
'<div id="viewer">' + "\n" +
'<div class="block">' + "\n" +
'<h2><span>&nbsp;</span></h2>' + "\n" +
'</div>' + "\n" +
'<table border="0" cellpadding="0" cellspacing="0">' + "\n" +
'<thead>' + "\n" +
'<tr>' + "\n" +
'<th class="time">Time</th>' + "\n" +
'<th class="level">Level</th>' + "\n" +
'<th class="logger">Logger</th>' + "\n" +
'<th class="message">Message</th>' + "\n" +
'</tr>' + "\n" +
'</thead>' + "\n" +
'<tfoot>' + "\n" +
'<tr>' + "\n" +
'<td colspan="4">No Events available</td>' + "\n" +
'</tr>' + "\n" +
'</thead>' + "\n" +
'</table>' + "\n" +
'<div id="state" class="loader">&nbsp;</div>' + "\n" +
'</div>'
);
var table = $( 'table', frame_element );
table
.die( 'update' )
.live
(
'update',
function( event )
{
var table = $( this );
var tbody = $( 'tbody', table );
0 !== tbody.size()
? table.addClass( 'has-data' )
: table.removeClass( 'has-data' );
return false;
}
);
load_logging_viewer();
$( '.has-trace a', table )
.die( 'click' )
.live
(
'click',
function( event )
{
$( this ).closest( 'tr' )
.toggleClass( 'open' )
.next().toggle();
return false;
}
);
}
);
}
);
// #/~logging/level
sammy.get
(
/^#\/~(logging)\/level$/,
function( context )
{
var core_basepath = $( 'li[data-basepath]', app.menu_element ).attr( 'data-basepath' );
loglevel_path = core_basepath + '/admin/logging';
var content_element = $( '#content' );
$.get
(
'tpl/logging.html',
function( template )
{
content_element
.html( template );
$( '#navigation a[href="' + context.path + '"]', content_element )
.parent().addClass( 'current' );
$.ajax
(
{
url : loglevel_path + '?wt=json',
dataType : 'json',
context : $( '#frame', content_element ),
beforeSend : function( xhr, settings )
{
this
.html( '<div class="loader">Loading ...</div>' );
},
success : logging_handler
}
);
} }
); );
} }

View File

@ -0,0 +1,32 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<div id="logging" class="clearfix">
<div id="frame">
</div>
<div id="navigation" class="clearfix">
<ul>
<li class="viewer"><a href="#/~logging">Viewer</a></li>
<li class="level"><a href="#/~logging/level">Level</a></li>
</ul>
</div>
</div>