From acb542462205b2bbaa34390fc18a0328755bd78d Mon Sep 17 00:00:00 2001 From: vthinkxie <yadong.xyd@alibaba-inc.com> Date: Tue, 14 Apr 2020 17:24:29 +0800 Subject: [PATCH] [FLINK-17130][web] Enable listing JM logs and displaying logs by filename This closes #11731. --- .../job-manager/job-manager-routing.module.ts | 16 ++++ .../job-manager/job-manager.component.ts | 3 +- .../pages/job-manager/job-manager.module.ts | 4 + .../job-manager-log-detail.component.html | 36 +++++++++ .../job-manager-log-detail.component.less | 54 +++++++++++++ .../job-manager-log-detail.component.ts | 78 +++++++++++++++++++ .../job-manager-log-list.component.html | 41 ++++++++++ .../job-manager-log-list.component.ts | 47 +++++++++++ .../task-manager-log-detail.component.less | 8 +- .../src/app/services/job-manager.service.ts | 27 +++++++ 10 files changed, 312 insertions(+), 2 deletions(-) create mode 100644 flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-detail/job-manager-log-detail.component.html create mode 100644 flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-detail/job-manager-log-detail.component.less create mode 100644 flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-detail/job-manager-log-detail.component.ts create mode 100644 flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-list/job-manager-log-list.component.html create mode 100644 flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-list/job-manager-log-list.component.ts diff --git a/flink-runtime-web/web-dashboard/src/app/pages/job-manager/job-manager-routing.module.ts b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/job-manager-routing.module.ts index 0b4dbc1287fde..9ccaa2d8e74b4 100644 --- a/flink-runtime-web/web-dashboard/src/app/pages/job-manager/job-manager-routing.module.ts +++ b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/job-manager-routing.module.ts @@ -20,6 +20,8 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { JobManagerConfigurationComponent } from './configuration/job-manager-configuration.component'; import { JobManagerComponent } from './job-manager.component'; +import { JobManagerLogDetailComponent } from './log-detail/job-manager-log-detail.component'; +import { JobManagerLogListComponent } from './log-list/job-manager-log-list.component'; import { JobManagerLogsComponent } from './logs/job-manager-logs.component'; import { JobManagerStdoutComponent } from './stdout/job-manager-stdout.component'; @@ -49,6 +51,20 @@ const routes: Routes = [ path: 'stdout' } }, + { + path: 'log', + component: JobManagerLogListComponent, + data: { + path: 'log' + } + }, + { + path: 'log/:logName', + component: JobManagerLogDetailComponent, + data: { + path: 'log' + } + }, { path: '**', redirectTo: 'config', diff --git a/flink-runtime-web/web-dashboard/src/app/pages/job-manager/job-manager.component.ts b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/job-manager.component.ts index ce14f28c9d39a..80951b31ff2c2 100644 --- a/flink-runtime-web/web-dashboard/src/app/pages/job-manager/job-manager.component.ts +++ b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/job-manager.component.ts @@ -28,6 +28,7 @@ export class JobManagerComponent { listOfNavigation = [ { path: 'config', title: 'Configuration' }, { path: 'logs', title: 'Logs' }, - { path: 'stdout', title: 'Stdout' } + { path: 'stdout', title: 'Stdout' }, + { path: 'log', title: 'Log List' } ]; } diff --git a/flink-runtime-web/web-dashboard/src/app/pages/job-manager/job-manager.module.ts b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/job-manager.module.ts index 0c11c48b311c6..5d22c100fa8e1 100644 --- a/flink-runtime-web/web-dashboard/src/app/pages/job-manager/job-manager.module.ts +++ b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/job-manager.module.ts @@ -23,6 +23,8 @@ import { ShareModule } from 'share/share.module'; import { JobManagerRoutingModule } from './job-manager-routing.module'; import { JobManagerComponent } from './job-manager.component'; import { JobManagerConfigurationComponent } from './configuration/job-manager-configuration.component'; +import { JobManagerLogDetailComponent } from './log-detail/job-manager-log-detail.component'; +import { JobManagerLogListComponent } from './log-list/job-manager-log-list.component'; import { JobManagerLogsComponent } from './logs/job-manager-logs.component'; import { JobManagerStdoutComponent } from './stdout/job-manager-stdout.component'; @@ -31,6 +33,8 @@ import { JobManagerStdoutComponent } from './stdout/job-manager-stdout.component declarations: [ JobManagerComponent, JobManagerConfigurationComponent, + JobManagerLogListComponent, + JobManagerLogDetailComponent, JobManagerLogsComponent, JobManagerStdoutComponent ] diff --git a/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-detail/job-manager-log-detail.component.html b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-detail/job-manager-log-detail.component.html new file mode 100644 index 0000000000000..a627ebf15c978 --- /dev/null +++ b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-detail/job-manager-log-detail.component.html @@ -0,0 +1,36 @@ +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you under the Apache License, Version 2.0 (the + ~ "License"); you may not use this file except in compliance + ~ with the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<div class="breadcrumb"> + <nz-breadcrumb> + <nz-breadcrumb-item> + <a [routerLink]="['../']"><i nz-icon type="rollback" theme="outline"></i> Log List</a> + </nz-breadcrumb-item> + <nz-breadcrumb-item> + {{ logName }} + </nz-breadcrumb-item> + </nz-breadcrumb> + <flink-refresh-download + [isLoading]="isLoading" + [downloadHref]="downloadUrl" + [downloadName]="logName" + (reload)="reload()" + (fullScreen)="toggleFullScreen($event)"> + </flink-refresh-download> +</div> +<flink-monaco-editor [value]="logs"></flink-monaco-editor> diff --git a/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-detail/job-manager-log-detail.component.less b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-detail/job-manager-log-detail.component.less new file mode 100644 index 0000000000000..3949a6f929ba0 --- /dev/null +++ b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-detail/job-manager-log-detail.component.less @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme"; + +:host { + display: block; + height: 100%; + &.full-screen { + position: fixed; + top: 0; + bottom: 0; + right: 0; + left: 0; + background: @component-background; + z-index: 99; + flink-monaco-editor { + height: calc(~"100vh - 46px"); + } + } +} + +flink-monaco-editor { + height: calc(~"100vh - 205px"); +} + +.breadcrumb { + background: @component-background; + border-bottom: 1px solid @border-color-split; + padding: 12px 24px; + position: relative; +} + +flink-refresh-download { + position: absolute; + right: 12px; + top: 0; + line-height: 47px; +} diff --git a/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-detail/job-manager-log-detail.component.ts b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-detail/job-manager-log-detail.component.ts new file mode 100644 index 0000000000000..b10ad6a0ab0c9 --- /dev/null +++ b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-detail/job-manager-log-detail.component.ts @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { finalize } from 'rxjs/operators'; +import { JobManagerService } from 'services'; +import { MonacoEditorComponent } from 'share/common/monaco-editor/monaco-editor.component'; + +@Component({ + selector: 'flink-job-manager-log-detail', + templateUrl: './job-manager-log-detail.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + host: { + '[class.full-screen]': 'isFullScreen' + }, + styleUrls: ['./job-manager-log-detail.component.less'] +}) +export class JobManagerLogDetailComponent implements OnInit { + logs = ''; + logName = ''; + downloadUrl = ''; + isLoading = false; + isFullScreen = false; + @ViewChild(MonacoEditorComponent) monacoEditorComponent: MonacoEditorComponent; + constructor( + private jobManagerService: JobManagerService, + private cdr: ChangeDetectorRef, + private activatedRoute: ActivatedRoute + ) {} + + reload() { + this.isLoading = true; + this.cdr.markForCheck(); + this.jobManagerService + .loadLog(this.logName) + .pipe( + finalize(() => { + this.isLoading = false; + this.layoutEditor(); + this.cdr.markForCheck(); + }) + ) + .subscribe(data => { + this.logs = data.data; + this.downloadUrl = data.url; + }); + } + + layoutEditor(): void { + setTimeout(() => this.monacoEditorComponent.layout()); + } + + toggleFullScreen(fullScreen: boolean) { + this.isFullScreen = fullScreen; + this.layoutEditor(); + } + + ngOnInit() { + this.logName = this.activatedRoute.snapshot.params.logName; + this.reload(); + } +} diff --git a/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-list/job-manager-log-list.component.html b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-list/job-manager-log-list.component.html new file mode 100644 index 0000000000000..efe09b34af559 --- /dev/null +++ b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-list/job-manager-log-list.component.html @@ -0,0 +1,41 @@ +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you under the Apache License, Version 2.0 (the + ~ "License"); you may not use this file except in compliance + ~ with the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<nz-card [nzBordered]="false"> + <nz-table + [nzSize]="'small'" + [nzData]="listOfLog" + [nzLoading]="isLoading" + [nzFrontPagination]="false" + [nzShowPagination]="false"> + <thead> + <tr> + <th>Log Name</th> + <th>Size (KB)</th> + </tr> + </thead> + <tbody> + <tr *ngFor="let log of listOfLog;"> + <td> + <a [routerLink]="[log.name]">{{ log.name }}</a> + </td> + <td>{{ (log.size / 1024) | number : '1.0-2' }}</td> + </tr> + </tbody> + </nz-table> +</nz-card> diff --git a/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-list/job-manager-log-list.component.ts b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-list/job-manager-log-list.component.ts new file mode 100644 index 0000000000000..9068b7bb98213 --- /dev/null +++ b/flink-runtime-web/web-dashboard/src/app/pages/job-manager/log-list/job-manager-log-list.component.ts @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core'; +import { finalize } from 'rxjs/operators'; +import { JobManagerService } from 'services'; + +@Component({ + selector: 'flink-job-manager-log-list', + templateUrl: './job-manager-log-list.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class JobManagerLogListComponent implements OnInit { + listOfLog: { name: string; size: number }[] = []; + isLoading = true; + + constructor(private jobManagerService: JobManagerService, private cdr: ChangeDetectorRef) {} + + ngOnInit() { + this.jobManagerService + .loadLogList() + .pipe( + finalize(() => { + this.isLoading = false; + this.cdr.markForCheck(); + }) + ) + .subscribe(data => { + this.listOfLog = data; + }); + } +} diff --git a/flink-runtime-web/web-dashboard/src/app/pages/task-manager/log-detail/task-manager-log-detail.component.less b/flink-runtime-web/web-dashboard/src/app/pages/task-manager/log-detail/task-manager-log-detail.component.less index d9bd69a31ff1b..73d1d21b1465a 100644 --- a/flink-runtime-web/web-dashboard/src/app/pages/task-manager/log-detail/task-manager-log-detail.component.less +++ b/flink-runtime-web/web-dashboard/src/app/pages/task-manager/log-detail/task-manager-log-detail.component.less @@ -27,8 +27,14 @@ left: 0; background: @component-background; z-index: 99; + .breadcrumb { + margin-bottom: 0px; + border-top: 0px; + } flink-monaco-editor { - height: calc(~"100vh - 65px"); + border-top: 0px; + border-bottom: 0px; + height: calc(~"100vh - 46px"); } } } diff --git a/flink-runtime-web/web-dashboard/src/app/services/job-manager.service.ts b/flink-runtime-web/web-dashboard/src/app/services/job-manager.service.ts index 06b6aa2ea5856..aa83524a82aac 100644 --- a/flink-runtime-web/web-dashboard/src/app/services/job-manager.service.ts +++ b/flink-runtime-web/web-dashboard/src/app/services/job-manager.service.ts @@ -19,6 +19,7 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { BASE_URL } from 'config'; +import { map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' @@ -50,6 +51,32 @@ export class JobManagerService { headers: new HttpHeaders().append('Cache-Control', 'no-cache') }); } + /** + * Load JM log list + */ + loadLogList() { + return this.httpClient + .get<{ logs: Array<{ name: string; size: number }> }>(`${BASE_URL}/jobmanager/logs`) + .pipe(map(data => data.logs)); + } + + /** + * Load JM log + * @param logName + */ + loadLog(logName: string) { + const url = `${BASE_URL}/jobmanager/logs/${logName}`; + return this.httpClient + .get(url, { responseType: 'text', headers: new HttpHeaders().append('Cache-Control', 'no-cache') }) + .pipe( + map(data => { + return { + data, + url + }; + }) + ); + } constructor(private httpClient: HttpClient) {} }