From a9735fd77725083a1f945bedb899d663f2eb0ecd Mon Sep 17 00:00:00 2001 From: Aaron Greenspan Date: Thu, 4 Feb 2021 12:40:59 -0700 Subject: [PATCH] ui: adds agent logs page in server show --- .../server-logs/server-logs.module.ts | 28 ++++++ .../server-logs/server-logs.page.html | 22 +++++ .../server-logs/server-logs.page.scss | 0 .../server-logs/server-logs.page.ts | 45 +++++++++ .../server-routes/server-routing.module.ts | 5 + .../server-show/server-show.page.html | 5 + ui/src/app/services/api/api.service.ts | 3 + ui/src/app/services/api/live-api.service.ts | 4 + ui/src/app/services/api/mock-api.service.ts | 94 +++++++++++++++++++ 9 files changed, 206 insertions(+) create mode 100644 ui/src/app/pages/server-routes/server-logs/server-logs.module.ts create mode 100644 ui/src/app/pages/server-routes/server-logs/server-logs.page.html create mode 100644 ui/src/app/pages/server-routes/server-logs/server-logs.page.scss create mode 100644 ui/src/app/pages/server-routes/server-logs/server-logs.page.ts diff --git a/ui/src/app/pages/server-routes/server-logs/server-logs.module.ts b/ui/src/app/pages/server-routes/server-logs/server-logs.module.ts new file mode 100644 index 000000000..b2fa3dd6a --- /dev/null +++ b/ui/src/app/pages/server-routes/server-logs/server-logs.module.ts @@ -0,0 +1,28 @@ +import { NgModule } from '@angular/core' +import { CommonModule } from '@angular/common' +import { Routes, RouterModule } from '@angular/router' + +import { IonicModule } from '@ionic/angular' + +import { ServerLogsPage } from './server-logs.page' +import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module' +import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module' + +const routes: Routes = [ + { + path: '', + component: ServerLogsPage, + }, +] + +@NgModule({ + imports: [ + CommonModule, + IonicModule, + RouterModule.forChild(routes), + PwaBackComponentModule, + BadgeMenuComponentModule, + ], + declarations: [ServerLogsPage], +}) +export class ServerLogsPageModule { } diff --git a/ui/src/app/pages/server-routes/server-logs/server-logs.page.html b/ui/src/app/pages/server-routes/server-logs/server-logs.page.html new file mode 100644 index 000000000..629d8c2ec --- /dev/null +++ b/ui/src/app/pages/server-routes/server-logs/server-logs.page.html @@ -0,0 +1,22 @@ + + + + + + Logs + + + + + + + + + + + + {{ error }} + + +

{{ logs }}

