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: {