// Copyright 2010 The Closure Library Authors. All Rights Reserved. // // Licensed 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. /** * @fileoverview A buffer for log records. The purpose of this is to improve * logging performance by re-using old objects when the buffer becomes full and * to eliminate the need for each app to implement their own log buffer. The * disadvantage to doing this is that log handlers cannot maintain references to * log records and expect that they are not overwriten at a later point. * * @author agrieve@google.com (Andrew Grieve) */ goog.provide('goog.debug.LogBuffer'); goog.require('goog.asserts'); goog.require('goog.debug.LogRecord'); /** * Creates the log buffer. * @constructor * @final */ goog.debug.LogBuffer = function() { goog.asserts.assert( goog.debug.LogBuffer.isBufferingEnabled(), 'Cannot use goog.debug.LogBuffer without defining ' + 'goog.debug.LogBuffer.CAPACITY.'); this.clear(); }; /** * A static method that always returns the same instance of LogBuffer. * @return {!goog.debug.LogBuffer} The LogBuffer singleton instance. */ goog.debug.LogBuffer.getInstance = function() { if (!goog.debug.LogBuffer.instance_) { // This function is written with the return statement after the assignment // to avoid the jscompiler StripCode bug described in http://b/2608064. // After that bug is fixed this can be refactored. goog.debug.LogBuffer.instance_ = new goog.debug.LogBuffer(); } return goog.debug.LogBuffer.instance_; }; /** * @define {number} The number of log records to buffer. 0 means disable * buffering. */ goog.define('goog.debug.LogBuffer.CAPACITY', 0); /** * The array to store the records. * @type {!Array} * @private */ goog.debug.LogBuffer.prototype.buffer_; /** * The index of the most recently added record or -1 if there are no records. * @type {number} * @private */ goog.debug.LogBuffer.prototype.curIndex_; /** * Whether the buffer is at capacity. * @type {boolean} * @private */ goog.debug.LogBuffer.prototype.isFull_; /** * Adds a log record to the buffer, possibly overwriting the oldest record. * @param {goog.debug.Logger.Level} level One of the level identifiers. * @param {string} msg The string message. * @param {string} loggerName The name of the source logger. * @return {!goog.debug.LogRecord} The log record. */ goog.debug.LogBuffer.prototype.addRecord = function(level, msg, loggerName) { var curIndex = (this.curIndex_ + 1) % goog.debug.LogBuffer.CAPACITY; this.curIndex_ = curIndex; if (this.isFull_) { var ret = this.buffer_[curIndex]; ret.reset(level, msg, loggerName); return ret; } this.isFull_ = curIndex == goog.debug.LogBuffer.CAPACITY - 1; return this.buffer_[curIndex] = new goog.debug.LogRecord(level, msg, loggerName); }; /** * @return {boolean} Whether the log buffer is enabled. */ goog.debug.LogBuffer.isBufferingEnabled = function() { return goog.debug.LogBuffer.CAPACITY > 0; }; /** * Removes all buffered log records. */ goog.debug.LogBuffer.prototype.clear = function() { this.buffer_ = new Array(goog.debug.LogBuffer.CAPACITY); this.curIndex_ = -1; this.isFull_ = false; }; /** * Calls the given function for each buffered log record, starting with the * oldest one. * @param {function(!goog.debug.LogRecord)} func The function to call. */ goog.debug.LogBuffer.prototype.forEachRecord = function(func) { var buffer = this.buffer_; // Corner case: no records. if (!buffer[0]) { return; } var curIndex = this.curIndex_; var i = this.isFull_ ? curIndex : -1; do { i = (i + 1) % goog.debug.LogBuffer.CAPACITY; func(/** @type {!goog.debug.LogRecord} */ (buffer[i])); } while (i != curIndex); };