Created
August 23, 2012 21:07
-
-
Save leoroos/3441763 to your computer and use it in GitHub Desktop.
Addition of file location and line number output for a log statement of log4javascript. The addition is made in the Patternlayout.format function.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
PatternLayout.prototype.format = function(loggingEvent) { | |
var regex = /%(-?[0-9]+)?(\.?[0-9]+)?([acdflmMnpr%])(\{([^\}]+)\})?|([^%]+)/; | |
var formattedString = ""; | |
var result; | |
var searchString = this.pattern; | |
// Cannot use regex global flag since it doesn't work with exec in IE5 | |
while ((result = regex.exec(searchString))) { | |
var matchedString = result[0]; | |
var padding = result[1]; | |
var truncation = result[2]; | |
var conversionCharacter = result[3]; | |
var specifier = result[5]; | |
var text = result[6]; | |
// Check if the pattern matched was just normal text | |
if (text) { | |
formattedString += "" + text; | |
} else { | |
// Create a raw replacement string based on the conversion | |
// character and specifier | |
var replacement = ""; | |
switch(conversionCharacter) { | |
//BEGIN -----------------------Additional Option to output the calling file name and line number of the logging call. | |
case "l": //Location | |
var isChrome = navigator.userAgent.indexOf("Chrome") !== -1; | |
if(isChrome){ | |
//do someting else | |
var stack = new Error().stack; | |
var lineAccessingLogger = stack.split("\n")[8]; | |
var funcBegin = lineAccessingLogger.indexOf("at ") + 3; | |
var resourceBegin = lineAccessingLogger.indexOf(" (") + 2; | |
var functionName = funcBegin < resourceBegin ? lineAccessingLogger.substring(funcBegin,resourceBegin-2) : null; | |
var resourceLoc; | |
if(functionName){ | |
resourceLoc = lineAccessingLogger.substring(resourceBegin,lineAccessingLogger.length-1); | |
}else{ | |
functionName = "(anonymous)"; | |
resourceLoc = lineAccessingLogger.substring(funcBegin); | |
} | |
var colIdx = resourceLoc.lastIndexOf(":"); | |
var column = parseInt(resourceLoc.substring(colIdx+1),10); | |
var lineIdx = resourceLoc.lastIndexOf(":",colIdx-1); | |
var line = parseInt(resourceLoc.substring(lineIdx+1,colIdx),10); | |
var resource = resourceLoc.substring(0,lineIdx); | |
var lastSegmentIdx = resource.lastIndexOf("/"); | |
var lastSegment = resource.substring(lastSegmentIdx+1); | |
/* | |
var resultObject = { | |
r : resource, | |
l : line, | |
c : column, | |
f : functionName, | |
s : lastSegment | |
}; | |
*/ | |
var spec = "s:l"; | |
if(specifier)spec = specifier; | |
var specresult = []; | |
var priorNum = ""; | |
for ( var int = 0; int < spec.length; int++) { | |
var l = spec[int]; | |
var num = parseInt(l,10); | |
if(num > -1 ){ | |
priorNum += l; | |
continue; | |
}else{ | |
if(priorNum.length >0){ | |
specresult.push(parseInt(priorNum,10)); | |
priorNum = ""; | |
} | |
specresult.push(l); | |
} | |
} | |
if(priorNum.length >0) | |
specresult.push(parseInt(priorNum,10)); | |
spec = specresult; | |
for ( var int = 0; int < spec.length; int++) { | |
var optNum = spec[int+1]; | |
switch(spec[int]){ | |
case "s": | |
replacement += lastSegment; | |
break; | |
case "r": | |
var string = resource; | |
if(typeof optNum === "number"){ | |
string = string.substring(string.length-optNum); | |
spec.splice(int+1,1); | |
} | |
replacement += string; | |
break; | |
case "l": | |
replacement += line; | |
break; | |
case "c": | |
replacement += column; | |
break; | |
case "f": | |
var string = functionName; | |
if(typeof optNum === "number"){ | |
string = string.substring(string.length-optNum); | |
spec.splice(int+1,1); | |
} | |
replacement += string; | |
break; | |
break; | |
default: | |
replacement += spec[int]; | |
}; | |
} | |
}else{ | |
throw "can only use this method on google chrome"; | |
} | |
break; | |
//END -----------------------Additional Option to output the calling file name and line number of the logging call. | |
case "a": // Array of messages | |
case "m": // Message | |
var depth = 0; | |
if (specifier) { | |
depth = parseInt(specifier, 10); | |
if (isNaN(depth)) { | |
handleError("PatternLayout.format: invalid specifier '" + | |
specifier + "' for conversion character '" + conversionCharacter + | |
"' - should be a number"); | |
depth = 0; | |
} | |
} | |
var messages = (conversionCharacter === "a") ? loggingEvent.messages[0] : loggingEvent.messages; | |
for (var i = 0, len = messages.length; i < len; i++) { | |
if (i > 0 && (replacement.charAt(replacement.length - 1) !== " ")) { | |
replacement += " "; | |
} | |
if (depth === 0) { | |
replacement += messages[i]; | |
} else { | |
replacement += formatObjectExpansion(messages[i], depth); | |
} | |
} | |
break; | |
case "c": // Logger name | |
var loggerName = loggingEvent.logger.name; | |
if (specifier) { | |
var precision = parseInt(specifier, 10); | |
var loggerNameBits = loggingEvent.logger.name.split("."); | |
if (precision >= loggerNameBits.length) { | |
replacement = loggerName; | |
} else { | |
replacement = loggerNameBits.slice(loggerNameBits.length - precision).join("."); | |
} | |
} else { | |
replacement = loggerName; | |
} | |
break; | |
case "d": // Date | |
var dateFormat = PatternLayout.ISO8601_DATEFORMAT; | |
if (specifier) { | |
dateFormat = specifier; | |
// Pick up special cases | |
if (dateFormat == "ISO8601") { | |
dateFormat = PatternLayout.ISO8601_DATEFORMAT; | |
} else if (dateFormat == "ABSOLUTE") { | |
dateFormat = PatternLayout.ABSOLUTETIME_DATEFORMAT; | |
} else if (dateFormat == "DATE") { | |
dateFormat = PatternLayout.DATETIME_DATEFORMAT; | |
} | |
} | |
// Format the date | |
replacement = (new SimpleDateFormat(dateFormat)).format(loggingEvent.timeStamp); | |
break; | |
case "f": // Custom field | |
if (this.hasCustomFields()) { | |
var fieldIndex = 0; | |
if (specifier) { | |
fieldIndex = parseInt(specifier, 10); | |
if (isNaN(fieldIndex)) { | |
handleError("PatternLayout.format: invalid specifier '" + | |
specifier + "' for conversion character 'f' - should be a number"); | |
} else if (fieldIndex === 0) { | |
handleError("PatternLayout.format: invalid specifier '" + | |
specifier + "' for conversion character 'f' - must be greater than zero"); | |
} else if (fieldIndex > this.customFields.length) { | |
handleError("PatternLayout.format: invalid specifier '" + | |
specifier + "' for conversion character 'f' - there aren't that many custom fields"); | |
} else { | |
fieldIndex = fieldIndex - 1; | |
} | |
} | |
replacement = this.customFields[fieldIndex].value; | |
} | |
break; | |
case "n": // New line | |
replacement = newLine; | |
break; | |
case "p": // Level | |
replacement = loggingEvent.level.name; | |
break; | |
case "r": // Milliseconds since log4javascript startup | |
replacement = "" + loggingEvent.timeStamp.getDifference(applicationStartDate); | |
break; | |
case "%": // Literal % sign | |
replacement = "%"; | |
break; | |
default: | |
replacement = matchedString; | |
break; | |
} | |
// Format the replacement according to any padding or | |
// truncation specified | |
var l; | |
// First, truncation | |
if (truncation) { | |
l = parseInt(truncation.substr(1), 10); | |
var strLen = replacement.length; | |
if (l < strLen) { | |
replacement = replacement.substring(strLen - l, strLen); | |
} | |
} | |
// Next, padding | |
if (padding) { | |
if (padding.charAt(0) == "-") { | |
l = parseInt(padding.substr(1), 10); | |
// Right pad with spaces | |
while (replacement.length < l) { | |
replacement += " "; | |
} | |
} else { | |
l = parseInt(padding, 10); | |
// Left pad with spaces | |
while (replacement.length < l) { | |
replacement = " " + replacement; | |
} | |
} | |
} | |
formattedString += replacement; | |
} | |
searchString = searchString.substr(result.index + result[0].length); | |
} | |
return formattedString; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var consoleAppender = new log4javascript.BrowserConsoleAppender(); | |
var patternLayout = new log4javascript.PatternLayout("%d{HH:mm:ss,SSS} %l{s:l} %-5p - %m{1}%n"); | |
consoleAppender.setLayout(patternLayout); | |
var rootLogger = log4javascript.getRootLogger(); | |
rootLogger.addAppender(consoleAppender); | |
rootLogger.setLevel(log4javascript.Level.ALL); | |
// The additional pattern %l{s:l} will output the last segment of the calling resource and the line of the call: | |
22:46:18,501 callingfile.js:212 DEBUG - Response SUCCESS: | |
// The pattern "%d{HH:mm:ss} %l{r40:l:c} %-5p - %m{1}%n" will output the last 40 characters of the calling resource, the line and the column each divided by a colon. | |
23:14:00 8085/sapdebug/localDebugTabConnection.js:212:15 DEBUG - Response S |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
First very nice and elegant solution :)
But there is a bug.
when using both popup and browserConsole appenders the row "var lineAccessingLogger = stack.split("\n")[8];" causes a bug because the stack length is increased...
can you fix it?