├── README.md ├── index.html └── log4b.js /README.md: -------------------------------------------------------------------------------- 1 | # log4b 2 | log for browser, can save and download console log 3 | 4 | idea form: https://github.com/inorganik/debugout.js 5 | 6 | # demo 7 | ``` 8 | var Log4b = new log4b(); 9 | 10 | Log4b.log('wangduanduan'); 11 | Log4b.log(JSON.stringify({name:'wangduan',age:18})); 12 | 13 | Log4b.getLog(); 14 | ``` 15 | # feature 16 | - log can saved Asynchronous 17 | - log can download 18 | - download file support ie10 and later 19 | 20 | # methods 21 | - getLog: get log show on the console tab 22 | - downloadLog: download the log 23 | - clear: clear all saved log 24 | - log: write log 25 | - lines: get how many lines of log 26 | - search: search a string 27 | 28 | # config 29 | - self.realTimeLoggingOn = true; // log in real time (forwards to console.log) 30 | - self.useTimestamps = false; // insert a timestamp in front of each log 31 | - self.recordLogs = true; // set to false after you're done debugging to avoid the log eating up memory 32 | - self.maxLines = 2500; // if autoTrim is true, this many most recent lines are saved 33 | - self.lineMaxChars = 1500; // if one log is max than lineMaxChars, it will be cut 34 | - self.logFilename = 'log4b.txt'; // filename of log downloaded with downloadLog() 35 | - self.lineBreak = '\n\n'; 36 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | log4b 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | readme 14 | 15 | 28 | 29 | -------------------------------------------------------------------------------- /log4b.js: -------------------------------------------------------------------------------- 1 | (function (log4b) { 2 | window.log4b = window.log4b || log4b 3 | })(function () { 4 | var self = this 5 | // config 6 | self.realTimeLoggingOn = true // log in real time (forwards to console.log) 7 | self.recordLogs = true // set to false after you're done debugging to avoid the log eating up memory 8 | self.maxLines = 2500 // if autoTrim is true, this many most recent lines are saved 9 | self.lineMaxChars = 1500 // if one log is max than lineMaxChars, it will be cut 10 | self.logFilename = 'log4b.txt' // filename of log downloaded with downloadLog() 11 | self.lineBreak = '\n\n' 12 | 13 | // log save 14 | self.output = '' 15 | 16 | this.getLog = function () { 17 | return self.recordLogs ? self.output : 'log recording is off' 18 | } 19 | 20 | this.downloadLog = function () { 21 | var downloadFileName = self.formatTimestamp() + '-' + self.logFilename 22 | 23 | if (window.navigator.msSaveBlob) { 24 | // for ie 10 and later 25 | try { 26 | var blobObject = new Blob([self.output]) 27 | window.navigator.msSaveBlob(blobObject, downloadFileName) 28 | } catch (e) { 29 | console.log(e) 30 | } 31 | } else { 32 | var file = 'data:text/plain;charset=utf-8,' 33 | var logFile = self.output 34 | var encoded = encodeURIComponent(logFile) 35 | file += encoded 36 | var a = document.createElement('a') 37 | a.href = file 38 | a.target = '_blank' 39 | a.download = downloadFileName 40 | document.body.appendChild(a) 41 | a.click() 42 | a.remove() 43 | } 44 | } 45 | 46 | this.search = function (string) { 47 | var lines = self.output.split(self.lineBreak) 48 | var rgx = new RegExp(string) 49 | var matched = [] 50 | 51 | for (var i = 0; i < lines.length; i++) { 52 | if (rgx.test(lines[i])) { 53 | matched.push('[' + i + ']: ' + lines[i]) 54 | } 55 | } 56 | var result = matched.join(self.lineBreak) 57 | return result || 'Nothing found for "' + string + '".' 58 | } 59 | 60 | this.clear = function () { 61 | var clearTime = new Date() 62 | self.output = '' 63 | if (self.realTimeLoggingOn) { 64 | console.log('[log4b.js] clear()') 65 | } 66 | } 67 | 68 | this.log = function (obj) { 69 | if (!self.recordLogs) { return } 70 | (function (obj) { 71 | setTimeout(function () { 72 | self._log(obj) 73 | }, 0) 74 | })(obj) 75 | } 76 | 77 | this._log = function (obj) { 78 | if (typeof obj === 'object') { 79 | obj = JSON.stringify(obj) 80 | } 81 | if (typeof obj !== 'string') { 82 | return 83 | } 84 | if (self.realTimeLoggingOn) { 85 | console.log(obj) 86 | } 87 | 88 | self.output += '[' + self.formatTimestamp() + ']: ' 89 | self.output += self.cutExceededChars(obj) + self.lineBreak 90 | self.output = self.trimLog(self.output, self.maxLines) 91 | } 92 | 93 | this.cutExceededChars = function (obj) { 94 | if (obj.length > self.lineMaxChars) { 95 | return obj.substr(0, self.lineMaxChars) 96 | } else { 97 | return obj 98 | } 99 | } 100 | 101 | this.trimLog = function (log, maxLines) { 102 | var lines = log.split(self.lineBreak) 103 | if (lines.length > maxLines) { 104 | lines = lines.slice(lines.length - maxLines) 105 | } 106 | return lines.join(self.lineBreak) 107 | } 108 | 109 | this.lines = function () { 110 | return self.output.split(self.lineBreak).length - 1 111 | } 112 | 113 | this.formatTimestamp = function () { 114 | var timestamp = new Date() 115 | var year = timestamp.getFullYear() 116 | var date = timestamp.getDate() 117 | var month = ('0' + (timestamp.getMonth() + 1)).slice(-2) 118 | var hrs = ('0' + timestamp.getHours()).slice(-2) 119 | var mins = ('0' + timestamp.getMinutes()).slice(-2) 120 | var secs = ('0' + timestamp.getSeconds()).slice(-2) 121 | var ms = timestamp.getMilliseconds() 122 | 123 | return year + '-' + month + '-' + date + ' ' + hrs + ':' + mins + ':' + secs + '.' + ms 124 | } 125 | }) 126 | --------------------------------------------------------------------------------