Logging Enhancements (#1521)

* Recreated Kavita Logging with Serilog instead of Default. This needs to be move out of the appsettings now, to allow auto updater to patch.

* Refactored the code to be completely configured via Code rather than appsettings.json. This is a required step for Auto Updating.

* Added in the ability to send logs directly to the UI only for users on the log route. Stopping implementation as Alerts page will handle the rest of the implementation.

* Fixed up the backup service to not rely on Config from appsettings.json

* Tweaked the Logging levels available

* Moved everything over to File-scoped namespaces

* Moved everything over to File-scoped namespaces

* Code cleanup, removed an old migration and changed so debug logging doesn't print sensitive db data

* Removed dead code
This commit is contained in:
Joseph Milazzo 2022-09-12 19:25:48 -05:00 committed by GitHub
parent 9f715cc35f
commit d1a14f7e68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
212 changed files with 16599 additions and 16834 deletions

View file

@ -142,6 +142,12 @@ export class MessageHubService {
this.onlineUsersSource.next(usernames);
});
this.hubConnection.on("LogObject", resp => {
console.log(resp);
});
this.hubConnection.on("LogString", resp => {
console.log(resp);
});
this.hubConnection.on(EVENTS.ScanSeries, resp => {
this.messagesSource.next({

View file

@ -23,6 +23,8 @@ import { SidenavModule } from '../sidenav/sidenav.module';
import { ManageMediaSettingsComponent } from './manage-media-settings/manage-media-settings.component';
import { ManageEmailSettingsComponent } from './manage-email-settings/manage-email-settings.component';
import { ManageTasksSettingsComponent } from './manage-tasks-settings/manage-tasks-settings.component';
import { ManageLogsComponent } from './manage-logs/manage-logs.component';
import { VirtualScrollerModule } from '@iharbeck/ngx-virtual-scroller';
@ -45,6 +47,7 @@ import { ManageTasksSettingsComponent } from './manage-tasks-settings/manage-tas
ManageMediaSettingsComponent,
ManageEmailSettingsComponent,
ManageTasksSettingsComponent,
ManageLogsComponent,
],
imports: [
CommonModule,
@ -59,6 +62,7 @@ import { ManageTasksSettingsComponent } from './manage-tasks-settings/manage-tas
PipeModule,
SidenavModule,
UserSettingsModule, // API-key componet
VirtualScrollerModule
],
providers: []
})

View file

@ -23,6 +23,9 @@
<ng-container *ngIf="tab.fragment === TabID.Libraries">
<app-manage-library></app-manage-library>
</ng-container>
<ng-container *ngIf="tab.fragment === TabID.Logs">
<app-manage-logs></app-manage-logs>
</ng-container>
<ng-container *ngIf="tab.fragment === TabID.System">
<app-manage-system></app-manage-system>
</ng-container>

View file

@ -13,7 +13,8 @@ enum TabID {
Libraries = 'libraries',
System = 'system',
Plugins = 'plugins',
Tasks = 'tasks'
Tasks = 'tasks',
Logs = 'logs'
}
@Component({
@ -27,6 +28,7 @@ export class DashboardComponent implements OnInit {
{title: 'General', fragment: TabID.General},
{title: 'Users', fragment: TabID.Users},
{title: 'Libraries', fragment: TabID.Libraries},
//{title: 'Logs', fragment: TabID.Logs},
{title: 'Media', fragment: TabID.Media},
{title: 'Email', fragment: TabID.Email},
//{title: 'Plugins', fragment: TabID.Plugins},

View file

@ -0,0 +1,9 @@
<ng-container *ngIf="logs$ | async as items">
<virtual-scroller #scroll [items]="items" [bufferAmount]="1">
<div class="grid row g-0" #container>
<div class="card col-auto mt-2 mb-2" *ngFor="let item of scroll.viewPortItems; index as i">
{{item.timestamp | date}} [{{item.level}}] {{item.message}}
</div>
</div>
</virtual-scroller>
</ng-container>

View file

@ -0,0 +1,66 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { HubConnection, HubConnectionBuilder } from '@microsoft/signalr';
import { BehaviorSubject, ReplaySubject, Subject, take } from 'rxjs';
import { AccountService } from 'src/app/_services/account.service';
import { environment } from 'src/environments/environment';
interface LogMessage {
timestamp: string;
level: 'Information' | 'Debug' | 'Warning' | 'Error';
message: string;
exception: string;
}
@Component({
selector: 'app-manage-logs',
templateUrl: './manage-logs.component.html',
styleUrls: ['./manage-logs.component.scss']
})
export class ManageLogsComponent implements OnInit, OnDestroy {
hubUrl = environment.hubUrl;
private hubConnection!: HubConnection;
logsSource = new BehaviorSubject<LogMessage[]>([]);
public logs$ = this.logsSource.asObservable();
constructor(private accountService: AccountService) { }
ngOnInit(): void {
this.accountService.currentUser$.pipe(take(1)).subscribe(user => {
if (user) {
this.hubConnection = new HubConnectionBuilder()
.withUrl(this.hubUrl + 'logs', {
accessTokenFactory: () => user.token
})
.withAutomaticReconnect()
.build();
console.log('Starting log connection');
this.hubConnection
.start()
.catch(err => console.error(err));
this.hubConnection.on('SendLogAsObject', resp => {
const payload = resp.arguments[0] as LogMessage;
const logMessage = {timestamp: payload.timestamp, level: payload.level, message: payload.message, exception: payload.exception};
// TODO: It might be better to just have a queue to show this
const values = this.logsSource.getValue();
values.push(logMessage);
this.logsSource.next(values);
});
}
});
}
ngOnDestroy(): void {
// unsubscrbe from signalr connection
if (this.hubConnection) {
this.hubConnection.stop().catch(err => console.error(err));
console.log('Stoping log connection');
}
}
}

View file

@ -1,6 +1,6 @@
<div class="container-fluid">
<form [formGroup]="settingsForm" *ngIf="serverSettings !== undefined">
<p class="text-warning pt-2">Port, Logging Level, and Swagger require a manual restart of Kavita to take effect.</p>
<p class="text-warning pt-2">Port and Swagger require a manual restart of Kavita to take effect.</p>
<div class="mb-3">
<label for="settings-cachedir" class="form-label">Cache Directory</label>&nbsp;<i class="fa fa-info-circle" placement="right" [ngbTooltip]="cacheDirectoryTooltip" role="button" tabindex="0"></i>
<ng-template #cacheDirectoryTooltip>Where the server place temporary files when reading. This will be cleaned up on a regular basis.</ng-template>
@ -48,8 +48,8 @@
<div class="col-md-4 col-sm-12">
<label for="logging-level-port" class="form-label">Logging Level</label>&nbsp;<i class="fa fa-info-circle" placement="right" [ngbTooltip]="loggingLevelTooltip" role="button" tabindex="0"></i>
<ng-template #loggingLevelTooltip>Use debug to help identify issues. Debug can eat up a lot of disk space. Requires restart to take effect.</ng-template>
<span class="visually-hidden" id="logging-level-port-help">Port the server listens on. Requires restart to take effect.</span>
<ng-template #loggingLevelTooltip>Use debug to help identify issues. Debug can eat up a lot of disk space.</ng-template>
<span class="visually-hidden" id="logging-level-port-help">Port the server listens on.</span>
<select id="logging-level-port" aria-describedby="logging-level-port-help" class="form-select" aria-describedby="settings-tasks-scan-help" formControlName="loggingLevel">
<option *ngFor="let level of logLevels" [value]="level">{{level | titlecase}}</option>
</select>