diff --git a/vscode-appdaemon/media/logExplorer.css b/vscode-appdaemon/media/logExplorer.css index 8f58d02..7ed7e7d 100644 --- a/vscode-appdaemon/media/logExplorer.css +++ b/vscode-appdaemon/media/logExplorer.css @@ -7,7 +7,7 @@ .block-title{font-weight:600;margin-bottom:6px;color:var(--fg);overflow-wrap:anywhere} -#error-count{font-weight:700;font-size:14px}#error-count.has-errors{color:var(--vscode-editorError-foreground,#ffacac);border-color:currentColor;background:var(--vscode-inputValidation-errorBackground,#5b3039)} +#error-count,#warning-count{font-weight:700;font-size:14px}#error-count.has-errors{color:var(--vscode-editorError-foreground,#ffacac);border-color:currentColor;background:var(--vscode-inputValidation-errorBackground,#5b3039)}#warning-count.has-warnings{color:var(--vscode-editorWarning-foreground,#f3cd80);border-color:currentColor;background:var(--vscode-inputValidation-warningBackground,#594925)} .last-log{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} summary{display:grid;grid-template-columns:auto minmax(0,1fr) repeat(3,max-content);align-items:center;column-gap:10px;row-gap:5px} diff --git a/vscode-appdaemon/media/logExplorer.html b/vscode-appdaemon/media/logExplorer.html index 36d78e8..00a5fe3 100644 --- a/vscode-appdaemon/media/logExplorer.html +++ b/vscode-appdaemon/media/logExplorer.html @@ -3,7 +3,7 @@ AppDaemon · Logs -

AppDaemon Logs

Reading logs…

+

AppDaemon Logs

Reading logs…

Applications

Log details

Select a log to view its details.

The base AppDaemon log format does not include causal links.

diff --git a/vscode-appdaemon/media/logExplorer.js b/vscode-appdaemon/media/logExplorer.js index 9121205..ff22749 100644 --- a/vscode-appdaemon/media/logExplorer.js +++ b/vscode-appdaemon/media/logExplorer.js @@ -13,7 +13,8 @@ const appFlashTokens = new Map(); let receivedInitialData = false; let pointerSelecting = false; - let errorView; + let countView; + let activeCountLevel; const $ = id => document.getElementById(id); const node = (tag, text, cls) => { const e = document.createElement(tag); if (text !== undefined) e.textContent = text; if (cls) e.className = cls; return e; }; const normalLevel = e => e.level === 'CRITICAL' ? 'ERROR' : e.level; @@ -149,6 +150,7 @@ }); const timeOf = (app, logs) => (lastLogs.get(app) || logs[logs.length - 1]).time; $('error-count').setAttribute('aria-pressed', String($('level').value === 'ERROR')); + $('warning-count').setAttribute('aria-pressed', String($('level').value === 'WARNING')); [...groups].sort(([a, al], [b, bl]) => { const order = $('sort').value; if (order === 'name') return a.localeCompare(b); @@ -363,6 +365,10 @@ $('error-count').textContent = `${errorCount} error${errorCount === 1 ? '' : 's'}`; $('error-count').classList.toggle('has-errors', errorCount > 0); $('error-count').title = 'Errors and critical logs across all apps in loaded history. Click to show them.'; + const warningCount = entries.filter(e => (e.kind === 'log' || e.kind.startsWith('initialization_')) && normalLevel(e) === 'WARNING').length; + $('warning-count').textContent = `${warningCount} warning${warningCount === 1 ? '' : 's'}`; + $('warning-count').classList.toggle('has-warnings', warningCount > 0); + $('warning-count').title = 'Warnings across all apps in loaded history. Click to show them.'; $('warnings').textContent = (message.warnings || []).join(' · '); renderApps(); renderDetail(); } function refreshLastLogAges() { @@ -387,21 +393,22 @@ document.addEventListener('pointerup', () => { pointerSelecting = false; }); document.addEventListener('selectionchange', () => { if (!selectionActive() && latest && latest !== appliedMessage) setTimeout(() => { if (!selectionActive() && latest !== appliedMessage) apply(latest); }, 0); }); ['search', 'period', 'level', 'sort'].forEach(id => $(id).addEventListener('input', () => { - errorView = undefined; selected = undefined; origin = undefined; + countView = undefined; activeCountLevel = undefined; selected = undefined; origin = undefined; save(); renderApps(); renderDetail(); })); - $('error-count').onclick = () => { - const leaving = $('level').value === 'ERROR'; + function toggleCountView(level) { + const leaving = activeCountLevel === level; if (leaving) { - $('search').value = errorView?.search || ''; - $('period').value = errorView?.period || '0'; - $('level').value = errorView?.level || 'all'; - if (errorView) { expanded.clear(); errorView.expanded.forEach(app => expanded.add(app)); } - errorView = undefined; + $('search').value = countView?.search || ''; + $('period').value = countView?.period || '0'; + $('level').value = countView?.level || 'all'; + if (countView) { expanded.clear(); countView.expanded.forEach(app => expanded.add(app)); } + countView = undefined; activeCountLevel = undefined; } else { - errorView = { search: $('search').value, period: $('period').value, level: $('level').value, expanded: [...expanded] }; - $('search').value = ''; $('period').value = '0'; $('level').value = 'ERROR'; - entries.filter(e => normalLevel(e) === 'ERROR').forEach(e => expanded.add(e.app)); + if (!activeCountLevel) countView = { search: $('search').value, period: $('period').value, level: $('level').value, expanded: [...expanded] }; + activeCountLevel = level; + $('search').value = ''; $('period').value = '0'; $('level').value = level; + entries.filter(e => normalLevel(e) === level).forEach(e => expanded.add(e.app)); } selected = undefined; origin = undefined; save(); renderApps(); renderDetail(); @@ -409,7 +416,9 @@ const first = document.querySelector('#apps .row'); if (first) { first.click(); first.closest('.rows').scrollTop = 0; first.focus({ preventScroll: true }); } } - }; + } + $('error-count').onclick = () => toggleCountView('ERROR'); + $('warning-count').onclick = () => toggleCountView('WARNING'); $('clear').onclick = () => { selected = undefined; origin = undefined; save(); $('clear').disabled = true; $('clear').textContent = 'Clearing…'; vscode.postMessage({ type: 'clear' }); }; $('graph-mode').onclick = () => { mode = 'graph'; save(); renderDetail(); }; $('tree-mode').onclick = () => { mode = 'tree'; save(); renderDetail(); }; diff --git a/vscode-appdaemon/vscode-appdaemon-0.2.0.vsix b/vscode-appdaemon/vscode-appdaemon-0.2.0.vsix index 4332377..6575559 100644 Binary files a/vscode-appdaemon/vscode-appdaemon-0.2.0.vsix and b/vscode-appdaemon/vscode-appdaemon-0.2.0.vsix differ