ui: adds agent logs page in server show

This commit is contained in:
Aaron Greenspan
2021-02-04 12:40:59 -07:00
committed by Aiden McClelland
parent 327c79350e
commit a9735fd777
9 changed files with 206 additions and 0 deletions

View File

@@ -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 { }

View File

@@ -0,0 +1,22 @@
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<pwa-back-button></pwa-back-button>
</ion-buttons>
<ion-title>Logs</ion-title>
<ion-buttons slot="end" class="ion-padding-end">
<ion-button (click)="getLogs()" color="primary">
<ion-icon name="refresh-outline"></ion-icon>
</ion-button>
<badge-menu-button></badge-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding" color="light">
<ion-item *ngIf="error" style="margin-bottom: 16px;">
<ion-text class="ion-text-wrap" color="danger">{{ error }}</ion-text>
</ion-item>
<ion-spinner *ngIf="$loading$ | async" class="center" name="lines" color="warning"></ion-spinner>
<p style="white-space: pre-line;">{{ logs }}</p>
</ion-content>

View File

@@ -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)
}
}
}

View File

@@ -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],

View File

@@ -47,6 +47,11 @@
<ion-label><ion-text color="primary">Monitor</ion-text></ion-label>
</ion-item>
<ion-item [routerLink]="['logs']">
<ion-icon slot="start" name="newspaper-outline" color="primary"></ion-icon>
<ion-label><ion-text color="primary">Logs</ion-text></ion-label>
</ion-item>
<ion-item lines="none" [routerLink]="['config']">
<ion-icon slot="start" name="cog-outline" color="primary"></ion-icon>
<ion-label><ion-text color="primary">Config</ion-text></ion-label>

View File

@@ -39,6 +39,7 @@ export abstract class ApiService {
abstract getExternalDisks (): Promise<DiskInfo[]>
abstract getAppConfig (appId: string): Promise<{ spec: ConfigSpec, config: object, rules: Rules[]}>
abstract getAppLogs (appId: string, params?: ReqRes.GetAppLogsReq): Promise<string[]>
abstract getServerLogs (): Promise<string>
abstract installApp (appId: string, version: string, dryRun?: boolean): Promise<AppInstalledFull & { breakages: DependentBreakage[] } >
abstract uninstallApp (appId: string, dryRun?: boolean): Promise<{ breakages: DependentBreakage[] }>
abstract startApp (appId: string): Promise<Unit>
@@ -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<number>
export type GetAppsInstalledRes = AppInstalledPreview[]
export type PostInstallAppReq = { version: string }

View File

@@ -123,6 +123,10 @@ export class LiveApiService extends ApiService {
return this.authRequest<ReqRes.GetAppLogsRes>( { method: Method.GET, url: `/apps/${appId}/logs`, params: params as any })
}
async getServerLogs (): Promise<string> {
return this.authRequest<ReqRes.GetServerLogsRes>( { method: Method.GET, url: `/logs` })
}
async getAppMetrics (appId: string): Promise<AppMetrics> {
return this.authRequest<ReqRes.GetAppMetricsRes | string>( { method: Method.GET, url: `/apps/${appId}/metrics` })
.then(parseMetricsPermissive)

View File

@@ -113,6 +113,10 @@ export class MockApiService extends ApiService {
return mockGetAppLogs()
}
async getServerLogs (): Promise<string> {
return mockGetServerLogs()
}
async installApp (appId: string, version: string, dryRun: boolean): Promise<AppInstalledFull & { breakages: DependentBreakage[] }> {
return mockInstallApp(appId)
}
@@ -271,6 +275,11 @@ async function mockGetAppLogs (): Promise<ReqRes.GetAppLogsRes> {
return mockApiAppLogs
}
async function mockGetServerLogs (): Promise<ReqRes.GetServerLogsRes> {
await pauseFor(1000)
return mockApiServerLogs.join('\n')
}
async function mockGetAppMetrics (): Promise<ReqRes.GetAppMetricsRes> {
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: {