+
\ No newline at end of file diff --git a/ui/src/app/pages/server-routes/server-logs/server-logs.page.scss b/ui/src/app/pages/server-routes/server-logs/server-logs.page.scss new file mode 100644 index 000000000..e69de29bb diff --git a/ui/src/app/pages/server-routes/server-logs/server-logs.page.ts b/ui/src/app/pages/server-routes/server-logs/server-logs.page.ts new file mode 100644 index 000000000..a44d8889c --- /dev/null +++ b/ui/src/app/pages/server-routes/server-logs/server-logs.page.ts @@ -0,0 +1,45 @@ +import { Component, ViewChild } from '@angular/core' +import { ActivatedRoute } from '@angular/router' +import { ApiService } from 'src/app/services/api/api.service' +import { IonContent } from '@ionic/angular' +import { pauseFor } from 'src/app/util/misc.util' +import { markAsLoadingDuringP } from 'src/app/services/loader.service' +import { BehaviorSubject } from 'rxjs' + +@Component({ + selector: 'server-logs', + templateUrl: './server-logs.page.html', + styleUrls: ['./server-logs.page.scss'], +}) +export class ServerLogsPage { + @ViewChild(IonContent, { static: false }) private content: IonContent + $loading$ = new BehaviorSubject(true) + error = '' + logs: string + + constructor ( + private readonly apiService: ApiService, + ) { } + + async ngOnInit () { + markAsLoadingDuringP(this.$loading$, Promise.all([ + this.getLogs(), + pauseFor(600), + ])) + } + + async getLogs () { + this.logs = '' + this.$loading$.next(true) + try { + this.logs = await this.apiService.getServerLogs() + this.error = '' + setTimeout(async () => await this.content.scrollToBottom(100), 200) + } catch (e) { + console.error(e) + this.error = e.message + } finally { + this.$loading$.next(false) + } + } +} diff --git a/ui/src/app/pages/server-routes/server-routing.module.ts b/ui/src/app/pages/server-routes/server-routing.module.ts index 78f5516fc..fbee41b59 100644 --- a/ui/src/app/pages/server-routes/server-routing.module.ts +++ b/ui/src/app/pages/server-routes/server-routing.module.ts @@ -18,6 +18,11 @@ const routes: Routes = [ canActivate: [AuthGuard], loadChildren: () => import('./server-metrics/server-metrics.module').then(m => m.ServerMetricsPageModule), }, + { + path: 'logs', + canActivate: [AuthGuard], + loadChildren: () => import('./server-logs/server-logs.module').then(m => m.ServerLogsPageModule), + }, { path: 'config', canActivate: [AuthGuard], diff --git a/ui/src/app/pages/server-routes/server-show/server-show.page.html b/ui/src/app/pages/server-routes/server-show/server-show.page.html index 11f0c9ecf..f4fa3c24e 100644 --- a/ui/src/app/pages/server-routes/server-show/server-show.page.html +++ b/ui/src/app/pages/server-routes/server-show/server-show.page.html @@ -47,6 +47,11 @@ Monitor + + + Logs + + Config diff --git a/ui/src/app/services/api/api.service.ts b/ui/src/app/services/api/api.service.ts index f920f5fc4..e5ffde85b 100644 --- a/ui/src/app/services/api/api.service.ts +++ b/ui/src/app/services/api/api.service.ts @@ -39,6 +39,7 @@ export abstract class ApiService { abstract getExternalDisks (): Promise abstract getAppConfig (appId: string): Promise<{ spec: ConfigSpec, config: object, rules: Rules[]}> abstract getAppLogs (appId: string, params?: ReqRes.GetAppLogsReq): Promise + abstract getServerLogs (): Promise abstract installApp (appId: string, version: string, dryRun?: boolean): Promise abstract uninstallApp (appId: string, dryRun?: boolean): Promise<{ breakages: DependentBreakage[] }> abstract startApp (appId: string): Promise @@ -76,7 +77,9 @@ export module ReqRes { export type GetAppInstalledRes = ApiAppInstalledFull export type GetAppConfigRes = ApiAppConfig export type GetAppLogsReq = { after?: string, before?: string, page?: string, perPage?: string } + export type GetServerLogsReq = { } export type GetAppLogsRes = string[] + export type GetServerLogsRes = string export type GetAppMetricsRes = AppMetricsVersioned export type GetAppsInstalledRes = AppInstalledPreview[] export type PostInstallAppReq = { version: string } diff --git a/ui/src/app/services/api/live-api.service.ts b/ui/src/app/services/api/live-api.service.ts index 85886cdf7..a1b397f73 100644 --- a/ui/src/app/services/api/live-api.service.ts +++ b/ui/src/app/services/api/live-api.service.ts @@ -123,6 +123,10 @@ export class LiveApiService extends ApiService { return this.authRequest( { method: Method.GET, url: `/apps/${appId}/logs`, params: params as any }) } + async getServerLogs (): Promise { + return this.authRequest( { method: Method.GET, url: `/logs` }) + } + async getAppMetrics (appId: string): Promise { return this.authRequest( { method: Method.GET, url: `/apps/${appId}/metrics` }) .then(parseMetricsPermissive) diff --git a/ui/src/app/services/api/mock-api.service.ts b/ui/src/app/services/api/mock-api.service.ts index 82b63ae01..1f3f0cd72 100644 --- a/ui/src/app/services/api/mock-api.service.ts +++ b/ui/src/app/services/api/mock-api.service.ts @@ -113,6 +113,10 @@ export class MockApiService extends ApiService { return mockGetAppLogs() } + async getServerLogs (): Promise { + return mockGetServerLogs() + } + async installApp (appId: string, version: string, dryRun: boolean): Promise { return mockInstallApp(appId) } @@ -271,6 +275,11 @@ async function mockGetAppLogs (): Promise { return mockApiAppLogs } +async function mockGetServerLogs (): Promise { + await pauseFor(1000) + return mockApiServerLogs.join('\n') +} + async function mockGetAppMetrics (): Promise { await pauseFor(1000) return mockApiAppMetricsV1 @@ -610,6 +619,91 @@ const mockApiAppLogs: string[] = [ '****** FINISH *****', ] +const mockApiServerLogs: string[] = [ + '****** START *****', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:20:30.872Z - Hash: 2b2e5abb3cba2164aea0', + '[ng] 114 unchanged chunks', + '[ng] chunk {app-logs-app-logs-module} app-logs-app-logs-module.js, app-logs-app-logs-module.js.map (app-logs-app-logs-module) 7.86 kB [rendered]', + '[ng] Time: 1244ms', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:21:01.685Z - Hash: bb3f5d0e11f2cd2dd57b', + '[ng] 114 unchanged chunks', + '[ng] chunk {app-logs-app-logs-module} app-logs-app-logs-module.js, app-logs-app-logs-module.js.map (app-logs-app-logs-module) 7.86 kB [rendered]', + '[ng] Time: 1185ms', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:23:13.812Z - Hash: 9342e11e6b8e16ad2f70', + '[ng] 114 unchanged chunks', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:20:30.872Z - Hash: 2b2e5abb3cba2164aea0', + '[ng] 114 unchanged chunks', + '[ng] chunk {app-logs-app-logs-module} app-logs-app-logs-module.js, app-logs-app-logs-module.js.map (app-logs-app-logs-module) 7.86 kB [rendered]', + '[ng] Time: 1244ms', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:21:01.685Z - Hash: bb3f5d0e11f2cd2dd57b', + '[ng] 114 unchanged chunks', + '[ng] chunk {app-logs-app-logs-module} app-logs-app-logs-module.js, app-logs-app-logs-module.js.map (app-logs-app-logs-module) 7.86 kB [rendered]', + '[ng] Time: 1185ms', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:23:13.812Z - Hash: 9342e11e6b8e16ad2f70', + '[ng] 114 unchanged chunks', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:20:30.872Z - Hash: 2b2e5abb3cba2164aea0', + '[ng] 114 unchanged chunks', + '[ng] chunk {app-logs-app-logs-module} app-logs-app-logs-module.js, app-logs-app-logs-module.js.map (app-logs-app-logs-module) 7.86 kB [rendered]', + '[ng] Time: 1244ms', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:21:01.685Z - Hash: bb3f5d0e11f2cd2dd57b', + '[ng] 114 unchanged chunks', + '[ng] chunk {app-logs-app-logs-module} app-logs-app-logs-module.js, app-logs-app-logs-module.js.map (app-logs-app-logs-module) 7.86 kB [rendered]', + '[ng] Time: 1185ms', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:23:13.812Z - Hash: 9342e11e6b8e16ad2f70', + '[ng] 114 unchanged chunks', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:20:30.872Z - Hash: 2b2e5abb3cba2164aea0', + '[ng] 114 unchanged chunks', + '[ng] chunk {app-logs-app-logs-module} app-logs-app-logs-module.js, app-logs-app-logs-module.js.map (app-logs-app-logs-module) 7.86 kB [rendered]', + '[ng] Time: 1244ms', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:21:01.685Z - Hash: bb3f5d0e11f2cd2dd57b', + '[ng] 114 unchanged chunks', + '[ng] chunk {app-logs-app-logs-module} app-logs-app-logs-module.js, app-logs-app-logs-module.js.map (app-logs-app-logs-module) 7.86 kB [rendered]', + '[ng] Time: 1185ms', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:23:13.812Z - Hash: 9342e11e6b8e16ad2f70', + '[ng] 114 unchanged chunks', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:20:30.872Z - Hash: 2b2e5abb3cba2164aea0', + '[ng] 114 unchanged chunks', + '[ng] chunk {app-logs-app-logs-module} app-logs-app-logs-module.js, app-logs-app-logs-module.js.map (app-logs-app-logs-module) 7.86 kB [rendered]', + '[ng] Time: 1244ms', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:21:01.685Z - Hash: bb3f5d0e11f2cd2dd57b', + '[ng] 114 unchanged chunks', + '[ng] chunk {app-logs-app-logs-module} app-logs-app-logs-module.js, app-logs-app-logs-module.js.map (app-logs-app-logs-module) 7.86 kB [rendered]', + '[ng] Time: 1185ms', + '[ng] ℹ 「wdm」: Compiled successfully.', + '[ng] ℹ 「wdm」: Compiling...', + '[ng] Date: 2019-12-26T14:23:13.812Z - Hash: 9342e11e6b8e16ad2f70', + '[ng] 114 unchanged chunks', + '****** FINISH *****', +] + const mockApiAppMetricsV1: AppMetricsVersioned<2> = { version: 2, data: {