feat(logs): replace custom logs list with dees-chart-log component and push logs to chart, add log mapping and lifecycle sync, and bump smartlog dependency
This commit is contained in:
@@ -55,87 +55,20 @@ export class OpsViewLogs extends DeesElement {
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.logContainer {
|
||||
background: ${cssManager.bdTheme('#f8f9fa', '#1e1e1e')};
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
max-height: 600px;
|
||||
overflow-y: auto;
|
||||
font-family: 'Consolas', 'Monaco', monospace;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.logEntry {
|
||||
margin-bottom: 8px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.logTimestamp {
|
||||
color: ${cssManager.bdTheme('#7a7a7a', '#7a7a7a')};
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.logLevel {
|
||||
font-weight: bold;
|
||||
margin-right: 8px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.logLevel.debug {
|
||||
color: ${cssManager.bdTheme('#6a9955', '#6a9955')};
|
||||
background: ${cssManager.bdTheme('rgba(106, 153, 85, 0.1)', 'rgba(106, 153, 85, 0.1)')};
|
||||
}
|
||||
.logLevel.info {
|
||||
color: ${cssManager.bdTheme('#569cd6', '#569cd6')};
|
||||
background: ${cssManager.bdTheme('rgba(86, 156, 214, 0.1)', 'rgba(86, 156, 214, 0.1)')};
|
||||
}
|
||||
.logLevel.warn {
|
||||
color: ${cssManager.bdTheme('#ce9178', '#ce9178')};
|
||||
background: ${cssManager.bdTheme('rgba(206, 145, 120, 0.1)', 'rgba(206, 145, 120, 0.1)')};
|
||||
}
|
||||
.logLevel.error {
|
||||
color: ${cssManager.bdTheme('#f44747', '#f44747')};
|
||||
background: ${cssManager.bdTheme('rgba(244, 71, 71, 0.1)', 'rgba(244, 71, 71, 0.1)')};
|
||||
}
|
||||
|
||||
.logCategory {
|
||||
color: ${cssManager.bdTheme('#c586c0', '#c586c0')};
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.logMessage {
|
||||
color: ${cssManager.bdTheme('#333', '#d4d4d4')};
|
||||
}
|
||||
|
||||
.noLogs {
|
||||
color: ${cssManager.bdTheme('#7a7a7a', '#7a7a7a')};
|
||||
text-align: center;
|
||||
padding: 40px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<ops-sectionheading>Logs</ops-sectionheading>
|
||||
|
||||
|
||||
<div class="controls">
|
||||
<div class="filterGroup">
|
||||
<dees-button
|
||||
<dees-button
|
||||
@click=${() => this.fetchLogs()}
|
||||
>
|
||||
Refresh Logs
|
||||
</dees-button>
|
||||
|
||||
<dees-button
|
||||
@click=${() => this.toggleStreaming()}
|
||||
.type=${this.logState.isStreaming ? 'highlighted' : 'normal'}
|
||||
>
|
||||
${this.logState.isStreaming ? 'Stop Streaming' : 'Start Streaming'}
|
||||
</dees-button>
|
||||
</div>
|
||||
|
||||
<div class="filterGroup">
|
||||
@@ -143,7 +76,7 @@ export class OpsViewLogs extends DeesElement {
|
||||
<dees-input-dropdown
|
||||
.options=${['all', 'debug', 'info', 'warn', 'error']}
|
||||
.selectedOption=${'all'}
|
||||
@selectedOption=${(e) => this.updateFilter('level', e.detail)}
|
||||
@selectedOption=${(e: any) => this.updateFilter('level', e.detail)}
|
||||
></dees-input-dropdown>
|
||||
</div>
|
||||
|
||||
@@ -152,7 +85,7 @@ export class OpsViewLogs extends DeesElement {
|
||||
<dees-input-dropdown
|
||||
.options=${['all', 'smtp', 'dns', 'security', 'system', 'email']}
|
||||
.selectedOption=${'all'}
|
||||
@selectedOption=${(e) => this.updateFilter('category', e.detail)}
|
||||
@selectedOption=${(e: any) => this.updateFilter('category', e.detail)}
|
||||
></dees-input-dropdown>
|
||||
</div>
|
||||
|
||||
@@ -161,34 +94,55 @@ export class OpsViewLogs extends DeesElement {
|
||||
<dees-input-dropdown
|
||||
.options=${['50', '100', '200', '500']}
|
||||
.selectedOption=${'100'}
|
||||
@selectedOption=${(e) => this.updateFilter('limit', e.detail)}
|
||||
@selectedOption=${(e: any) => this.updateFilter('limit', e.detail)}
|
||||
></dees-input-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="logContainer">
|
||||
${this.logState.recentLogs.length > 0 ?
|
||||
this.logState.recentLogs.map(log => html`
|
||||
<div class="logEntry">
|
||||
<span class="logTimestamp">${new Date(log.timestamp).toLocaleTimeString()}</span>
|
||||
<span class="logLevel ${log.level}">${log.level.toUpperCase()}</span>
|
||||
<span class="logCategory">[${log.category}]</span>
|
||||
<span class="logMessage">${log.message}</span>
|
||||
</div>
|
||||
`) : html`
|
||||
<div class="noLogs">No logs to display</div>
|
||||
`
|
||||
}
|
||||
</div>
|
||||
<dees-chart-log
|
||||
.label=${'Application Logs'}
|
||||
.autoScroll=${true}
|
||||
.maxEntries=${2000}
|
||||
.showMetrics=${true}
|
||||
></dees-chart-log>
|
||||
`;
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
super.connectedCallback();
|
||||
// Auto-fetch logs when the view mounts
|
||||
this.fetchLogs();
|
||||
}
|
||||
|
||||
async updated(changedProperties: Map<string, any>) {
|
||||
super.updated(changedProperties);
|
||||
if (changedProperties.has('logState')) {
|
||||
this.pushLogsToChart();
|
||||
}
|
||||
}
|
||||
|
||||
private async pushLogsToChart() {
|
||||
const chartLog = this.shadowRoot?.querySelector('dees-chart-log') as any;
|
||||
if (!chartLog) return;
|
||||
|
||||
// Ensure the chart element has finished its own initialization
|
||||
await chartLog.updateComplete;
|
||||
|
||||
chartLog.clearLogs();
|
||||
const entries = this.getMappedLogEntries();
|
||||
if (entries.length > 0) {
|
||||
chartLog.updateLog(entries);
|
||||
}
|
||||
}
|
||||
|
||||
private getMappedLogEntries() {
|
||||
return this.logState.recentLogs.map((log) => ({
|
||||
timestamp: new Date(log.timestamp).toISOString(),
|
||||
level: log.level as 'debug' | 'info' | 'warn' | 'error',
|
||||
message: log.message,
|
||||
source: log.category,
|
||||
}));
|
||||
}
|
||||
|
||||
private async fetchLogs() {
|
||||
await appstate.logStatePart.dispatchAction(appstate.fetchRecentLogsAction, {
|
||||
limit: this.filterLimit,
|
||||
@@ -214,17 +168,4 @@ export class OpsViewLogs extends DeesElement {
|
||||
|
||||
this.fetchLogs();
|
||||
}
|
||||
|
||||
private getActiveFilters() {
|
||||
return {
|
||||
level: this.filterLevel,
|
||||
category: this.filterCategory,
|
||||
limit: this.filterLimit,
|
||||
};
|
||||
}
|
||||
|
||||
private toggleStreaming() {
|
||||
// TODO: Implement log streaming with VirtualStream
|
||||
console.log('Streaming toggle not yet implemented');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user