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 at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// 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 and
13// limitations under the License.
14
15/**
16 * @fileoverview A buffer for log records. The purpose of this is to improve
17 * logging performance by re-using old objects when the buffer becomes full and
18 * to eliminate the need for each app to implement their own log buffer. The
19 * disadvantage to doing this is that log handlers cannot maintain references to
20 * log records and expect that they are not overwriten at a later point.
21 *
22 * @author agrieve@google.com (Andrew Grieve)
23 */
24
25goog.provide('goog.debug.LogBuffer');
26
27goog.require('goog.asserts');
28goog.require('goog.debug.LogRecord');
29
30
31
32/**
33 * Creates the log buffer.
34 * @constructor
35 * @final
36 */
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};
43
44
45/**
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 assignment
52 // 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};
58
59
60/**
61 * @define {number} The number of log records to buffer. 0 means disable
62 * buffering.
63 */
64goog.define('goog.debug.LogBuffer.CAPACITY', 0);
65
66
67/**
68 * The array to store the records.
69 * @type {!Array.<!goog.debug.LogRecord|undefined>}
70 * @private
71 */
72goog.debug.LogBuffer.prototype.buffer_;
73
74
75/**
76 * The index of the most recently added record or -1 if there are no records.
77 * @type {number}
78 * @private
79 */
80goog.debug.LogBuffer.prototype.curIndex_;
81
82
83/**
84 * Whether the buffer is at capacity.
85 * @type {boolean}
86 * @private
87 */
88goog.debug.LogBuffer.prototype.isFull_;
89
90
91/**
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};
110
111
112/**
113 * @return {boolean} Whether the log buffer is enabled.
114 */
115goog.debug.LogBuffer.isBufferingEnabled = function() {
116 return goog.debug.LogBuffer.CAPACITY > 0;
117};
118
119
120/**
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};
128
129
130/**
131 * Calls the given function for each buffered log record, starting with the
132 * 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