# 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 |
25 | goog.provide('goog.debug.LogBuffer');
26 |
27 | goog.require('goog.asserts');
28 | goog.require('goog.debug.LogRecord');
29 |
30 |
31 |
32 | /**
33 | * Creates the log buffer.
34 | * @constructor
35 | * @final
36 | */
37 | goog.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 | */
49 | goog.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 | */
64 | goog.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 | */
72 | goog.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 | */
80 | goog.debug.LogBuffer.prototype.curIndex_;
81 |
82 |
83 | /**
84 | * Whether the buffer is at capacity.
85 | * @type {boolean}
86 | * @private
87 | */
88 | goog.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 | */
98 | goog.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 | */
115 | goog.debug.LogBuffer.isBufferingEnabled = function() {
116 | return goog.debug.LogBuffer.CAPACITY > 0;
117 | };
118 |
119 |
120 | /**
121 | * Removes all buffered log records.
122 | */
123 | goog.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 | */
135 | goog.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 |