# lib/goog/debug/logbuffer.js

    1// Copyright 2010 The Closure Library Authors. All Rights Reserved.2//3// Licensed under the Apache License, Version 2.0 (the "License");4// you may not use this file except in compliance with the License.5// You may obtain a copy of the License at6//7//      http://www.apache.org/licenses/LICENSE-2.08//9// Unless required by applicable law or agreed to in writing, software10// distributed under the License is distributed on an "AS-IS" BASIS,11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12// See the License for the specific language governing permissions and13// limitations under the License.1415/**16 * @fileoverview A buffer for log records. The purpose of this is to improve17 * logging performance by re-using old objects when the buffer becomes full and18 * to eliminate the need for each app to implement their own log buffer. The19 * disadvantage to doing this is that log handlers cannot maintain references to20 * log records and expect that they are not overwriten at a later point.21 *22 * @author agrieve@google.com (Andrew Grieve)23 */2425goog.provide('goog.debug.LogBuffer');2627goog.require('goog.asserts');28goog.require('goog.debug.LogRecord');29303132/**33 * Creates the log buffer.34 * @constructor35 * @final36 */37goog.debug.LogBuffer = function() {38  goog.asserts.assert(goog.debug.LogBuffer.isBufferingEnabled(),39      'Cannot use goog.debug.LogBuffer without defining ' +40      'goog.debug.LogBuffer.CAPACITY.');41  this.clear();42};434445/**46 * A static method that always returns the same instance of LogBuffer.47 * @return {!goog.debug.LogBuffer} The LogBuffer singleton instance.48 */49goog.debug.LogBuffer.getInstance = function() {50  if (!goog.debug.LogBuffer.instance_) {51    // This function is written with the return statement after the assignment52    // to avoid the jscompiler StripCode bug described in http://b/2608064.53    // After that bug is fixed this can be refactored.54    goog.debug.LogBuffer.instance_ = new goog.debug.LogBuffer();55  }56  return goog.debug.LogBuffer.instance_;57};585960/**61 * @define {number} The number of log records to buffer. 0 means disable62 * buffering.63 */64goog.define('goog.debug.LogBuffer.CAPACITY', 0);656667/**68 * The array to store the records.69 * @type {!Array.<!goog.debug.LogRecord|undefined>}70 * @private71 */72goog.debug.LogBuffer.prototype.buffer_;737475/**76 * The index of the most recently added record or -1 if there are no records.77 * @type {number}78 * @private79 */80goog.debug.LogBuffer.prototype.curIndex_;818283/**84 * Whether the buffer is at capacity.85 * @type {boolean}86 * @private87 */88goog.debug.LogBuffer.prototype.isFull_;899091/**92 * Adds a log record to the buffer, possibly overwriting the oldest record.93 * @param {goog.debug.Logger.Level} level One of the level identifiers.94 * @param {string} msg The string message.95 * @param {string} loggerName The name of the source logger.96 * @return {!goog.debug.LogRecord} The log record.97 */98goog.debug.LogBuffer.prototype.addRecord = function(level, msg, loggerName) {99  var curIndex = (this.curIndex_ + 1) % goog.debug.LogBuffer.CAPACITY;100  this.curIndex_ = curIndex;101  if (this.isFull_) {102    var ret = this.buffer_[curIndex];103    ret.reset(level, msg, loggerName);104    return ret;105  }106  this.isFull_ = curIndex == goog.debug.LogBuffer.CAPACITY - 1;107  return this.buffer_[curIndex] =108      new goog.debug.LogRecord(level, msg, loggerName);109};110111112/**113 * @return {boolean} Whether the log buffer is enabled.114 */115goog.debug.LogBuffer.isBufferingEnabled = function() {116  return goog.debug.LogBuffer.CAPACITY > 0;117};118119120/**121 * Removes all buffered log records.122 */123goog.debug.LogBuffer.prototype.clear = function() {124  this.buffer_ = new Array(goog.debug.LogBuffer.CAPACITY);125  this.curIndex_ = -1;126  this.isFull_ = false;127};128129130/**131 * Calls the given function for each buffered log record, starting with the132 * oldest one.133 * @param {function(!goog.debug.LogRecord)} func The function to call.134 */135goog.debug.LogBuffer.prototype.forEachRecord = function(func) {136  var buffer = this.buffer_;137  // Corner case: no records.138  if (!buffer[0]) {139    return;140  }141  var curIndex = this.curIndex_;142  var i = this.isFull_ ? curIndex : -1;143  do {144    i = (i + 1) % goog.debug.LogBuffer.CAPACITY;145    func(/** @type {!goog.debug.LogRecord} */ (buffer[i]));146  } while (i != curIndex);147};148