Commit /logs function dirs. not commited before, because of .gitignore.
This commit is contained in:
parent
c155508d25
commit
7d1d5a213c
10 changed files with 477 additions and 0 deletions
18
src/main/webapp/app/admin/logs/log.model.ts
Normal file
18
src/main/webapp/app/admin/logs/log.model.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
export type Level = 'TRACE' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'OFF';
|
||||
|
||||
export interface Logger {
|
||||
configuredLevel: Level | null;
|
||||
effectiveLevel: Level;
|
||||
}
|
||||
|
||||
export interface LoggersResponse {
|
||||
levels: Level[];
|
||||
loggers: { [key: string]: Logger };
|
||||
}
|
||||
|
||||
export class Log {
|
||||
constructor(
|
||||
public name: string,
|
||||
public level: Level,
|
||||
) {}
|
||||
}
|
82
src/main/webapp/app/admin/logs/logs.component.html
Normal file
82
src/main/webapp/app/admin/logs/logs.component.html
Normal file
|
@ -0,0 +1,82 @@
|
|||
@defer (when loggers() && !isLoading()) {
|
||||
<div class="table-responsive">
|
||||
<h2 id="logs-page-heading" data-cy="logsPageHeading" jhiTranslate="logs.title">Logs</h2>
|
||||
|
||||
<p jhiTranslate="logs.nbloggers" [translateValues]="{ total: loggers()?.length }">Existem {{ loggers()?.length }} loggers.</p>
|
||||
|
||||
<span jhiTranslate="logs.filter">Filtro</span>
|
||||
<input type="text" [ngModel]="filter()" (ngModelChange)="filter.set($event)" class="form-control" />
|
||||
|
||||
<table class="table table-sm table-striped table-bordered" aria-describedby="logs-page-heading">
|
||||
<thead>
|
||||
<tr jhiSort [sortState]="sortState" (sortChange)="sortState.set($event)">
|
||||
<th jhiSortBy="name" scope="col"><span jhiTranslate="logs.table.name">Nome</span> <fa-icon icon="sort"></fa-icon></th>
|
||||
<th jhiSortBy="level" scope="col"><span jhiTranslate="logs.table.level">Nível</span> <fa-icon icon="sort"></fa-icon></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@for (logger of filteredAndOrderedLoggers(); track $index) {
|
||||
<tr>
|
||||
<td>
|
||||
<small>{{ logger.name | slice: 0 : 140 }}</small>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
(click)="changeLevel(logger.name, 'TRACE')"
|
||||
[ngClass]="logger.level === 'TRACE' ? 'btn-primary' : 'btn-light'"
|
||||
class="btn btn-sm"
|
||||
>
|
||||
TRACE
|
||||
</button>
|
||||
|
||||
<button
|
||||
(click)="changeLevel(logger.name, 'DEBUG')"
|
||||
[ngClass]="logger.level === 'DEBUG' ? 'btn-success' : 'btn-light'"
|
||||
class="btn btn-sm"
|
||||
>
|
||||
DEBUG
|
||||
</button>
|
||||
|
||||
<button
|
||||
(click)="changeLevel(logger.name, 'INFO')"
|
||||
[ngClass]="logger.level === 'INFO' ? 'btn-info' : 'btn-light'"
|
||||
class="btn btn-sm"
|
||||
>
|
||||
INFO
|
||||
</button>
|
||||
|
||||
<button
|
||||
(click)="changeLevel(logger.name, 'WARN')"
|
||||
[ngClass]="logger.level === 'WARN' ? 'btn-warning' : 'btn-light'"
|
||||
class="btn btn-sm"
|
||||
>
|
||||
WARN
|
||||
</button>
|
||||
|
||||
<button
|
||||
(click)="changeLevel(logger.name, 'ERROR')"
|
||||
[ngClass]="logger.level === 'ERROR' ? 'btn-danger' : 'btn-light'"
|
||||
class="btn btn-sm"
|
||||
>
|
||||
ERROR
|
||||
</button>
|
||||
|
||||
<button
|
||||
(click)="changeLevel(logger.name, 'OFF')"
|
||||
[ngClass]="logger.level === 'OFF' ? 'btn-secondary' : 'btn-light'"
|
||||
class="btn btn-sm"
|
||||
>
|
||||
OFF
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
} @loading {
|
||||
<div class="d-flex justify-content-center me-3">
|
||||
<div class="spinner-border"></div>
|
||||
</div>
|
||||
}
|
82
src/main/webapp/app/admin/logs/logs.component.spec.ts
Normal file
82
src/main/webapp/app/admin/logs/logs.component.spec.ts
Normal file
|
@ -0,0 +1,82 @@
|
|||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { of } from 'rxjs';
|
||||
|
||||
import LogsComponent from './logs.component';
|
||||
import { LogsService } from './logs.service';
|
||||
import { Log, LoggersResponse } from './log.model';
|
||||
|
||||
describe('LogsComponent', () => {
|
||||
let comp: LogsComponent;
|
||||
let fixture: ComponentFixture<LogsComponent>;
|
||||
let service: LogsService;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [HttpClientTestingModule, LogsComponent],
|
||||
providers: [LogsService],
|
||||
})
|
||||
.overrideTemplate(LogsComponent, '')
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LogsComponent);
|
||||
comp = fixture.componentInstance;
|
||||
service = TestBed.inject(LogsService);
|
||||
});
|
||||
|
||||
describe('OnInit', () => {
|
||||
it('should set all default values correctly', () => {
|
||||
expect(comp.filter()).toBe('');
|
||||
expect(comp.sortState().predicate).toBe('name');
|
||||
expect(comp.sortState().order).toBe('asc');
|
||||
});
|
||||
|
||||
it('Should call load all on init', () => {
|
||||
// GIVEN
|
||||
const log = new Log('main', 'WARN');
|
||||
jest.spyOn(service, 'findAll').mockReturnValue(
|
||||
of({
|
||||
loggers: {
|
||||
main: {
|
||||
effectiveLevel: 'WARN',
|
||||
},
|
||||
},
|
||||
} as unknown as LoggersResponse),
|
||||
);
|
||||
|
||||
// WHEN
|
||||
comp.ngOnInit();
|
||||
|
||||
// THEN
|
||||
expect(service.findAll).toHaveBeenCalled();
|
||||
expect(comp.loggers()?.[0]).toEqual(expect.objectContaining(log));
|
||||
});
|
||||
});
|
||||
|
||||
describe('change log level', () => {
|
||||
it('should change log level correctly', () => {
|
||||
// GIVEN
|
||||
const log = new Log('main', 'ERROR');
|
||||
jest.spyOn(service, 'changeLevel').mockReturnValue(of({}));
|
||||
jest.spyOn(service, 'findAll').mockReturnValue(
|
||||
of({
|
||||
loggers: {
|
||||
main: {
|
||||
effectiveLevel: 'ERROR',
|
||||
},
|
||||
},
|
||||
} as unknown as LoggersResponse),
|
||||
);
|
||||
|
||||
// WHEN
|
||||
comp.changeLevel('main', 'ERROR');
|
||||
|
||||
// THEN
|
||||
expect(service.changeLevel).toHaveBeenCalled();
|
||||
expect(service.findAll).toHaveBeenCalled();
|
||||
expect(comp.loggers()?.[0]).toEqual(expect.objectContaining(log));
|
||||
});
|
||||
});
|
||||
});
|
61
src/main/webapp/app/admin/logs/logs.component.ts
Normal file
61
src/main/webapp/app/admin/logs/logs.component.ts
Normal file
|
@ -0,0 +1,61 @@
|
|||
import { Component, computed, inject, OnInit, signal } from '@angular/core';
|
||||
import { finalize } from 'rxjs/operators';
|
||||
|
||||
import SharedModule from 'app/shared/shared.module';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { SortDirective, SortByDirective, sortStateSignal, SortService } from 'app/shared/sort';
|
||||
import { Log, LoggersResponse, Level } from './log.model';
|
||||
import { LogsService } from './logs.service';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'jhi-logs',
|
||||
templateUrl: './logs.component.html',
|
||||
imports: [SharedModule, FormsModule, SortDirective, SortByDirective],
|
||||
})
|
||||
export default class LogsComponent implements OnInit {
|
||||
loggers = signal<Log[] | undefined>(undefined);
|
||||
isLoading = signal(false);
|
||||
filter = signal('');
|
||||
sortState = sortStateSignal({ predicate: 'name', order: 'asc' });
|
||||
filteredAndOrderedLoggers = computed<Log[] | undefined>(() => {
|
||||
let data = this.loggers() ?? [];
|
||||
const filter = this.filter();
|
||||
if (filter) {
|
||||
data = data.filter(logger => logger.name.toLowerCase().includes(filter.toLowerCase()));
|
||||
}
|
||||
|
||||
const { order, predicate } = this.sortState();
|
||||
if (order && predicate) {
|
||||
data = data.sort(this.sortService.startSort({ order, predicate }, { predicate: 'name', order: 'asc' }));
|
||||
}
|
||||
return data;
|
||||
});
|
||||
|
||||
private logsService = inject(LogsService);
|
||||
private sortService = inject(SortService);
|
||||
|
||||
ngOnInit(): void {
|
||||
this.findAndExtractLoggers();
|
||||
}
|
||||
|
||||
changeLevel(name: string, level: Level): void {
|
||||
this.logsService.changeLevel(name, level).subscribe(() => this.findAndExtractLoggers());
|
||||
}
|
||||
|
||||
private findAndExtractLoggers(): void {
|
||||
this.isLoading.set(true);
|
||||
this.logsService
|
||||
.findAll()
|
||||
.pipe(
|
||||
finalize(() => {
|
||||
this.isLoading.set(false);
|
||||
}),
|
||||
)
|
||||
.subscribe({
|
||||
next: (response: LoggersResponse) =>
|
||||
this.loggers.set(Object.entries(response.loggers).map(([key, logger]) => new Log(key, logger.effectiveLevel))),
|
||||
error: () => this.loggers.set([]),
|
||||
});
|
||||
}
|
||||
}
|
31
src/main/webapp/app/admin/logs/logs.service.spec.ts
Normal file
31
src/main/webapp/app/admin/logs/logs.service.spec.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
|
||||
|
||||
import { LogsService } from './logs.service';
|
||||
|
||||
describe('Logs Service', () => {
|
||||
let service: LogsService;
|
||||
let httpMock: HttpTestingController;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [HttpClientTestingModule],
|
||||
});
|
||||
|
||||
service = TestBed.inject(LogsService);
|
||||
httpMock = TestBed.inject(HttpTestingController);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
httpMock.verify();
|
||||
});
|
||||
|
||||
describe('Service methods', () => {
|
||||
it('should change log level', () => {
|
||||
service.changeLevel('main', 'ERROR').subscribe();
|
||||
|
||||
const req = httpMock.expectOne({ method: 'POST' });
|
||||
expect(req.request.body).toEqual({ configuredLevel: 'ERROR' });
|
||||
});
|
||||
});
|
||||
});
|
20
src/main/webapp/app/admin/logs/logs.service.ts
Normal file
20
src/main/webapp/app/admin/logs/logs.service.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { inject, Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { ApplicationConfigService } from 'app/core/config/application-config.service';
|
||||
import { LoggersResponse, Level } from './log.model';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class LogsService {
|
||||
private http = inject(HttpClient);
|
||||
private applicationConfigService = inject(ApplicationConfigService);
|
||||
|
||||
changeLevel(name: string, configuredLevel: Level): Observable<{}> {
|
||||
return this.http.post(this.applicationConfigService.getEndpointFor(`management/loggers/${name}`), { configuredLevel });
|
||||
}
|
||||
|
||||
findAll(): Observable<LoggersResponse> {
|
||||
return this.http.get<LoggersResponse>(this.applicationConfigService.getEndpointFor('management/loggers'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
:host .modal-body {
|
||||
overflow-y: auto;
|
||||
max-height: 500px;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<div class="modal-header">
|
||||
<h4 class="modal-title" jhiTranslate="resilientApp.inputDataUploadLogLogsDialog.title">Ocorrências na integração de dados</h4>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
|
||||
@if (inputDataUploadLogs?.length === 0) {
|
||||
<div class="alert alert-warning" id="no-result">
|
||||
<span jhiTranslate="resilientApp.inputDataUploadLog.home.notFound">Nenhum Input Data Upload Logs encontrado</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (inputDataUploadLogs && inputDataUploadLogs.length > 0) {
|
||||
<div class="table-responsive table-entities" id="entities">
|
||||
<table class="table table-striped" aria-describedby="page-heading">
|
||||
<tbody>
|
||||
@for (inputDataUploadLog of inputDataUploadLogs; track trackId) {
|
||||
<tr data-cy="entityTable">
|
||||
<td>{{ inputDataUploadLog.logMessage }}</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal" (click)="cancel()">
|
||||
<fa-icon icon="ban"></fa-icon> <span jhiTranslate="resilientApp.inputDataUploadLogLogsDialog.action.close">Fechar</span>
|
||||
</button>
|
||||
</div>
|
|
@ -0,0 +1,64 @@
|
|||
jest.mock('@ng-bootstrap/ng-bootstrap');
|
||||
|
||||
import { ComponentFixture, TestBed, inject, fakeAsync, tick } from '@angular/core/testing';
|
||||
import { HttpResponse } from '@angular/common/http';
|
||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
import { InputDataUploadLogService } from '../service/input-data-upload-log.service';
|
||||
|
||||
import { InputDataUploadLogLogsDialogComponent } from './input-data-upload-log-logs-dialog.component';
|
||||
|
||||
describe('InputDataUploadLog Management Logs Component', () => {
|
||||
let comp: InputDataUploadLogLogsDialogComponent;
|
||||
let fixture: ComponentFixture<InputDataUploadLogLogsDialogComponent>;
|
||||
let service: InputDataUploadLogService;
|
||||
let mockActiveModal: NgbActiveModal;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [HttpClientTestingModule, InputDataUploadLoglogsDialogComponent],
|
||||
providers: [NgbActiveModal],
|
||||
})
|
||||
.overrideTemplate(InputDataUploadLogLogsDialogComponent, '')
|
||||
.compileComponents();
|
||||
fixture = TestBed.createComponent(InputDataUploadLogLogsDialogComponent);
|
||||
comp = fixture.componentInstance;
|
||||
service = TestBed.inject(InputDataUploadLogService);
|
||||
mockActiveModal = TestBed.inject(NgbActiveModal);
|
||||
});
|
||||
|
||||
/*
|
||||
describe('confirmDelete', () => {
|
||||
it('Should call delete service on confirmDelete', inject(
|
||||
[],
|
||||
fakeAsync(() => {
|
||||
// GIVEN
|
||||
jest.spyOn(service, 'delete').mockReturnValue(of(new HttpResponse({ body: {} })));
|
||||
|
||||
// WHEN
|
||||
comp.confirmDelete(123);
|
||||
tick();
|
||||
|
||||
// THEN
|
||||
expect(service.delete).toHaveBeenCalledWith(123);
|
||||
expect(mockActiveModal.close).toHaveBeenCalledWith('deleted');
|
||||
}),
|
||||
));
|
||||
|
||||
it('Should not call delete service on clear', () => {
|
||||
// GIVEN
|
||||
jest.spyOn(service, 'delete');
|
||||
|
||||
// WHEN
|
||||
comp.cancel();
|
||||
|
||||
// THEN
|
||||
expect(service.delete).not.toHaveBeenCalled();
|
||||
expect(mockActiveModal.close).not.toHaveBeenCalled();
|
||||
expect(mockActiveModal.dismiss).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
*/
|
||||
});
|
|
@ -0,0 +1,83 @@
|
|||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { sortStateSignal, SortDirective, SortByDirective, type SortState, SortService } from 'app/shared/sort';
|
||||
import { combineLatest, filter, Observable, Subscription, tap } from 'rxjs';
|
||||
|
||||
import SharedModule from 'app/shared/shared.module';
|
||||
import { DurationPipe, FormatMediumDatetimePipe, FormatMediumDatePipe } from 'app/shared/date';
|
||||
import { ITEM_DELETED_EVENT } from 'app/config/navigation.constants';
|
||||
import { IInputDataUpload } from 'app/entities/input-data-upload/input-data-upload.model';
|
||||
import { IInputDataUploadLog } from '../input-data-upload-log.model';
|
||||
import { EntityArrayResponseType, InputDataUploadLogService } from '../service/input-data-upload-log.service';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
templateUrl: './input-data-upload-log-logs-dialog.component.html',
|
||||
styleUrl: './input-data-upload-log-logs-dialog.component.css',
|
||||
imports: [
|
||||
SharedModule,
|
||||
FormsModule,
|
||||
SortDirective,
|
||||
SortByDirective,
|
||||
DurationPipe,
|
||||
FormatMediumDatetimePipe,
|
||||
FormatMediumDatePipe,
|
||||
],
|
||||
})
|
||||
export class InputDataUploadLogLogsDialogComponent implements OnInit {
|
||||
inputDataUpload?: IInputDataUpload;
|
||||
inputDataUploadLogs?: IInputDataUploadLog[];
|
||||
isLoading = false;
|
||||
|
||||
sortState = sortStateSignal({});
|
||||
|
||||
protected sortService = inject(SortService);
|
||||
protected inputDataUploadLogService = inject(InputDataUploadLogService);
|
||||
protected activeModal = inject(NgbActiveModal);
|
||||
|
||||
trackId = (_index: number, item: IInputDataUploadLog): number => this.inputDataUploadLogService.getEntityIdentifier(item);
|
||||
|
||||
setInputDataUpload(inputDataUpload: IInputDataUpload) {
|
||||
this.inputDataUpload = inputDataUpload;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (this.inputDataUpload) {
|
||||
this.load();
|
||||
}
|
||||
}
|
||||
|
||||
cancel(): void {
|
||||
this.activeModal.dismiss();
|
||||
}
|
||||
|
||||
load(): void {
|
||||
this.queryBackend().subscribe({
|
||||
next: (res: EntityArrayResponseType) => {
|
||||
this.onResponseSuccess(res);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
protected onResponseSuccess(response: EntityArrayResponseType): void {
|
||||
const dataFromBody = this.fillComponentAttributesFromResponseBody(response.body);
|
||||
this.inputDataUploadLogs = this.refineData(dataFromBody);
|
||||
}
|
||||
|
||||
protected refineData(data: IInputDataUploadLog[]): IInputDataUploadLog[] {
|
||||
const { predicate, order } = this.sortState();
|
||||
return predicate && order ? data.sort(this.sortService.startSort({ predicate, order })) : data;
|
||||
}
|
||||
|
||||
protected fillComponentAttributesFromResponseBody(data: IInputDataUploadLog[] | null): IInputDataUploadLog[] {
|
||||
return data ?? [];
|
||||
}
|
||||
|
||||
protected queryBackend(): Observable<EntityArrayResponseType> {
|
||||
this.isLoading = true;
|
||||
|
||||
return this.inputDataUploadLogService.findByOwner(this.inputDataUpload?.id ?? 0).pipe(tap(() => (this.isLoading = false)));
|
||||
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue