/* * Copyright © 2012, 2013 Pedro Agullo Soliveres. * * This file is part of Log4js-ext. * * Log4js-ext is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License. * * Commercial use is permitted to the extent that the code/component(s) * do NOT become part of another Open Source or Commercially developed * licensed development library or toolkit without explicit permission. * * Log4js-ext is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Log4js-ext. If not, see <http://www.gnu.org/licenses/>. * * This software uses the ExtJs library (http://extjs.com), which is * distributed under the GPL v3 license (see http://extjs.com/license). */ /*jslint strict:false */ (function() { // "use strict"; //$NON-NLS-1$ /** * An appender that knows how to output data to the built-in log viewer * window (see {@link Sm.log.LogViewerWindow}). */ Ext.define('Sm.log.LogViewerAppender', { //$NON-NLS-1$ extend : 'Sm.log.AppenderBase', uses : ['Sm.log.util.Assert'], /** * @private * * Attaches the appender to a viewer. * * @param {Sm.log.LogViewerWindow} viewer * The viewer to which to attach this appender. * * @returns {void} */ attachViewer : function( viewer ) { Sm.log.util.Assert.assert(viewer); Sm.log.util.Assert.assert( !this.viewer ); this.viewer = viewer; }, /** * @private * * Detaches the appender from this viewer. * * @returns {void} */ detachViewer : function() { Sm.log.util.Assert.assert( this.viewer); if( this.isLogging() ) { this.startBuffering(); } this.viewer = null; }, /** * Starts buffering logs. * * While buffering, logs are not sent to the viewer window automatically, * but rather they are kept apart until we change the status to logging. * Then, all buffered logs will be sent to the window. * * This is useful in cases where the viewer window should not be updated * to avoid interference while debugging, or where the window simply does * not exist but we want to register such log nevertheless. * * @returns {void} */ startBuffering : function() { this.state = Sm.log.AppenderBase.BUFFERING; }, /** * Returns true if the viewer is buffering logs. * * @returns {Boolean} true if the viewer is buffering logs. */ isBuffering : function () { return this.state === Sm.log.AppenderBase.BUFFERING; }, /** * Clears the buffered logs. * * The buffered log are lost. * * @returns {void} */ clearBuffer : function() { this.buffer = []; }, /** * Returns true if we can log. * * Note that we might not be able to log directly when the viewer * window is not available, for example. * * @returns {Boolean} */ canLog : function() { return this.viewer; }, /** * Sets the appender in the loggins state. * * All logs sent to the appender from now on will be logged. * Besides, if there were some buffered logs, they will be immediately * sent to the log viewer window, if any. * * @returns {void} */ startLogging : function() { // If not attached, we can't start logging Sm.log.util.Assert.assert( this.canLog() ); if( this.buffer.length > 0 ) { this.doPhysicalLog( this.buffer); this.clearBuffer(); } this.callParent(arguments); }, /** * @inheritDoc */ stopLogging : function () { this.callParent(arguments); this.clearBuffer(); }, /** * Returns true, as this appender supports log buffering. * * @returns {Boolean} true, as this appender supports log buffering. */ supportsBuffering : function() { return true; }, /** * @protected * @inheritDoc */ setInitialState : function () { this.startBuffering(); }, /** * Creates a new log viewer appender. * * @param cfg */ constructor : function (cfg ) { this.callParent(arguments); // We are going to output to HTML, in the end this.setHtmlEncodedLogEventProperties( [// "time" // Never encode this, it is a Date // ,"formattedTime" // If some layout adds HTML, we want HTML "message" ,"ndc" // ,"hasLoggedObject" // Never encode this, it is a boolean ,"formattedMessage" // ,"formattedLoggedObject" // We *are* adding HTML, want it used ] ); this.clearBuffer(); }, /** * @inheritDoc * * @protected * * @param logEvent */ doLog : function(logEvent) { var indent = 5; // @todo: pag Dislike doing this here, maybe should create a custom // layout that adds the formattedMultilineLoggedObject? // But that is cumbersome logEvent.formattedMultilineLoggedObject = ''; if( logEvent.hasLoggedObject) { logEvent.formattedMultilineLoggedObject = this.getLayout().jsonLikeFormat( logEvent.loggedObject, true, true, indent ); } logEvent.formattedMultilineMessage = logEvent.formattedMessage.replace( /(\r\n|\n|\r)/gm, '<br>'); if( this.isBuffering()) { this.buffer.push(logEvent); } else { this.doPhysicalLog([logEvent]); } }, /** * @private * * Performs outputs of an array of log events. * * Using an array can help with performance, as it allows to * send a handful of buffered logs in a single step. * * @param {Array} logEvents * * @returns {void} */ doPhysicalLog : function(logEvents) { Sm.log.util.Assert.assert( this.viewer); this.viewer.appendLoggingEvents(logEvents); } }); }());