Created
May 17, 2018 12:17
-
-
Save ssddi456/5e0e5e118b1a059d98af4867b91db7d0 to your computer and use it in GitHub Desktop.
logViewer
This file contains hidden or 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
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Document</title> | |
<link href="https://cdn.bootcss.com/bootstrap/4.1.0/css/bootstrap.css" rel="stylesheet"> | |
</head> | |
<body> | |
<style> | |
.log { | |
border: 1px solid #ced4da; | |
} | |
.log:not(:last-child) { | |
border-bottom: 0; | |
} | |
.log-content { | |
border-left: 1px solid #ced4da; | |
display: block; | |
} | |
.highlight { | |
background-color: yellow; | |
} | |
.row { | |
display: block; | |
} | |
.col-sm-1 { | |
width: 8.333333%; | |
flex: none; | |
float: left; | |
} | |
.col-sm-11 { | |
width: 91.666667%; | |
flex: none; | |
float: left; | |
} | |
.col-sm-12 { | |
width: 100%; | |
flex: none; | |
float: left; | |
} | |
.my-navbar { | |
top: 10px; | |
background-color: rgba(255, 255, 255, 0.2); | |
} | |
.my-navbar hr{ | |
margin-bottom: 5px; | |
} | |
.my-navbar .input-group{ | |
margin-bottom: 5px; | |
} | |
</style> | |
<div class="container" id="main"> | |
<div class="container my-navbar sticky-top"> | |
<div class="tool-bar row"> | |
<div class="btn-group"> | |
<div class="btn btn-light" | |
@click="switchViewMode('all')" | |
:class="[viewMode == 'all' && 'active' ]">all</div> | |
<div class="btn btn-light" | |
@click="switchViewMode('filtered')" | |
:class="[viewMode == 'filtered' && 'active' ]">filtered</div> | |
</div> | |
<div class="btn-group"> | |
<div class="btn btn-primary" | |
@click="loadLog">reload</div> | |
</div> | |
</div> | |
<hr/> | |
<div class="tool-bar row"> | |
<div class="input-group" v-for="keyword in keywords"> | |
<input type="text" class="form-control" v-model="keyword.value"> | |
<div class="input-group-append"> | |
<div class="btn btn-light" @click="removeKeyword(keyword)">x</div> | |
</div> | |
</div> | |
<div class="btn btn-primary" @click="addKeyword">add keyword</div> | |
</div> | |
</div> | |
<hr/> | |
<div class="logs row clearfix"> | |
<div class="log col-sm-12" v-for="log in logs"> | |
<div class="col-sm-1">{{log.startIndex}}<br/>{{log.time}}</div> | |
<div class="col-sm-11 log-content"> | |
<pre v-html="log.content"></pre> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script> | |
<script src="./logViewer.js"></script> | |
</body> | |
</html> |
This file contains hidden or 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 ViewMode; | |
(function (ViewMode) { | |
ViewMode["all"] = "all"; | |
ViewMode["filtered"] = "filtered"; | |
})(ViewMode || (ViewMode = {})); | |
var logText = ''; | |
var originLogs = []; | |
var mainVm = new Vue({ | |
el: '#main', | |
data: { | |
viewMode: 'all', | |
keywords: [], | |
logs: [], | |
updating: false | |
}, | |
methods: { | |
switchViewMode: function (mode) { | |
this.viewMode = mode; | |
this.updateLog(); | |
}, | |
addKeyword: function () { | |
this.keywords.push({ color: 'red', value: '' }); | |
}, | |
removeKeyword: function (keyword) { | |
this.keywords.splice(this.keywords.indexOf(keyword), 1); | |
}, | |
loadLog: loadLog, | |
updateLog: function () { | |
console.time('updateLogData'); | |
var newLogs = highLightLog(filterLog(originLogs)); | |
console.timeEnd('updateLogData'); | |
console.time('updateLogVm'); | |
this.logs = newLogs; | |
console.timeEnd('updateLogVm'); | |
} | |
}, | |
computed: { | |
keywordVersion: function () { | |
var theKey = this.keywords.filter(function (x) { return !!x.value.length; }).map(function (x) { return x.value; }).join('-|-'); | |
return theKey; | |
} | |
}, | |
watch: { | |
keywordVersion: throttle(function () { | |
this.updateLog(); | |
}) | |
} | |
}); | |
function throttle(handle) { | |
var timer; | |
return function () { | |
var self = this; | |
clearTimeout(timer); | |
timer = setTimeout(function () { | |
handle.call(self); | |
}, 1000); | |
}; | |
} | |
loadLog(); | |
function loadLog() { | |
// clear up | |
mainVm.logs.splice(0, mainVm.logs.length); | |
// reload | |
fetch('./test.log').then(function (res) { | |
res.text().then(function (text) { | |
originLogs = parseLog(text); | |
mainVm.updateLog(); | |
}); | |
}); | |
} | |
var highlightStartTag = '<code class="highlight">'; | |
function filterLog(logs) { | |
var keywords = mainVm.keywords; | |
if (!keywords || !keywords.length) { | |
return logs; | |
} | |
if (mainVm.viewMode == ViewMode.filtered) { | |
var ret = []; | |
for (var i = logs.length - 1; i >= 0; i--) { | |
var contents = logs[i].contents; | |
SearchLoop: for (var j = 0; j < keywords.length; ++j) { | |
var keyword = keywords[j]; | |
var keywordLength = keyword.value.length; | |
if (keywordLength > 0) { | |
for (var k = 0; k < contents.length; ++k) { | |
var content = contents[k]; | |
if (content.length > keywordLength | |
&& content.indexOf(keyword.value) !== -1) { | |
ret.unshift(logs[i]); | |
break SearchLoop; | |
} | |
} | |
} | |
} | |
} | |
return ret; | |
} | |
else { | |
return logs; | |
} | |
} | |
function buildSegHtml(segs) { | |
var ret = []; | |
for (var j = 0; j < segs.length; ++j) { | |
var seg = segs[j]; | |
if (seg.type == 'normal') { | |
ret.push('<code>' + seg.text + '</code>'); | |
} | |
else { | |
ret.push(highlightStartTag + seg.text + '</code>'); | |
} | |
} | |
return ret.join(''); | |
} | |
function createSegs(line, keywords) { | |
var segs = [{ text: line, type: 'normal' }]; | |
for (var i = 0; i < keywords.length; ++i) { | |
var keyword = keywords[i]; | |
var keywordLength = keyword.value.length; | |
if (keywordLength > 0) { | |
for (var j = 0; j < segs.length; ++j) { | |
var seg = segs[j]; | |
if (seg.type == 'normal') { | |
var keywordIndex = seg.text.indexOf(keyword.value); | |
if (keywordIndex != -1) { | |
if (keywordIndex != 0) { | |
segs.splice(j, 0, { text: seg.text.slice(0, keywordIndex), type: 'normal' }); | |
j++; | |
} | |
segs.splice(j, 1, { text: keyword.value, type: 'highlight' }); | |
if ((keywordIndex + keywordLength) < seg.text.length) { | |
segs.splice(j + 1, 0, { | |
text: seg.text.slice(keywordIndex + keywordLength), | |
type: 'normal' | |
}); | |
j++; | |
} | |
} | |
} | |
} | |
} | |
} | |
return segs; | |
} | |
function highLightLog(logs) { | |
var keywords = mainVm.keywords; | |
for (var i = logs.length - 1; i >= 0; i--) { | |
var contents = logs[i].contents; | |
var content = []; | |
for (var i_1 = 0; i_1 < contents.length; ++i_1) { | |
var line = contents[i_1]; | |
if (keywords && keywords.length) { | |
content.push(buildSegHtml(createSegs(line, keywords)) + '\n'); | |
} | |
else { | |
content.push('<code>'); | |
content.push(line); | |
content.push('</code>\n'); | |
} | |
} | |
logs[i].content = content.join(''); | |
} | |
return logs; | |
} | |
var reg_start = /^\[-- (\d+:\d+:\d+)\]$/; | |
var reg_end = /^\[(\d+:\d+:\d+) \-\-\]$/; | |
function parseLog(text) { | |
var pos = 0; | |
var logLength = text.length; | |
var logs = []; | |
var lineIndex = 0; | |
var currentLog; | |
while (pos < logLength) { | |
lineIndex++; | |
var lineBreakIdx = text.indexOf('\n', pos); | |
var lineText = text.slice(pos, lineBreakIdx); | |
if (lineText.length > 10 && lineText.length < 15) { | |
var startMatch = lineText.match(reg_start); | |
if (startMatch) { | |
currentLog = { | |
startIndex: lineIndex, | |
time: startMatch[1], | |
contents: [] | |
}; | |
} | |
else if (lineText.match(reg_end)) { | |
currentLog.endIndx = lineIndex; | |
currentLog.id = logs.push(currentLog); | |
} | |
else { | |
currentLog.contents.push(lineText); | |
} | |
} | |
else { | |
currentLog.contents.push(lineText); | |
} | |
pos = lineBreakIdx + 1; | |
} | |
logs.push(currentLog); | |
return logs; | |
} |
This file contains hidden or 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
declare const Vue; | |
enum ViewMode{ | |
all = 'all', | |
filtered = 'filtered', | |
} | |
const logText = ''; | |
let originLogs = []; | |
const mainVm = new Vue({ | |
el : '#main', | |
data: { | |
viewMode: 'all', | |
keywords: [], | |
logs: [], | |
updating: false, | |
}, | |
methods: { | |
switchViewMode(mode: ViewMode){ | |
this.viewMode = mode; | |
this.updateLog(); | |
}, | |
addKeyword() { | |
this.keywords.push({ color: 'red', value : '' }); | |
}, | |
removeKeyword(keyword) { | |
this.keywords.splice(this.keywords.indexOf(keyword), 1); | |
}, | |
loadLog, | |
updateLog() { | |
console.time('updateLogData'); | |
const newLogs = highLightLog(filterLog(originLogs)); | |
console.timeEnd('updateLogData'); | |
console.time('updateLogVm'); | |
this.logs = newLogs | |
console.timeEnd('updateLogVm'); | |
} | |
}, | |
computed: { | |
keywordVersion() { | |
const theKey = this.keywords.filter(x => !!x.value.length).map( x => x.value ).join('-|-'); | |
return theKey; | |
} | |
}, | |
watch: { | |
keywordVersion: throttle(function() { | |
this.updateLog(); | |
}) | |
} | |
}); | |
function throttle( handle ) { | |
var timer; | |
return function() { | |
var self = this; | |
clearTimeout(timer); | |
timer = setTimeout(function() { | |
handle.call(self); | |
}, 1000); | |
}; | |
} | |
loadLog(); | |
function loadLog() { | |
// clear up | |
mainVm.logs.splice(0, mainVm.logs.length); | |
// reload | |
fetch('./test.log').then( res => { | |
res.text().then(text => { | |
originLogs = parseLog(text); | |
mainVm.updateLog(); | |
}); | |
}); | |
} | |
const highlightStartTag = '<code class="highlight">'; | |
function filterLog ( logs ) { | |
const keywords = mainVm.keywords; | |
if(!keywords || !keywords.length){ | |
return logs; | |
} | |
if(mainVm.viewMode == ViewMode.filtered) { | |
const ret = []; | |
for (let i = logs.length - 1; i >= 0; i--) { | |
const contents = logs[i].contents; | |
SearchLoop: | |
for (let j = 0; j < keywords.length; ++j) { | |
const keyword = keywords[j]; | |
const keywordLength = keyword.value.length; | |
if (keywordLength > 0) { | |
for (var k = 0; k < contents.length; ++k) { | |
const content = contents[k]; | |
if (content.length > keywordLength | |
&& content.indexOf(keyword.value) !== -1 | |
) { | |
ret.unshift(logs[i]); | |
break SearchLoop; | |
} | |
} | |
} | |
} | |
} | |
return ret; | |
} else { | |
return logs; | |
} | |
} | |
function buildSegHtml (segs) { | |
const ret = []; | |
for (let j = 0; j < segs.length; ++j) { | |
const seg = segs[j]; | |
if( seg.type == 'normal' ){ | |
ret.push('<code>' + seg.text + '</code>'); | |
} else { | |
ret.push(highlightStartTag + seg.text + '</code>'); | |
} | |
} | |
return ret.join(''); | |
} | |
function createSegs( line, keywords ) { | |
const segs = [{ text: line, type: 'normal'}]; | |
for (let i = 0; i < keywords.length; ++i) { | |
const keyword = keywords[i]; | |
const keywordLength = keyword.value.length; | |
if (keywordLength > 0) { | |
for (var j = 0; j < segs.length; ++j) { | |
const seg = segs[j]; | |
if (seg.type == 'normal') { | |
const keywordIndex = seg.text.indexOf(keyword.value); | |
if (keywordIndex != -1) { | |
if(keywordIndex != 0) { | |
segs.splice(j, 0, { text: seg.text.slice(0, keywordIndex), type: 'normal' }); | |
j ++; | |
} | |
segs.splice(j, 1, { text: keyword.value, type: 'highlight' }); | |
if((keywordIndex + keywordLength) < seg.text.length) { | |
segs.splice(j + 1, 0, { | |
text: seg.text.slice(keywordIndex + keywordLength), | |
type: 'normal' | |
}); | |
j ++; | |
} | |
} | |
} | |
} | |
} | |
} | |
return segs; | |
} | |
function highLightLog( logs ) { | |
const keywords = mainVm.keywords; | |
for (let i = logs.length - 1; i >= 0; i--) { | |
const contents = logs[i].contents; | |
const content = []; | |
for (let i = 0; i < contents.length; ++i) { | |
const line = contents[i]; | |
if(keywords && keywords.length) { | |
content.push( buildSegHtml(createSegs(line, keywords)) + '\n'); | |
} else { | |
content.push('<code>'); | |
content.push(line); | |
content.push('</code>\n'); | |
} | |
} | |
logs[i].content = content.join(''); | |
} | |
return logs; | |
} | |
const reg_start = /^\[-- (\d+:\d+:\d+)\]$/; | |
const reg_end = /^\[(\d+:\d+:\d+) \-\-\]$/; | |
function parseLog(text) { | |
let pos = 0; | |
const logLength = text.length; | |
const logs = []; | |
let lineIndex = 0; | |
let currentLog; | |
while(pos < logLength) { | |
lineIndex ++; | |
const lineBreakIdx = text.indexOf('\n', pos); | |
const lineText = text.slice(pos, lineBreakIdx); | |
if(lineText.length > 10 && lineText.length < 15){ | |
var startMatch = lineText.match(reg_start); | |
if(startMatch) { | |
currentLog = { | |
startIndex: lineIndex, | |
time: startMatch[1], | |
contents: [], | |
} | |
} else if(lineText.match(reg_end)){ | |
currentLog.endIndx = lineIndex; | |
currentLog.id = logs.push(currentLog); | |
} else { | |
currentLog.contents.push(lineText); | |
} | |
} else { | |
currentLog.contents.push(lineText); | |
} | |
pos = lineBreakIdx + 1; | |
} | |
logs.push(currentLog); | |
return logs; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment