// 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.
*/
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.debug.LogBuffer.CAPACITY = goog.define('goog.debug.LogBuffer.CAPACITY', 0);
/**
* The array to store the records.
* @type {!Array<!goog.debug.LogRecord|undefined>}
* @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);
};