jlog-rails 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/README.md +8 -1
- data/Rakefile +11 -1
- data/app/controllers/jlog/ajax_controller.rb +4 -4
- data/jlog-rails.gemspec +1 -0
- data/lib/jlog/version.rb +1 -1
- data/test/ajax-appender-test.js +22 -0
- data/test/buster.js +28 -0
- data/test/lib/jquery-1.9.1.min.js +5 -0
- data/test/lib/underscore.js +1226 -0
- data/test/logger-test.js +49 -0
- data/test/pattern-layout-test.js +37 -0
- data/vendor/assets/javascripts/appender.js +93 -0
- data/vendor/assets/javascripts/appenders/ajax.js +151 -0
- data/vendor/assets/javascripts/appenders/console.js +20 -0
- data/vendor/assets/javascripts/jlog.js +11 -236
- data/vendor/assets/javascripts/layout.js +216 -0
- data/vendor/assets/javascripts/layouts/pattern.js +184 -0
- data/vendor/assets/javascripts/levels.js +35 -0
- data/vendor/assets/javascripts/logger.js +370 -0
- data/vendor/assets/javascripts/logging_event.js +81 -0
- data/vendor/assets/javascripts/mount.js +4 -0
- metadata +38 -3
@@ -0,0 +1,216 @@
|
|
1
|
+
JLog.Layout = function() {};
|
2
|
+
/*
|
3
|
+
Class: Layout
|
4
|
+
|
5
|
+
Abstract class for message formatting.
|
6
|
+
*/
|
7
|
+
JLog.Layout.prototype = {
|
8
|
+
defaults: {
|
9
|
+
loggerKey: "logger",
|
10
|
+
timeStampKey: "timestamp",
|
11
|
+
millisecondsKey: "milliseconds",
|
12
|
+
levelKey: "level",
|
13
|
+
messageKey: "message",
|
14
|
+
exceptionKey: "exception",
|
15
|
+
urlKey: "url"
|
16
|
+
},
|
17
|
+
loggerKey: "logger",
|
18
|
+
timeStampKey: "timestamp",
|
19
|
+
millisecondsKey: "milliseconds",
|
20
|
+
levelKey: "level",
|
21
|
+
messageKey: "message",
|
22
|
+
exceptionKey: "exception",
|
23
|
+
urlKey: "url",
|
24
|
+
/*
|
25
|
+
Property: batchHeader
|
26
|
+
|
27
|
+
Header of batch output.
|
28
|
+
|
29
|
+
See Also:
|
30
|
+
<allowBatching>, <batchFooter>, <batchSeparator>
|
31
|
+
*/
|
32
|
+
batchHeader: "",
|
33
|
+
/*
|
34
|
+
Property: batchFooter
|
35
|
+
|
36
|
+
Footer of batch output.
|
37
|
+
|
38
|
+
See Also:
|
39
|
+
<allowBatching>, <batchHeader>, <batchSeparator>
|
40
|
+
*/
|
41
|
+
batchFooter: "",
|
42
|
+
/*
|
43
|
+
Property: batchSeparator
|
44
|
+
|
45
|
+
Separator of batch output.
|
46
|
+
|
47
|
+
See Also:
|
48
|
+
<allowBatching>, <batchHeader>, <batchFooter>
|
49
|
+
*/
|
50
|
+
batchSeparator: "",
|
51
|
+
/*
|
52
|
+
Property: useTimeStampsInMilliseconds
|
53
|
+
|
54
|
+
If timestamp should be outputted in milliseconds.
|
55
|
+
*/
|
56
|
+
useTimeStampsInMilliseconds: null,
|
57
|
+
|
58
|
+
/*
|
59
|
+
Method: format
|
60
|
+
|
61
|
+
Formats log message into a string. Has to be overloaded by derivative classes.
|
62
|
+
|
63
|
+
Parameters:
|
64
|
+
logMessage - Log Message to format.
|
65
|
+
|
66
|
+
Returns:
|
67
|
+
Message formatted as string.
|
68
|
+
*/
|
69
|
+
format: function(logMessage) {
|
70
|
+
JLog.handleError("Layout.format: layout supplied has no format() method");
|
71
|
+
},
|
72
|
+
|
73
|
+
/*
|
74
|
+
Method: getContentType
|
75
|
+
|
76
|
+
Used to set content type for network sending.
|
77
|
+
|
78
|
+
Returns:
|
79
|
+
Content-Type header value.
|
80
|
+
*/
|
81
|
+
getContentType: function() {
|
82
|
+
return "text/plain";
|
83
|
+
},
|
84
|
+
|
85
|
+
/*
|
86
|
+
Method: allowBatching
|
87
|
+
|
88
|
+
If formatted messages can be send in a batch. If true, messages will be send in format:
|
89
|
+
batchHeader+MESSAGES.join(batchSeparator)+batchFooter
|
90
|
+
|
91
|
+
Returns:
|
92
|
+
Boolean
|
93
|
+
|
94
|
+
See Also:
|
95
|
+
<batchHeader>, <batchFooter>, <batchSeparator>
|
96
|
+
*/
|
97
|
+
allowBatching: function() {
|
98
|
+
return true;
|
99
|
+
},
|
100
|
+
|
101
|
+
/*
|
102
|
+
Method: getTimeStampValue
|
103
|
+
|
104
|
+
Returns string representation of time of event occurrence in seconds or milliseconds, depending on configuration.
|
105
|
+
|
106
|
+
Parameters:
|
107
|
+
loggingEvent - <LoggingEvent> to fetch timestamp.
|
108
|
+
*/
|
109
|
+
getTimeStampValue: function(loggingEvent) {
|
110
|
+
return this.useTimeStampsInMilliseconds() ?
|
111
|
+
loggingEvent.timeStampInMilliseconds : loggingEvent.timeStampInSeconds;
|
112
|
+
},
|
113
|
+
|
114
|
+
/*
|
115
|
+
Method: getDataValues
|
116
|
+
|
117
|
+
Builds the map of log event environment.
|
118
|
+
|
119
|
+
Parameters:
|
120
|
+
loggingEvent - <LoggingEvent> to fetch data from.
|
121
|
+
combineMessages - Boolean, if messages should be combined into single String, or Array is required.
|
122
|
+
*/
|
123
|
+
getDataValues: function(loggingEvent, combineMessages) {
|
124
|
+
var dataValues = [
|
125
|
+
[this.loggerKey, loggingEvent.logger.name],
|
126
|
+
[this.timeStampKey, this.getTimeStampValue(loggingEvent)],
|
127
|
+
[this.levelKey, loggingEvent.level.name],
|
128
|
+
[this.urlKey, window.location.href],
|
129
|
+
[this.messageKey, combineMessages ? loggingEvent.getCombinedMessages() : loggingEvent.messages]
|
130
|
+
];
|
131
|
+
if(!this.useTimeStampsInMilliseconds()) {
|
132
|
+
dataValues.push([this.millisecondsKey, loggingEvent.milliseconds]);
|
133
|
+
}
|
134
|
+
if(loggingEvent.exception) {
|
135
|
+
dataValues.push([this.exceptionKey, getExceptionStringRep(loggingEvent.exception)]);
|
136
|
+
}
|
137
|
+
if(this.hasCustomFields()) {
|
138
|
+
for(var i = 0, len = this.customFields.length; i < len; i++) {
|
139
|
+
var val = this.customFields[i].value;
|
140
|
+
|
141
|
+
// Check if the value is a function. If so, execute it, passing it the
|
142
|
+
// current layout and the logging event
|
143
|
+
try {
|
144
|
+
if(typeof val === "function")
|
145
|
+
val = val(this, loggingEvent);
|
146
|
+
} catch(e) {
|
147
|
+
JLog.handleError(e);
|
148
|
+
val = "[Exception during evaluating]"
|
149
|
+
}
|
150
|
+
|
151
|
+
dataValues.push([this.customFields[i].name, val]);
|
152
|
+
}
|
153
|
+
}
|
154
|
+
return dataValues;
|
155
|
+
},
|
156
|
+
|
157
|
+
/*
|
158
|
+
Method: setKeys
|
159
|
+
|
160
|
+
Sets key names for standard environment variables.
|
161
|
+
|
162
|
+
Parameters:
|
163
|
+
loggerKey - key for <Logger> name value
|
164
|
+
timeStampKey - key for timestamp value
|
165
|
+
levelKey - key for event <Level> value
|
166
|
+
messageKey - key for message value(s)
|
167
|
+
exceptionKey - key for exception value
|
168
|
+
urlKey - key for URL value
|
169
|
+
millisecondsKey - key for timestamp value in milliseconds
|
170
|
+
*/
|
171
|
+
setKeys: function(loggerKey, timeStampKey, levelKey, messageKey,
|
172
|
+
exceptionKey, urlKey, millisecondsKey) {
|
173
|
+
this.loggerKey = extractStringFromParam(loggerKey, this.defaults.loggerKey);
|
174
|
+
this.timeStampKey = extractStringFromParam(timeStampKey, this.defaults.timeStampKey);
|
175
|
+
this.levelKey = extractStringFromParam(levelKey, this.defaults.levelKey);
|
176
|
+
this.messageKey = extractStringFromParam(messageKey, this.defaults.messageKey);
|
177
|
+
this.exceptionKey = extractStringFromParam(exceptionKey, this.defaults.exceptionKey);
|
178
|
+
this.urlKey = extractStringFromParam(urlKey, this.defaults.urlKey);
|
179
|
+
this.millisecondsKey = extractStringFromParam(millisecondsKey, this.defaults.millisecondsKey);
|
180
|
+
},
|
181
|
+
|
182
|
+
/*
|
183
|
+
Method: setCustomField
|
184
|
+
|
185
|
+
Sets custom variable of the layout.
|
186
|
+
|
187
|
+
Parameters:
|
188
|
+
name - Key for custom field
|
189
|
+
value - Value for custom field
|
190
|
+
*/
|
191
|
+
setCustomField: function(name, value) {
|
192
|
+
var fieldUpdated = false;
|
193
|
+
for (var i = 0, len = this.customFields.length; i < len; i++) {
|
194
|
+
if (this.customFields[i].name === name) {
|
195
|
+
this.customFields[i].value = value;
|
196
|
+
fieldUpdated = true;
|
197
|
+
}
|
198
|
+
}
|
199
|
+
if (!fieldUpdated) {
|
200
|
+
this.customFields.push({"name": name, "value": value});
|
201
|
+
}
|
202
|
+
},
|
203
|
+
|
204
|
+
/*
|
205
|
+
Method: hasCustomFields
|
206
|
+
|
207
|
+
Checks, if there are any custom fields.
|
208
|
+
*/
|
209
|
+
hasCustomFields: function() {
|
210
|
+
return (this.customFields.length > 0);
|
211
|
+
},
|
212
|
+
|
213
|
+
toString: function() {
|
214
|
+
JLog.handleError("Layout.toString: all layouts must override this method");
|
215
|
+
}
|
216
|
+
};
|
@@ -0,0 +1,184 @@
|
|
1
|
+
(function() {
|
2
|
+
var newLine = "\n";
|
3
|
+
|
4
|
+
/*
|
5
|
+
Class: PatternLayout
|
6
|
+
|
7
|
+
Pattern based layout.
|
8
|
+
*/
|
9
|
+
|
10
|
+
/*
|
11
|
+
Constructor: PatternLayout
|
12
|
+
|
13
|
+
Initializes Pattern Layout. Recognizes patterns like %[padding][trunctaion](type)[specifier], where type can be:
|
14
|
+
- *a* - array of messages.
|
15
|
+
- *m* - prints all the messages. Objects are dumped to the _specifier_ depth.
|
16
|
+
- *c* - prints logger name
|
17
|
+
- *d* - prints log event date
|
18
|
+
- *f* - prints custom field defined by _specifier_
|
19
|
+
- *n* - prints new line
|
20
|
+
- *p* - prints log event level name
|
21
|
+
- *r* - prints time in seconds since JLog startup
|
22
|
+
- *%* - prints % sign
|
23
|
+
|
24
|
+
Parameters:
|
25
|
+
pattern - (optional) String format
|
26
|
+
*/
|
27
|
+
function PatternLayout(pattern) {
|
28
|
+
if(pattern) this.pattern = pattern;
|
29
|
+
else this.pattern = PatternLayout.DEFAULT_CONVERSION_PATTERN;
|
30
|
+
this.customFields = [];
|
31
|
+
}
|
32
|
+
|
33
|
+
/*
|
34
|
+
Constant: TTCC_CONVERSION_PATTERN
|
35
|
+
|
36
|
+
Usual verbose pattern.
|
37
|
+
*/
|
38
|
+
PatternLayout.TTCC_CONVERSION_PATTERN = "%r %p %c - %m%n";
|
39
|
+
|
40
|
+
/*
|
41
|
+
Constant: DEFAULT_CONVERSION_PATTERN
|
42
|
+
|
43
|
+
Default concise pattern.
|
44
|
+
*/
|
45
|
+
PatternLayout.DEFAULT_CONVERSION_PATTERN = "%m%n";
|
46
|
+
|
47
|
+
PatternLayout.prototype = new JLog.Layout();
|
48
|
+
|
49
|
+
/*
|
50
|
+
Method: format
|
51
|
+
|
52
|
+
Formats event into string.
|
53
|
+
|
54
|
+
Parameters:
|
55
|
+
loggingEvent - <LoggingEvent> to format
|
56
|
+
*/
|
57
|
+
PatternLayout.prototype.format = function(loggingEvent) {
|
58
|
+
var regex = /%(-?[0-9]+)?(\.?[0-9]+)?([acdfmMnpr%])(\{([^\}]+)\})?|([^%]+)/;
|
59
|
+
var formattedString = "";
|
60
|
+
var result;
|
61
|
+
var searchString = this.pattern;
|
62
|
+
|
63
|
+
// Cannot use regex global flag since it doesn't work with exec in IE5
|
64
|
+
while ((result = regex.exec(searchString))) {
|
65
|
+
var matchedString = result[0];
|
66
|
+
var padding = result[1];
|
67
|
+
var truncation = result[2];
|
68
|
+
var conversionCharacter = result[3];
|
69
|
+
var specifier = result[5];
|
70
|
+
var text = result[6];
|
71
|
+
|
72
|
+
// Check if the pattern matched was just normal text
|
73
|
+
if (text) {
|
74
|
+
formattedString += "" + text;
|
75
|
+
} else {
|
76
|
+
// Create a raw replacement string based on the conversion
|
77
|
+
// character and specifier
|
78
|
+
var replacement = "";
|
79
|
+
switch(conversionCharacter) {
|
80
|
+
case "a": // Array of messages
|
81
|
+
case "m": // Message
|
82
|
+
var depth = 0;
|
83
|
+
if (specifier) {
|
84
|
+
depth = parseInt(specifier, 10);
|
85
|
+
if (isNaN(depth)) {
|
86
|
+
handleError("PatternLayout.format: invalid specifier '" +
|
87
|
+
specifier + "' for conversion character '" + conversionCharacter +
|
88
|
+
"' - should be a number");
|
89
|
+
depth = 0;
|
90
|
+
}
|
91
|
+
}
|
92
|
+
var messages = (conversionCharacter === "a") ? loggingEvent.messages[0] : loggingEvent.messages;
|
93
|
+
for (var i = 0, len = messages.length; i < len; i++) {
|
94
|
+
if (i > 0 && (replacement.charAt(replacement.length - 1) !== " ")) {
|
95
|
+
replacement += " ";
|
96
|
+
}
|
97
|
+
if (depth === 0) {
|
98
|
+
replacement += messages[i];
|
99
|
+
} else {
|
100
|
+
replacement += formatObjectExpansion(messages[i], depth);
|
101
|
+
}
|
102
|
+
}
|
103
|
+
break;
|
104
|
+
case "c": // Logger name
|
105
|
+
var loggerName = loggingEvent.logger.getName();
|
106
|
+
if (specifier) {
|
107
|
+
var precision = parseInt(specifier, 10);
|
108
|
+
var loggerNameBits = loggingEvent.logger.getName().split(".");
|
109
|
+
if (precision >= loggerNameBits.length) {
|
110
|
+
replacement = loggerName;
|
111
|
+
} else {
|
112
|
+
replacement = loggerNameBits.slice(loggerNameBits.length - precision).join(".");
|
113
|
+
}
|
114
|
+
} else {
|
115
|
+
replacement = loggerName;
|
116
|
+
}
|
117
|
+
break;
|
118
|
+
case "d": // Date
|
119
|
+
replacement = "[date-not-implemented]";
|
120
|
+
break;
|
121
|
+
case "f": // Custom field
|
122
|
+
if (this.hasCustomFields()) {
|
123
|
+
var ff = _.findWhere(this.customFields, {name: specifier});
|
124
|
+
if(!ff) replacement = "[Custom Field not fount: " + specifier + "]";
|
125
|
+
else replacement = ff.value;
|
126
|
+
}
|
127
|
+
break;
|
128
|
+
case "n": // New line
|
129
|
+
replacement = newLine;
|
130
|
+
break;
|
131
|
+
case "p": // Level
|
132
|
+
replacement = loggingEvent.level.name;
|
133
|
+
break;
|
134
|
+
case "r": // Milliseconds since log4javascript startup
|
135
|
+
replacement = "" + (loggingEvent.timeStamp.getTime() - JLog.startup.getTime());
|
136
|
+
break;
|
137
|
+
case "%": // Literal % sign
|
138
|
+
replacement = "%";
|
139
|
+
break;
|
140
|
+
default:
|
141
|
+
replacement = matchedString;
|
142
|
+
break;
|
143
|
+
}
|
144
|
+
// Format the replacement according to any padding or
|
145
|
+
// truncation specified
|
146
|
+
var l;
|
147
|
+
|
148
|
+
// First, truncation
|
149
|
+
if (truncation) {
|
150
|
+
l = parseInt(truncation.substr(1), 10);
|
151
|
+
var strLen = replacement.length;
|
152
|
+
if (l < strLen) {
|
153
|
+
replacement = replacement.substring(strLen - l, strLen);
|
154
|
+
}
|
155
|
+
}
|
156
|
+
// Next, padding
|
157
|
+
if (padding) {
|
158
|
+
if (padding.charAt(0) == "-") {
|
159
|
+
l = parseInt(padding.substr(1), 10);
|
160
|
+
// Right pad with spaces
|
161
|
+
while (replacement.length < l) {
|
162
|
+
replacement += " ";
|
163
|
+
}
|
164
|
+
} else {
|
165
|
+
l = parseInt(padding, 10);
|
166
|
+
// Left pad with spaces
|
167
|
+
while (replacement.length < l) {
|
168
|
+
replacement = " " + replacement;
|
169
|
+
}
|
170
|
+
}
|
171
|
+
}
|
172
|
+
formattedString += replacement;
|
173
|
+
}
|
174
|
+
searchString = searchString.substr(result.index + result[0].length);
|
175
|
+
}
|
176
|
+
return formattedString;
|
177
|
+
};
|
178
|
+
|
179
|
+
PatternLayout.prototype.toString = function() {
|
180
|
+
return "PatternLayout";
|
181
|
+
};
|
182
|
+
|
183
|
+
JLog.PatternLayout = PatternLayout;
|
184
|
+
})(JLog);
|
@@ -0,0 +1,35 @@
|
|
1
|
+
/*
|
2
|
+
Enum: Level
|
3
|
+
|
4
|
+
Levels of messages.
|
5
|
+
|
6
|
+
ALL - Used to mark <Logger> of <Appender> as ones allowing all messages.
|
7
|
+
DEBUG - Minimal priority for message. This one is used for least valuable, and massive messages.
|
8
|
+
INFO - Used to trace the system status. These messages are less aggressive then <Level.DEBUG>.
|
9
|
+
WARN - Something could be better at this time.
|
10
|
+
ERROR - Same as <Level.WARN>, but brakes some part of the system. Has to be fixed.
|
11
|
+
FATAL - Same as <Level.WARN>, but brakes all the system. If not fixed - nothing will work at all.
|
12
|
+
NONE - Used to mark <Logger> of <Appender> as ones blocking all the messages.
|
13
|
+
*/
|
14
|
+
JLog.Level = (function() {
|
15
|
+
function Level(priority, name) {
|
16
|
+
this.priority = priority;
|
17
|
+
this.name = name;
|
18
|
+
};
|
19
|
+
|
20
|
+
Level.prototype = {
|
21
|
+
isGreaterOrEqual: function(otherLevel) {
|
22
|
+
return this.priority >= otherLevel.priority;
|
23
|
+
}
|
24
|
+
};
|
25
|
+
|
26
|
+
Level.ALL = new Level(0, "ALL");
|
27
|
+
Level.DEBUG = new Level(1, "DEBUG");
|
28
|
+
Level.INFO = new Level(2, "INFO");
|
29
|
+
Level.WARN = new Level(3, "WARN");
|
30
|
+
Level.ERROR = new Level(4, "ERROR");
|
31
|
+
Level.FATAL = new Level(5, "FATAL");
|
32
|
+
Level.NONE = new Level(6, "NONE");
|
33
|
+
|
34
|
+
return Level;
|
35
|
+
})();
|