Skip to content

Instantly share code, notes, and snippets.

@ssddi456
Created May 17, 2018 12:17
Show Gist options
  • Save ssddi456/5e0e5e118b1a059d98af4867b91db7d0 to your computer and use it in GitHub Desktop.
Save ssddi456/5e0e5e118b1a059d98af4867b91db7d0 to your computer and use it in GitHub Desktop.
logViewer
<!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>
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;
}
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