Skip to content

Commit

Permalink
feat: logs in connectors
Browse files Browse the repository at this point in the history
  • Loading branch information
ceedjy authored and burgerni10 committed Jan 6, 2025
1 parent f8d60e5 commit aa15acb
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,17 @@ <h1 id="title" translate="history-query.title" [translateParams]="{ name: histor
</oib-box>
<!-- Items -->
<oib-history-query-items [inMemory]="false" [historyQuery]="historyQuery" [southManifest]="southManifest"></oib-history-query-items>
<!-- Logs -->
<oib-box>
<ng-template oibBoxTitle>
<div class="d-flex justify-content-between align-items-center">
<div>
<span id="logs-title">{{ 'logs.title' | translate }}</span>
</div>
</div>
</ng-template>
</oib-box>
<oib-logs [scopeId]="historyQueryId" scopeType="history-query"></oib-logs>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ class HistoryQueryDisplayComponentTester extends ComponentTester<HistoryQueryDet
get items() {
return this.elements('tbody tr.south-item');
}

get historyQueryLogs() {
return this.elements('#logs-title');
}
}

describe('HistoryQueryDisplayComponent', () => {
Expand Down Expand Up @@ -239,6 +243,11 @@ describe('HistoryQueryDisplayComponent', () => {
expect(item.elements('td')[2]).toContainText('sql');
});

it('should display logs', () => {
tester.detectChanges();
expect(tester.historyQueryLogs.length).toBe(1);
});

it('should test north connection', () => {
tester.componentInstance.northManifest = northManifest;
tester.componentInstance.historyQuery = historyQuery;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { EngineService } from '../../services/engine.service';
import { ClipboardModule } from '@angular/cdk/clipboard';
import { ModalService } from '../../shared/modal.service';
import { TestConnectionResultModalComponent } from '../../shared/test-connection-result-modal/test-connection-result-modal.component';
import { LogsComponent } from '../../logs/logs.component';

@Component({
selector: 'oib-history-query-detail',
Expand All @@ -53,7 +54,8 @@ import { TestConnectionResultModalComponent } from '../../shared/test-connection
HistoryMetricsComponent,
SouthMetricsComponent,
AsyncPipe,
ClipboardModule
ClipboardModule,
LogsComponent
],
templateUrl: './history-query-detail.component.html',
styleUrl: './history-query-detail.component.scss',
Expand All @@ -76,6 +78,7 @@ export class HistoryQueryDetailComponent implements OnInit, OnDestroy {
historyStream: EventSource | null = null;
state = new ObservableState();
oibusInfo: OIBusInfo | null = null;
historyQueryId: string | null = null;

constructor(
private historyQueryService: HistoryQueryService,
Expand All @@ -99,9 +102,10 @@ export class HistoryQueryDetailComponent implements OnInit, OnDestroy {
this.route.paramMap
.pipe(
switchMap(params => {
const paramHistoryQueryId = params.get('historyQueryId') || '';
if (paramHistoryQueryId) {
return this.historyQueryService.get(paramHistoryQueryId);
this.historyQueryId = params.get('historyQueryId') || '';

if (this.historyQueryId) {
return this.historyQueryService.get(this.historyQueryId);
}
return of(null);
}),
Expand Down
116 changes: 66 additions & 50 deletions frontend/src/app/logs/logs.component.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
<div class="oib-padded-container">
<div [ngClass]="{ 'oib-padded-container': !this.scopeId && !this.scopeType }">
<div class="oib-header-container">
<div class="row mb-2">
<div class="col d-flex">
<div class="oib-block-title">
<img class="oib-title-image pt-2" src="/home/logs.svg" />
@if (!this.scopeId && !this.scopeType) {
<div class="row mb-2">
<div class="col d-flex">
<div class="oib-block-title">
<img class="oib-title-image pt-2" src="/home/logs.svg" />
</div>
<h1 class="oib-title">{{ 'logs.title' | translate }}</h1>
</div>
<h1 class="oib-title">{{ 'logs.title' | translate }}</h1>
</div>
</div>
}
<div>
<form class="px-3 mb-4 oib-search-form" id="logs-form" [formGroup]="searchForm" (ngSubmit)="triggerSearch()">
<div class="row gx-2 py-3">
Expand All @@ -21,46 +23,57 @@ <h1 class="oib-title">{{ 'logs.title' | translate }}</h1>
<oib-datetimepicker formControlName="end" id="end"></oib-datetimepicker>
<val-errors [control]="searchForm"></val-errors>
</div>
<label for="levels" class="col-auto col-form-label" translate="logs.search.levels"></label>
<div class="col-1">
<oib-multi-select formControlName="levels" id="levels">
@for (level of levels; track level) {
<oib-multi-select-option [value]="level" [label]="level | logLevelsEnum"></oib-multi-select-option>
}
</oib-multi-select>
</div>

<label for="scope-types" class="col-auto col-form-label" translate="logs.search.scope-type"></label>
<div class="col-2">
<oib-multi-select formControlName="scopeTypes" id="scope-types">
@for (scopeType of scopeTypes; track scopeType) {
<oib-multi-select-option [value]="scopeType" [label]="scopeType | scopeTypesEnum"></oib-multi-select-option>
}
</oib-multi-select>
</div>
@if (!this.scopeId && !this.scopeType) {
<label for="levels" class="col-auto col-form-label" translate="logs.search.levels"></label>
<div class="col-1">
<oib-multi-select formControlName="levels" id="levels">
@for (level of levels; track level) {
<oib-multi-select-option [value]="level" [label]="level | logLevelsEnum"></oib-multi-select-option>
}
</oib-multi-select>
</div>
<label for="scope-types" class="col-auto col-form-label" translate="logs.search.scope-type"></label>
<div class="col-2">
<oib-multi-select formControlName="scopeTypes" id="scope-types">
@for (scopeType of scopeTypes; track scopeType) {
<oib-multi-select-option [value]="scopeType" [label]="scopeType | scopeTypesEnum"></oib-multi-select-option>
}
</oib-multi-select>
</div>
}
</div>
<div class="row gx-2 py-3">
<label for="scope-ids" class="col-auto col-form-label" translate="logs.search.scope"></label>
<div class="col-2">
<input
id="scope-ids"
class="form-control"
formControlName="scopeIds"
[ngbTypeahead]="scopeTypeahead"
[resultFormatter]="scopeFormatter"
[inputFormatter]="scopeFormatter"
[editable]="false"
(selectItem)="selectScope($event)"
/>
<div [style.margin-top.rem]="selectedScopes.length ? -0.75 : 0">
@for (scope of selectedScopes; track scope.scopeId) {
<oib-pill type="secondary" [removable]="true" (removed)="removeScope(scope)"> {{ scope.scopeName }} </oib-pill>
}
@if (!this.scopeId && !this.scopeType) {
<label for="scope-ids" class="col-auto col-form-label" translate="logs.search.scope"></label>
<div class="col-2">
<input
id="scope-ids"
class="form-control"
formControlName="scopeIds"
[ngbTypeahead]="scopeTypeahead"
[resultFormatter]="scopeFormatter"
[inputFormatter]="scopeFormatter"
[editable]="false"
(selectItem)="selectScope($event)"
/>
<div [style.margin-top.rem]="selectedScopes.length ? -0.75 : 0">
@for (scope of selectedScopes; track scope.scopeId) {
<oib-pill type="secondary" [removable]="true" (removed)="removeScope(scope)"> {{ scope.scopeName }} </oib-pill>
}
</div>
</div>
</div>

} @else {
<label for="levels" class="col-auto col-form-label" translate="logs.search.levels"></label>
<div class="col-2">
<oib-multi-select formControlName="levels" id="levels">
@for (level of levels; track level) {
<oib-multi-select-option [value]="level" [label]="level | logLevelsEnum"></oib-multi-select-option>
}
</oib-multi-select>
</div>
}
<label for="message-content" class="col-auto col-form-label" translate="logs.search.message-content"></label>
<div class="col-8">
<div [ngClass]="!this.scopeId && !this.scopeType ? 'col-8' : 'col-7'">
<input type="text" class="form-control" id="message-content" formControlName="messageContent" />
</div>

Expand Down Expand Up @@ -89,25 +102,28 @@ <h1 class="oib-title">{{ 'logs.title' | translate }}</h1>
@if (logs.totalElements !== 0) {
<div class="table-container">
<table class="table table-sm table-hover oib-table-logs">
<thead>
<thead [ngClass]="{ light: this.scopeId && this.scopeType }">
<tr>
<th style="width: 1%"></th>
<th translate="logs.date"></th>
<th translate="logs.scope-type" style="width: 8%"></th>
<th translate="logs.scope" style="width: 4%"></th>
<th translate="logs.message"></th>
@if (!this.scopeId && !this.scopeType) {
<th translate="logs.scope-type" style="width: 8%"></th>
<th translate="logs.scope" style="width: 4%"></th>
}
<th [ngClass]="{ 'w-50': this.scopeId && this.scopeType }" translate="logs.message"></th>
</tr>
</thead>
<tbody>
@for (log of logs.content; track log) {
<tr class="data">
<td>
<!-- need to not be "display: inline" -->
<span style="display: block" [class]="getLevelClass(log.level)"></span>
</td>
<td class="text-nowrap">{{ log.timestamp | datetime: 'mediumWithSeconds' }}</td>
<td>{{ log.scopeType | scopeTypesEnum }}</td>
<td>{{ log.scopeName }}</td>
@if (!this.scopeId && !this.scopeType) {
<td>{{ log.scopeType | scopeTypesEnum }}</td>
<td>{{ log.scopeName }}</td>
}
<td class="text-break">{{ log.message }}</td>
</tr>
}
Expand Down
29 changes: 22 additions & 7 deletions frontend/src/app/logs/logs.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, inject, OnDestroy, OnInit } from '@angular/core';
import { Component, inject, OnDestroy, OnInit, Input } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { ActivatedRoute, Router } from '@angular/router';
import { PageLoader } from '../shared/page-loader.service';
Expand Down Expand Up @@ -37,6 +37,7 @@ import { TYPEAHEAD_DEBOUNCE_TIME } from '../shared/typeahead';
import { NgbTypeahead, NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap';
import { PillComponent } from '../shared/pill/pill.component';
import { LegendComponent } from '../shared/legend/legend.component';
import { NgClass } from '@angular/common';

@Component({
selector: 'oib-logs',
Expand All @@ -53,13 +54,17 @@ import { LegendComponent } from '../shared/legend/legend.component';
ScopeTypesEnumPipe,
NgbTypeahead,
PillComponent,
LegendComponent
LegendComponent,
NgClass
],
templateUrl: './logs.component.html',
styleUrl: './logs.component.scss',
providers: [PageLoader]
})
export class LogsComponent implements OnInit, OnDestroy {
@Input() scopeId: string | null = null;
@Input() scopeType: ScopeType | null = null;

readonly searchForm = inject(NonNullableFormBuilder).group(
{
messageContent: null as string | null,
Expand Down Expand Up @@ -121,6 +126,10 @@ export class LogsComponent implements OnInit, OnDestroy {
}

ngOnInit(): void {
if (this.scopeId !== null && this.scopeType !== null) {
this.searchForm.controls.scopeTypes.disable();
this.searchForm.controls.scopeIds.disable();
}
const queryScopeIds = this.route.snapshot.queryParamMap.getAll('scopeIds');
if (queryScopeIds.length > 0) {
combineLatest(queryScopeIds.map(scopeId => this.logService.getScopeById(scopeId))).subscribe(selectedScopes => {
Expand Down Expand Up @@ -155,8 +164,15 @@ export class LogsComponent implements OnInit, OnDestroy {
const now = DateTime.now().endOf('minute');
const queryParamMap = route.snapshot.queryParamMap;
const messageContent = queryParamMap.get('messageContent');
const scopeTypes = queryParamMap.getAll('scopeTypes');
const scopeIds = queryParamMap.getAll('scopeIds');
let scopeTypes = null;
let scopeIds = null;
if (this.scopeId !== null && this.scopeType !== null) {
scopeTypes = [this.scopeType];
scopeIds = [this.scopeId];
} else {
scopeTypes = queryParamMap.getAll('scopeTypes');
scopeIds = queryParamMap.getAll('scopeIds');
}
const start = queryParamMap.get('start') ?? now.minus({ days: 1 }).toISO();
const end = queryParamMap.get('end');
const levels = queryParamMap.getAll('levels');
Expand All @@ -174,11 +190,10 @@ export class LogsComponent implements OnInit, OnDestroy {
end: formValue.end!,
messageContent: formValue.messageContent!,
levels: formValue.levels!,
scopeTypes: formValue.scopeTypes!,
scopeIds: this.selectedScopes!.map(scope => scope.scopeId),
scopeTypes: this.scopeType ? [this.scopeType] : formValue.scopeTypes!,
scopeIds: this.scopeId ? [this.scopeId] : this.selectedScopes!.map(scope => scope.scopeId),
page: 0
};

this.router.navigate(['.'], { queryParams: criteria, relativeTo: this.route });
}

Expand Down
11 changes: 11 additions & 0 deletions frontend/src/app/north/north-detail/north-detail.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,17 @@ <h1 id="title" translate="north.title" [translateParams]="{ name: northConnector
</oib-box>
<!-- subscription -->
<oib-north-subscriptions [northConnector]="northConnector"></oib-north-subscriptions>
<!-- Logs -->
<oib-box>
<ng-template oibBoxTitle>
<div class="d-flex justify-content-between align-items-center">
<div>
<span id="logs-title">{{ 'logs.title' | translate }}</span>
</div>
</div>
</ng-template>
</oib-box>
<oib-logs [scopeId]="northId" scopeType="north"></oib-logs>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ class NorthDetailComponentTester extends ComponentTester<NorthDetailComponent> {
get northSettings() {
return this.elements('tbody.north-settings tr');
}

get northLogs() {
return this.elements('#logs-title');
}
}

describe('NorthDetailComponent', () => {
Expand Down Expand Up @@ -150,6 +154,11 @@ describe('NorthDetailComponent', () => {
expect(settings[1]).toContainText('url');
});

it('should display logs', () => {
tester.detectChanges();
expect(tester.northLogs.length).toBe(1);
});

it('should stop north', () => {
tester.detectChanges();
tester.toggleButton.click();
Expand Down
11 changes: 7 additions & 4 deletions frontend/src/app/north/north-detail/north-detail.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { ModalService } from '../../shared/modal.service';
import { BooleanEnumPipe } from '../../shared/boolean-enum.pipe';
import { PipeProviderService } from '../../shared/form/pipe-provider.service';
import { EngineService } from '../../services/engine.service';
import { LogsComponent } from '../../logs/logs.component';

@Component({
selector: 'oib-north-detail',
Expand All @@ -38,7 +39,8 @@ import { EngineService } from '../../services/engine.service';
BoxTitleDirective,
DurationPipe,
EnabledEnumPipe,
ClipboardModule
ClipboardModule,
LogsComponent
],
templateUrl: './north-detail.component.html',
styleUrl: './north-detail.component.scss',
Expand All @@ -52,6 +54,7 @@ export class NorthDetailComponent implements OnInit, OnDestroy {
connectorStream: EventSource | null = null;
connectorMetrics: NorthConnectorMetrics | null = null;
oibusInfo: OIBusInfo | null = null;
northId: string | null = null;

constructor(
private windowService: WindowService,
Expand All @@ -74,10 +77,10 @@ export class NorthDetailComponent implements OnInit, OnDestroy {
this.route.paramMap
.pipe(
switchMap(params => {
const paramNorthId = params.get('northId');
this.northId = params.get('northId');

if (paramNorthId) {
return this.northConnectorService.get(paramNorthId);
if (this.northId) {
return this.northConnectorService.get(this.northId);
}
return of(null);
}),
Expand Down
Loading

0 comments on commit aa15acb

Please sign in to comment.