From e20c6d82e32a0a4e2013c528e1e81c93bdd0b0af Mon Sep 17 00:00:00 2001 From: Afreen Misbah Date: Mon, 18 May 2026 02:48:11 +0530 Subject: [PATCH] mgr/dashboard: carbonize logs component Fixes https://tracker.ceph.com/issues/68260 Assisted-by: Claude Signed-off-by: Afreen Misbah --- .../app/ceph/cluster/logs/logs.component.html | 100 ++++++++------ .../app/ceph/cluster/logs/logs.component.scss | 129 +++++++++++++----- .../app/ceph/cluster/logs/logs.component.ts | 7 +- 3 files changed, 157 insertions(+), 79 deletions(-) diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.html index f5cf5ddb0d01..9fed18accfbc 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.html @@ -11,67 +11,85 @@ Cluster Logs -
-
+ @if (clog) { +
+ @if (clog.length && showClusterLogs && showDownloadCopyButton) { +
+ fileName="cluster_log"> - +
-
-

- {{ line.stamp | cdDate }} - {{ line.priority }} - -

- - + } + +
+ @for (line of clog; track trackByLogEntry($index, line)) { +
+ + + {{ line.priority }} + + + +
+ } + + @if (clog.length === 0) { +
+ +
+ }
+ } Audit Logs -
-
+ @if (audit_log && showAuditLogs) { +
+ @if (audit_log.length && showDownloadCopyButton) { +
+ fileName="audit_log"> - +
-
-

- {{ line.stamp | cdDate }} - {{ line.priority }} - -

- - + } + +
+ @for (line of audit_log; track trackByLogEntry($index, line)) { +
+ + + {{ line.priority }} + + + +
+ } + + @if (audit_log.length === 0) { +
+ +
+ }
+ } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.scss index 6e4a282070a0..2476726fc54a 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.scss +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.scss @@ -1,58 +1,113 @@ -@use './src/styles/vendor/variables' as vv; +// Log viewer container +.log-viewer { + position: relative; + background: var(--cds-layer-01); + border-radius: var(--cds-spacing-02); + padding: var(--cds-spacing-05); -p { - font-family: monospace; -} + &--scrollable { + max-height: 50vh; + overflow-y: auto; -.card { - .btn-group { - margin-top: -57px; - position: absolute; - right: 0; - } + // Custom scrollbar styling for better Carbon integration + &::-webkit-scrollbar { + width: 8px; + } - div p { - display: flex; + &::-webkit-scrollbar-track { + background: var(--cds-layer-01); + } + + &::-webkit-scrollbar-thumb { + background: var(--cds-border-subtle-01); + border-radius: var(--cds-spacing-02); - &:last-child { - margin-bottom: 0; + &:hover { + background: var(--cds-border-strong-01); + } } } - .timestamp { - flex-shrink: 0; - font-weight: bold; + &__empty { + font-size: var(--cds-body-compact-01-font-size); + font-weight: var(--cds-body-compact-01-font-weight); + line-height: var(--cds-body-compact-01-line-height); + letter-spacing: var(--cds-body-compact-01-letter-spacing); + color: var(--cds-text-secondary); + padding: var(--cds-spacing-07) 0; + text-align: center; } +} - .priority { - margin-left: 0.5rem; - } +// Action buttons (download/copy) +.log-actions { + position: absolute; + top: var(--cds-spacing-03); + right: var(--cds-spacing-03); + display: flex; + gap: var(--cds-spacing-02); + z-index: 1; +} - .message { - margin-left: 1rem; - } +// Log entries container +.log-entries { + display: flex; + flex-direction: column; + gap: var(--cds-spacing-02); +} - .err { - color: vv.$danger; - } +// Individual log entry +.log-entry { + display: flex; + gap: var(--cds-spacing-04); + padding: var(--cds-spacing-02) 0; - .warn { - color: vv.$warning; + &:hover { + background: var(--cds-layer-hover-01); + margin: 0 calc(-1 * var(--cds-spacing-03)); + padding: var(--cds-spacing-02) var(--cds-spacing-03); + border-radius: var(--cds-spacing-01); } - .info { - color: vv.$info; + &__timestamp { + flex-shrink: 0; + font-weight: 600; + color: var(--cds-text-primary); + min-width: 140px; } - .debug { - color: vv.$gray-700; + &__priority { + flex-shrink: 0; + font-weight: 500; + min-width: 48px; + + &--err { + color: var(--cds-support-error); + } + + &--warn { + color: var(--cds-support-warning); + } + + &--info { + color: var(--cds-support-info); + } + + &--debug { + color: var(--cds-text-secondary); + } } -} -::ng-deep cd-logs ngb-timepicker input.ngb-tp-input { - width: 3.5rem !important; + &__message { + flex: 1; + overflow-wrap: break-word; + color: var(--cds-text-primary); + } } -.card-body.overflow-auto { - height: 50vh; +.log-entry__message mark { + background-color: var(--cds-background-selected); + color: var(--cds-text-on-color); + padding: 0 var(--cds-spacing-01); + border-radius: var(--cds-spacing-01); } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.ts index 2feac9cb91b4..f9d13d7585c4 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.ts @@ -1,5 +1,5 @@ import { DatePipe } from '@angular/common'; -import { Component, Input, NgZone, OnDestroy, OnInit } from '@angular/core'; +import { Component, Input, NgZone, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; import { NgbDateStruct } from '@ng-bootstrap/ng-bootstrap'; import { Observable } from 'rxjs'; @@ -13,6 +13,7 @@ import { Icons } from '~/app/shared/enum/icons.enum'; selector: 'cd-logs', templateUrl: './logs.component.html', styleUrls: ['./logs.component.scss'], + encapsulation: ViewEncapsulation.None, standalone: false }) export class LogsComponent implements OnInit, OnDestroy { @@ -192,4 +193,8 @@ export class LogsComponent implements OnInit, OnDestroy { } return logText; } + + trackByLogEntry(index: number, entry: any): string { + return `${entry.stamp}-${index}`; + } } -- 2.47.3