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 | |