]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Add daemon logs tab to Logs component 46807/head
authorAashish Sharma <aasharma@redhat.com>
Fri, 6 May 2022 07:09:02 +0000 (12:39 +0530)
committerAashish Sharma <aasharma@redhat.com>
Wed, 22 Jun 2022 10:26:53 +0000 (15:56 +0530)
Add Daemon logs to the logs component

Signed-off-by: Aashish Sharma <aasharma@redhat.com>
(cherry picked from commit a581660f47d85da0e985c5bcba6e9a6cd6b47dae)

16 files changed:
src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/logs.e2e-spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-performance/rbd-performance.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-tabs/cephfs-tabs.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.html
src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.ts

index 9868b89aedbc5489298b34355d7a092078a44a06..ecc3cc1cd912668b407dacdce3d5283b5cf48258 100644 (file)
@@ -27,8 +27,8 @@ describe('Logs page', () => {
       logs.expectBreadcrumbText('Logs');
     });
 
-    it('should show two tabs', () => {
-      logs.getTabsCount().should('eq', 2);
+    it('should show three tabs', () => {
+      logs.getTabsCount().should('eq', 3);
     });
 
     it('should show cluster logs tab at first', () => {
@@ -38,6 +38,10 @@ describe('Logs page', () => {
     it('should show audit logs as a second tab', () => {
       logs.getTabText(1).should('eq', 'Audit Logs');
     });
+
+    it('should show daemon logs as a third tab', () => {
+      logs.getTabText(2).should('eq', 'Daemon Logs');
+    });
   });
 
   describe('audit logs respond to pool creation and deletion test', () => {
index 7503863e0fb2c256165b2b0ee793e83b6ad62792..349fba7b0f967cf35049f6caf4216baba6ecd415 100644 (file)
          i18n>Performance</a>
       <ng-template ngbNavContent>
         <cd-grafana [grafanaPath]="rbdDashboardUrl"
+                    [type]="'metrics'"
                     uid="YhCYGcuZz"
                     grafanaStyle="one">
         </cd-grafana>
index 002c8e57c02036830a38eb3b1e44bb4e8c98b583..e8116ea2a86d2b3af772b5bcc9cd2237ab752ab6 100644 (file)
@@ -1,6 +1,7 @@
 <cd-rbd-tabs></cd-rbd-tabs>
 
 <cd-grafana [grafanaPath]="'rbd-overview?'"
+            [type]="'metrics'"
             uid="41FrpeUiz"
             grafanaStyle="two">
 </cd-grafana>
index 7a222a1000e32e5fa72be822bff4e3ccbb6a4558..830645d2b6fca0a2a43c5f483254f14b8313c7b9 100644 (file)
@@ -36,6 +36,7 @@
          i18n>Performance Details</a>
       <ng-template ngbNavContent>
         <cd-grafana [grafanaPath]="'mds-performance?var-mds_servers=mds.' + grafanaId"
+                    [type]="'metrics'"
                     uid="tbO9LAiZz"
                     grafanaStyle="one">
         </cd-grafana>
index a138768c351f4328a71b396ebf63996b0d4cf976..5803776d0aaefb28813c17accc2495a01386f7d7 100644 (file)
@@ -35,6 +35,7 @@
          i18n>Performance Details</a>
       <ng-template ngbNavContent>
         <cd-grafana [grafanaPath]="'host-details?var-ceph_hosts=' + selectedHostname"
+                    [type]="'metrics'"
                     uid="rtOg0AiWz"
                     grafanaStyle="four">
         </cd-grafana>
index b41ecfa8663302264a2a0246701838930040d36f..b8a17135af4379336f6f6c00176e0769e7d534c7 100644 (file)
@@ -36,6 +36,7 @@
        i18n>Overall Performance</a>
     <ng-template ngbNavContent>
       <cd-grafana [grafanaPath]="'host-overview?'"
+                  [type]="'metrics'"
                   uid="y0KGL0iZz"
                   grafanaStyle="two">
       </cd-grafana>
index dd55a678fb19614aaa5fae3d75eace193ce3d774..d5c73eb73904a198f8e66319ad2abefbd17fb544 100644 (file)
         </div>
       </ng-template>
     </li>
+    <li ngbNavItem="daemon-logs">
+      <a ngbNavLink
+         i18n>Daemon Logs</a>
+      <ng-template ngbNavContent>
+        <ng-container *ngIf="lokiServiceStatus$ | async as lokiServiceStatus; else daemonLogsTpl">
+          <div *ngIf="promtailServiceStatus$ | async as promtailServiceStatus; else daemonLogsTpl">
+            <cd-grafana [grafanaPath]="'explore?'"
+                        [type]="'logs'"
+                        uid="CrAHE0iZz"
+                        grafanaStyle="two">
+            </cd-grafana>
+          </div>
+        </ng-container>
+      </ng-template>
+    </li>
   </ul>
 
   <div [ngbNavOutlet]="nav"></div>
      (click)="resetFilter()"
      i18n>Reset filter.</a>
 </ng-template>
+
+<ng-template #daemonLogsTpl>
+  <cd-alert-panel type="info"
+                  title="Loki/Promtail service not running"
+                  i18n-title>
+  <ng-container i18n>Please start the loki and promtail service to see these logs.</ng-container>
+  </cd-alert-panel>
+</ng-template>
index 420da495891425d34954fdf15fd215c22903978e..ed8c721eaf3e1f6b3440d091c4c829dc01edf366 100644 (file)
@@ -2,7 +2,10 @@ import { DatePipe } from '@angular/common';
 import { Component, NgZone, OnDestroy, OnInit } from '@angular/core';
 
 import { NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
+import { Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
 
+import { CephServiceService } from '~/app/shared/api/ceph-service.service';
 import { LogsService } from '~/app/shared/api/logs.service';
 import { Icons } from '~/app/shared/enum/icons.enum';
 
@@ -18,6 +21,8 @@ export class LogsComponent implements OnInit, OnDestroy {
   icons = Icons;
   clogText: string;
   auditLogText: string;
+  lokiServiceStatus$: Observable<boolean>;
+  promtailServiceStatus$: Observable<boolean>;
 
   interval: number;
   priorities: Array<{ name: string; value: string }> = [
@@ -40,6 +45,7 @@ export class LogsComponent implements OnInit, OnDestroy {
 
   constructor(
     private logsService: LogsService,
+    private cephService: CephServiceService,
     private datePipe: DatePipe,
     private ngZone: NgZone
   ) {}
@@ -47,6 +53,7 @@ export class LogsComponent implements OnInit, OnDestroy {
   ngOnInit() {
     this.getInfo();
     this.ngZone.runOutsideAngular(() => {
+      this.getDaemonDetails();
       this.interval = window.setInterval(() => {
         this.ngZone.run(() => {
           this.getInfo();
@@ -59,6 +66,19 @@ export class LogsComponent implements OnInit, OnDestroy {
     clearInterval(this.interval);
   }
 
+  getDaemonDetails() {
+    this.lokiServiceStatus$ = this.cephService.getDaemons('loki').pipe(
+      map((data: any) => {
+        return data.length > 0 && data[0].status === 1;
+      })
+    );
+    this.promtailServiceStatus$ = this.cephService.getDaemons('promtail').pipe(
+      map((data: any) => {
+        return data.length > 0 && data[0].status === 1;
+      })
+    );
+  }
+
   getInfo() {
     this.logsService.getLogs().subscribe((data: any) => {
       this.contentData = data;
index bd85e2255689ba1291f3afaabb36d229b8b01289..56eee8c8b9c432dba8c8b46c73f8fd417db8448b 100644 (file)
@@ -56,6 +56,7 @@
          i18n>Performance Details</a>
       <ng-template ngbNavContent>
         <cd-grafana [grafanaPath]="'osd-device-details?var-osd=osd.' + osd['id']"
+                    [type]="'metrics'"
                     uid="CrAHE0iZz"
                     grafanaStyle="three">
         </cd-grafana>
index 3e6f1475afff8da90f0ea53f2877555d4777c8ac..afec81d9d1971e2446d5b36768329ee7ae8ecc01 100644 (file)
@@ -44,6 +44,7 @@
        i18n>Overall Performance</a>
     <ng-template ngbNavContent>
       <cd-grafana [grafanaPath]="'osd-overview?'"
+                  [type]="'metrics'"
                   uid="lo02I1Aiz"
                   grafanaStyle="four">
       </cd-grafana>
index 1b0cd563cc8aa37a959b718faaa08cf36b7df615..40d71dd0e32182f39d87120bc02f45dcc0ed8d01 100644 (file)
@@ -20,6 +20,7 @@
          i18n>Performance Details</a>
       <ng-template ngbNavContent>
         <cd-grafana grafanaPath="ceph-pool-detail?var-pool_name={{selection.pool_name}}"
+                    [type]="'metrics'"
                     uid="-xyV8KCiz"
                     grafanaStyle="three">
         </cd-grafana>
index 7122f749cfb9e84f33a7fa1774c2fd62a2dea70b..bd568a9107ea03d1a93453e4c51927305106bc59 100644 (file)
@@ -38,6 +38,7 @@
        i18n>Overall Performance</a>
     <ng-template ngbNavContent>
       <cd-grafana [grafanaPath]="'ceph-pools-overview?'"
+                  [type]="'metrics'"
                   uid="z99hzWtmk"
                   grafanaStyle="two">
       </cd-grafana>
index e53eaa8f73d3d6c5801f52429bc52e4cc78a4148..f10394342b1381e0eef7c587bad937fb63e8ff18 100644 (file)
@@ -27,6 +27,7 @@
          i18n>Performance Details</a>
       <ng-template ngbNavContent>
         <cd-grafana [grafanaPath]="'rgw-instance-detail?var-rgw_servers=rgw.' + this.serviceId"
+                    [type]="'metrics'"
                     uid="x5ARzZtmk"
                     grafanaStyle="one">
         </cd-grafana>
index 38683a6f6d8f72e1fe562a65bf646579afca3cb6..e5b01305706ae81ec6e2450f3ae5ec1486dcafc8 100644 (file)
@@ -24,6 +24,7 @@
        i18n>Overall Performance</a>
     <ng-template ngbNavContent>
       <cd-grafana [grafanaPath]="'rgw-overview?'"
+                  [type]="'metrics'"
                   uid="WAkugZpiz"
                   grafanaStyle="two">
       </cd-grafana>
@@ -36,6 +37,7 @@
        i18n>Sync Performance</a>
     <ng-template ngbNavContent>
       <cd-grafana [grafanaPath]="'radosgw-sync-overview?'"
+                  [type]="'metrics'"
                   uid="rgw-sync-overview"
                   grafanaStyle="two">
       </cd-grafana>
index 63733fd759cccd79423ee02fe9b097cf14787947..5052ef9ec6e822eac104b8b9c6f13077c0af1c78 100644 (file)
@@ -20,6 +20,8 @@ describe('GrafanaComponent', () => {
   let fixture: ComponentFixture<GrafanaComponent>;
   const expected_url =
     'http:localhost:3000/d/foo/somePath&refresh=2s&var-datasource=Dashboard1&kiosk&from=now-1h&to=now';
+  const expected_logs_url =
+    'http:localhost:3000/explore?orgId=1&left=["now-1h","now","Loki",{"refId":"A"}]&kiosk';
 
   configureTestBed({
     declarations: [GrafanaComponent, AlertPanelComponent, LoadingPanelComponent, DocComponent],
@@ -31,6 +33,7 @@ describe('GrafanaComponent', () => {
     fixture = TestBed.createComponent(GrafanaComponent);
     component = fixture.componentInstance;
     component.grafanaPath = 'somePath';
+    component.type = 'metrics';
     component.uid = 'foo';
   });
 
@@ -50,6 +53,7 @@ describe('GrafanaComponent', () => {
   describe('with grafana initialized', () => {
     beforeEach(() => {
       TestBed.inject(SettingsService)['settings'] = { 'api/grafana/url': 'http:localhost:3000' };
+      component.type = 'metrics';
       fixture.detectChanges();
     });
 
@@ -78,4 +82,23 @@ describe('GrafanaComponent', () => {
       expect(component.dashboardExist).toBe(true);
     });
   });
+
+  describe('with loki datasource', () => {
+    beforeEach(() => {
+      TestBed.inject(SettingsService)['settings'] = { 'api/grafana/url': 'http:localhost:3000' };
+      component.type = 'logs';
+      component.grafanaPath = 'explore?';
+      fixture.detectChanges();
+    });
+
+    it('should have found out that Loki Log Search exists', () => {
+      expect(component.grafanaExist).toBe(true);
+      expect(component.baseUrl).toBe('http:localhost:3000/d/');
+      expect(component.loading).toBe(false);
+      expect(component.url).toBe(expected_logs_url);
+      expect(component.grafanaSrc).toEqual({
+        changingThisBreaksApplicationSecurity: expected_logs_url
+      });
+    });
+  });
 });
index a687959b747f8532a7b03a69e8a642000a21655e..a5c32e6867a20b57531ab9e667c758d90dd6c577 100644 (file)
@@ -19,7 +19,7 @@ export class GrafanaComponent implements OnInit, OnChanges {
   panelStyle: any;
   grafanaExist = false;
   mode = '&kiosk';
-  datasource = 'Dashboard1';
+  datasource: string;
   loading = true;
   styles: Record<string, string> = {};
   dashboardExist = true;
@@ -28,6 +28,8 @@ export class GrafanaComponent implements OnInit, OnChanges {
   icons = Icons;
   readonly DEFAULT_TIME: string = 'from=now-1h&to=now';
 
+  @Input()
+  type: string;
   @Input()
   grafanaPath: string;
   @Input()
@@ -153,6 +155,8 @@ export class GrafanaComponent implements OnInit, OnChanges {
       four: 'grafana_four'
     };
 
+    this.datasource = this.type === 'metrics' ? 'Dashboard1' : 'Loki';
+
     this.settingsService.ifSettingConfigured('api/grafana/url', (url) => {
       this.grafanaExist = true;
       this.loading = false;
@@ -166,16 +170,13 @@ export class GrafanaComponent implements OnInit, OnChanges {
     this.settingsService
       .validateGrafanaDashboardUrl(this.uid)
       .subscribe((data: any) => (this.dashboardExist = data === 200));
-    this.url =
-      this.baseUrl +
-      this.uid +
-      '/' +
-      this.grafanaPath +
-      '&refresh=2s' +
-      `&var-datasource=${this.datasource}` +
-      this.mode +
-      '&' +
-      this.time;
+    if (this.type === 'metrics') {
+      this.url = `${this.baseUrl}${this.uid}/${this.grafanaPath}&refresh=2s&var-datasource=${this.datasource}${this.mode}&${this.time}`;
+    } else {
+      this.url = `${this.baseUrl.slice(0, -2)}${this.grafanaPath}orgId=1&left=["now-1h","now","${
+        this.datasource
+      }",{"refId":"A"}]${this.mode}`;
+    }
     this.grafanaSrc = this.sanitizer.bypassSecurityTrustResourceUrl(this.url);
   }