Skip to content

Commit f17f364

Browse files
authored
Merge pull request #5484 from chromoxdor/filter-weblog
[LOG] Adding a filter for the weblog
2 parents 97fa64f + 2c7ce5e commit f17f364

File tree

5 files changed

+343
-215
lines changed

5 files changed

+343
-215
lines changed

src/src/Static/WebStaticData.h

Lines changed: 77 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -341,12 +341,12 @@ static const char jsClipboardCopyPart2[] PROGMEM = {
341341
// "if(t==null){i= max_loop + 1;"
342342
"if(t==null){i=101;"
343343
"}else{"
344-
"cb+=t.innerHTML.replace(/<[Bb][Rr]\\s*\\/?>/gim,'\\n')+'"
344+
"const visibleLines=Array.from(t.children).filter((e=>null!==e.offsetParent)).map((e=>e.innerHTML));visibleLines.length>0&&(cb+=visibleLines.join('\\n').replace(/<[Bb][Rr]\\s*\\/?>/gim,'\\n')+'"
345345
};
346346

347347
//Fix HTML
348348
static const char jsClipboardCopyPart3[] PROGMEM = {
349-
"';}}"
349+
"');}}"
350350
"cb=cb.replace(/<\\/[Dd][Ii][Vv]\\s*\\/?>/gim,'\\n');"
351351
"cb=cb.replace(/<[^>]*>/gim,'');"
352352
"var ti=document.createElement('textarea');"
@@ -381,38 +381,90 @@ static const char jsSplitMultipleFields[] PROGMEM = {
381381
#ifdef WEBSERVER_INCLUDE_JS
382382
static const char DATA_UPDATE_SENSOR_VALUES_DEVICE_PAGE_JS[] PROGMEM = {
383383
"function elId(e){return document.getElementById(e)}"
384-
"function loopDeLoop(e,s){var o,a,n=0;isNaN(s)&&(s=1),null==e&&(e=1e3),"
385-
"i=setInterval(function(){if(n>0){clearInterval(i);return}"
386-
"++s>1||fetch('/json?view=sensorupdate').then(function(s){var n;if(200!==s.status){console.log('Looks like there was a problem. Status Code: '+s.status);return}"
387-
"s.json().then(function(s){e=s.TTL;"
384+
"loopDeLoop(1000);"
385+
"const SENSOR_URL='/json?view=sensorupdate';"
386+
"function loopDeLoop(e=1000){setTimeout(function(){fetch(SENSOR_URL)"
387+
".then(e=>{if(!e.ok)throw new Error(e.status);return e.json()})"
388+
".then(o=>{e=o.TTL||e;"
388389
#if (defined(FEATURE_TASKVALUE_UNIT_OF_MEASURE) && FEATURE_TASKVALUE_UNIT_OF_MEASURE) || (defined(FEATURE_STRING_VARIABLES) && FEATURE_STRING_VARIABLES)
389-
"var r=void 0===s.ShowUoM||s.ShowUoM&&'false'!==s.ShowUoM;"
390+
"const n=void 0===o.ShowUoM||o.ShowUoM&&'false'!==o.ShowUoM;"
390391
#endif // if (defined(FEATURE_TASKVALUE_UNIT_OF_MEASURE) && FEATURE_TASKVALUE_UNIT_OF_MEASURE) || (defined(FEATURE_STRING_VARIABLES) && FEATURE_STRING_VARIABLES)
391-
"for(o=0;o<s.Sensors.length;o++)if(s.Sensors[o].hasOwnProperty('TaskValues'))"
392-
"for(a=0;a<s.Sensors[o].TaskValues.length;a++)try{n=s.Sensors[o].TaskValues[a].Value}catch(l){n=l.name}"
393-
"finally{if('TypeError'!==n){var u=s.Sensors[o].TaskValues[a].Value,t=s.Sensors[o].TaskValues[a].NrDecimals;t<255&&(u=parseFloat(u).toFixed(t));"
392+
"for(let i=0;i<o.Sensors.length;i++){const t=o.Sensors[i];"
393+
"if(t.TaskValues)for(let j=0;j<t.TaskValues.length;j++){const r=t.TaskValues[j];"
394+
"if(!r||null==r.Value)continue;"
395+
"let s=r.Value;const d=r.NrDecimals;"
396+
"d<255&&(s=parseFloat(s).toFixed(d));"
394397
#if (defined(FEATURE_TASKVALUE_UNIT_OF_MEASURE) && FEATURE_TASKVALUE_UNIT_OF_MEASURE) || (defined(FEATURE_STRING_VARIABLES) && FEATURE_STRING_VARIABLES)
395-
"var $=s.Sensors[o].TaskValues[a].UoM,T=s.Sensors[o].TaskValues[a].Presentation;T?u=T:$&&r&&(u+=' '+$);"
398+
"r.Presentation?s=r.Presentation:"
399+
"r.UoM&&n&&(s+=' '+r.UoM);"
396400
#endif // if (defined(FEATURE_TASKVALUE_UNIT_OF_MEASURE) && FEATURE_TASKVALUE_UNIT_OF_MEASURE) || (defined(FEATURE_STRING_VARIABLES) && FEATURE_STRING_VARIABLES)
397-
"var S='value_'+(s.Sensors[o].TaskNumber-1)+'_'+(s.Sensors[o].TaskValues[a].ValueNumber-1),"
398-
"k='valuename_'+(s.Sensors[o].TaskNumber-1)+'_'+(s.Sensors[o].TaskValues[a].ValueNumber-1),"
399-
"V=elId(S),f=elId(k);V&&(V.innerHTML=u),"
400-
"f&&(f.innerHTML=s.Sensors[o].TaskValues[a].Name+':')}}"
401-
"clearInterval(i),loopDeLoop(e,0)})}).catch(function(s){console.log(s.message),e=5e3,clearInterval(i),loopDeLoop(e,0)}),n=1},e)}"
402-
"loopDeLoop(1e3,0);"
401+
"const l=t.TaskNumber-1+'_'+(r.ValueNumber-1),"
402+
"a=elId('value_'+l);"
403+
"a&&(a.innerHTML=s);"
404+
"const u=elId('valuename_'+l);"
405+
"u&&(u.innerHTML=r.Name+':')"
406+
"}}loopDeLoop(e)})"
407+
".catch(e=>{loopDeLoop(5000)})},e)}"
403408
};
404409
#endif // WEBSERVER_INCLUDE_JS
405410

406411
#ifdef WEBSERVER_INCLUDE_JS
407412
static const char DATA_FETCH_AND_PARSE_LOG_JS[] PROGMEM = {
408-
"function elId(e){return document.getElementById(e)}"
409-
"function getBrowser(){var e,o=navigator.userAgent,r=o.match(/(opera|chrome|safari|firefox|msie|trident(?=\\/))\\/?\\s*(\\d+)/i)||[];return/trident/i.test(r[1])?{name:'IE',version:(e=/\brv[ :]+(\\d+)/g.exec(o)||[])[1]||''}:'Chrome'===r[1]&&null!=(e=o.match(/\bOPR|Edge\\/(\\d+)/))?{name:'Opera',version:e[1]}:(r=r[2]?[r[1],r[2]]:[navigator.appName,navigator.appVersion,'-?'],null!=(e=o.match(/version\\/(\\d+)/i))&&r.splice(1,1,e[1]),{name:r[0],version:r[1]})}"
410-
"var browser=getBrowser(),currentBrowser=browser.name+browser.version;textToDisplay=(browser.name=browser.version<12)?'Error: '+currentBrowser+' is not supported! Please try a modern web browser.':'Fetching log entries...',elId('copyText_1').innerHTML=textToDisplay,loopDeLoop(1e3,0);var logLevel=['Unused','Error','Info','Debug','Debug More','Undefined','Undefined','Undefined','Undefined','Debug Dev'];"
411-
"function loopDeLoop(e,o){let r='copyText_1';isNaN(o)&&(o=1),null==e&&(e=1e3),scrolling_type=e<=500?'auto':'smooth';var n,t,i='',l=0,"
412-
"s=setInterval(function(){if(l>0){clearInterval(s);return}++o>1?l=1:fetch('/logjson').then(function(o){if(200!==o.status){console.log('Looks like there was a problem. Status Code: '+o.status);return}o.json()"
413-
".then(function(o){var l;for(null==t&&(t=''),n=0;n<o.Log.nrEntries;++n)try{l=o.Log.Entries[n].timestamp}catch(a){l=a.name}finally{'TypeError'!==l&&(i=o.Log.Entries[n].timestamp,t+='<div class=level_'+o.Log.Entries[n].level+' id='+i+'><font color=\"gray\">'+o.Log.Entries[n].timestamp+':</font> '+o.Log.Entries[n].text+'</div>')}e=o.Log.TTL,''!==t&&('Fetching log entries...'==elId(r).innerHTML&&(elId(r).innerHTML=''),elId(r).innerHTML+=t),t='',!0==(autoscroll_on=elId('autoscroll').checked)&&''!==i&&elId(i).scrollIntoView({behavior:scrolling_type}),elId('current_loglevel').innerHTML='Logging: '+logLevel[o.Log.SettingsWebLogLevel]+' ('+o.Log.SettingsWebLogLevel+')',clearInterval(s),"
414-
"loopDeLoop(e,0)})}).catch(function(o){elId(r).innerHTML+='<div>>> '+o.message+' <<</div>',autoscroll_on=elId('autoscroll').checked,elId(r).scrollTop=elId(r).scrollHeight,e=5e3,clearInterval(s),"
415-
"loopDeLoop(e,0)}),l=1},e)}"
413+
"function elId(e){return document.getElementById(e)}"
414+
"window.fetch?ct1.textContent='Fetching log entries...':"
415+
"ct1.textContent='Error: This browser is not supported. Please use a modern browser.';"
416+
"const logLevel={0:'Unused',1:'Error',2:'Info',3:'Debug',4:'Debug More',9:'Debug Dev'};"
417+
"function loopDeLoop(e=1000){setTimeout(function(){fetch('/logjson')"
418+
".then(e=>{if(!e.ok)throw Error(e.status);return e.json()})"
419+
".then(t=>{let o='';"
420+
"for(let l=0;l<t.Log.nrEntries;l++){let i=t.Log.Entries[l];"
421+
"i&&i.timestamp&&(o+=`<div class=level_${i.level}>"
422+
"<font color='gray'>${i.timestamp}:</font> ${i.text}</div>`)}"
423+
"e=t.Log.TTL||e;"
424+
"o&&(ct1.textContent==='Fetching log entries...'&&(ct1.innerHTML=''),ct1.innerHTML+=o);"
425+
"applyLogFilter();"
426+
"elId('autoscroll')?.checked&&ct1.scrollTo({top:ct1.scrollHeight,behavior:e<=500?'auto':'smooth'});"
427+
"let n=t.Log.SettingsWebLogLevel,r=logLevel[n]??'Undefined';"
428+
"elId('current_loglevel').textContent=`Logging: ${r} (${n})`;"
429+
"loopDeLoop(e)})"
430+
".catch(e=>{ct1.innerHTML+=`<div>>> ${e.message} <<</div>`;"
431+
"ct1.scrollTop=ct1.scrollHeight;loopDeLoop(5000)})},e)}"
432+
"function applyLogFilter(){"
433+
"let e=elId('logfilter').value.split(';').map(e=>e.trim()).filter(Boolean),"
434+
"t=document.querySelectorAll('#copyText_1 > div'),"
435+
"o=e.some(e=>!e.startsWith('!'));"
436+
"for(let l of t){"
437+
"l.dataset.originalHtml||(l.dataset.originalHtml=l.innerHTML);"
438+
"let i=l.dataset.originalHtml,n=l.textContent.toLowerCase(),r=[],s=!1,a=!o;"
439+
"for(let c of e){"
440+
"if(c.startsWith('!')){let g=c.slice(1);"
441+
"if(!g.includes('&')||g.startsWith('&')||g.endsWith('&')){"
442+
"if(g&&n.includes(g.toLowerCase())){s=!0;break}}"
443+
"else{let f=g.split('&').map(e=>e.trim()).filter(Boolean),u=-1,d=!0;"
444+
"for(let p of f){let h=n.indexOf(p.toLowerCase(),u+1);if(h===-1){d=!1;break}u=h}"
445+
"if(d){s=!0;break}}continue}"
446+
"if(c.includes('&')&&!c.startsWith('&')&&!c.endsWith('&')){"
447+
"let L=c.split('&').map(e=>e.trim()).filter(Boolean);"
448+
"if(L.length>=2){let _=-1,$=!0;"
449+
"for(let b of L){let m=n.indexOf(b.toLowerCase(),_+1);if(m===-1){$=!1;break}_=m}"
450+
"if($){r.push(...L),a=!0;break}}continue}"
451+
"if(n.includes(c.toLowerCase())){r.push(c),a=!0;break}}"
452+
"if(s||!a){l.style.display='none';continue}"
453+
"l.style.display='';l.innerHTML=highlightOutsideTags(i,r)}}"
454+
"function highlightOutsideTags(e,t){if(!t.length)return e;"
455+
"let o='',l=!1,i=0;"
456+
"for(;i<e.length;){let n=e[i];"
457+
"if('<'===n&&(l=!0),'>'===n){l=!1;o+=n;i++;continue}"
458+
"if(!l){let r=!1;"
459+
"for(let s of t){let a=e.slice(i,i+s.length);"
460+
"if(a.toLowerCase()===s.toLowerCase()){"
461+
"o+=`<span style='background-color: #bb9300;color: black;'>${a}</span>`;"
462+
"i+=s.length;r=!0;break}}"
463+
"if(r)continue}"
464+
"o+=n;i++}return o}"
465+
"loopDeLoop(1000);"
466+
"const input=document.getElementById('logfilter');"
467+
"input&&(input.placeholder='\"!\"=exclude \";\"=or \"&\"=and (e.g. !act)');"
416468
};
417469
#endif // WEBSERVER_INCLUDE_JS
418470

src/src/WebServer/Log.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "../WebServer/JSON.h"
77
#include "../WebServer/Markup.h"
88
#include "../WebServer/Markup_Buttons.h"
9+
#include "../WebServer/Markup_Forms.h"
910

1011
#include "../DataStructs/LogBuffer.h"
1112
#include "../DataStructs/TimingStats.h"
@@ -35,6 +36,7 @@ void handle_log() {
3536
"</TR></table><div id='current_loglevel' style='font-weight: bold;'>Logging: </div><div class='logviewer' id='copyText_1'></div>"));
3637
addHtml(F("Autoscroll: "));
3738
addCheckBox(F("autoscroll"), true);
39+
addFormTextBox(F("Filter"), F("logfilter"), "", 30);
3840
addHtml(F("<BR></body>"));
3941

4042
serve_JS(JSfiles_e::FetchAndParseLog);

0 commit comments

Comments
 (0)