feat(oggui): soporte de múltiples SYSLOG_IDENTIFIER en visor de logs de disco
oggui-debian-package/pipeline/head This commit looks good Details
testing/ogGui-multibranch/pipeline/head There was a failure building this commit Details

- StatusLogsComponent: @Input identifiers[] en lugar de identifier string,
  parseo de entries JSON estructurado con formato [timestamp] ID: mensaje
- Templates ogboot, ogdhcp, ogrepository, ogcore-status: identifiers correctos
  por componente y host basado en IP en lugar de nombre del servidor
- Añadidos métodos getSelectedXxxIp() en ogboot, ogdhcp y ogrepository status
pull/93/head^2
Nicolas Arenas 2026-05-14 21:38:35 +02:00
parent 59067ee94c
commit 647fa5079e
8 changed files with 51 additions and 16 deletions

View File

@ -45,8 +45,8 @@
<div id="ogboot-logs-section">
<app-status-logs
[title]="'ogbootLogs'"
[identifier]="'ogboot'"
[host]="getSelectedBootServerName()"
[identifiers]="['ogboot', 'tftpd-hpa']"
[host]="getSelectedBootServerIp()"
[oglogUrl]="getBootServerIframeUrl()">
</app-status-logs>
</div>

View File

@ -101,6 +101,11 @@ export class GlobalOgbootStatusComponent implements OnInit {
}
}
getSelectedBootServerIp(): string {
const s = this.bootServers.find(s => s.uuid === this.selectedBootServerUuid);
return s ? s.ip : '';
}
getSelectedBootServerName(): string {
const selectedBootServer = this.bootServers.find(server => server.uuid === this.selectedBootServerUuid);
return selectedBootServer ? selectedBootServer.name : '';

View File

@ -3,7 +3,7 @@
<div id="ogcore-logs-section">
<app-status-logs
[title]="'ogcoreLogs'"
[identifier]="'ogcore'"
[identifiers]="['ogcore']"
[host]="''"
[oglogUrl]="getOgCoreIframeUrl()">
</app-status-logs>

View File

@ -45,8 +45,8 @@
<div id="dhcp-logs-section">
<app-status-logs
[title]="'dhcpLogs'"
[identifier]="'ogdhcp'"
[host]="getSelectedDhcpName()"
[identifiers]="['ogdhcp', 'kea-dhcp4', 'kea-ctrl-agent', 'DhcpLFC']"
[host]="getSelectedDhcpIp()"
[oglogUrl]="getDhcpIframeUrl()">
</app-status-logs>
</div>

View File

@ -104,6 +104,11 @@ export class OgdhcpStatusComponent implements OnInit {
}
}
getSelectedDhcpIp(): string {
const d = this.dhcps.find(d => d.uuid === this.selectedDhcpUuid);
return d ? d.ip : '';
}
getSelectedDhcpName(): string {
const selectedDhcp = this.dhcps.find(dhcp => dhcp.uuid === this.selectedDhcpUuid);
return selectedDhcp ? selectedDhcp.name : '';

View File

@ -52,8 +52,8 @@
<div id="repository-logs-section">
<app-status-logs
[title]="'ogrepositoryLogs'"
[identifier]="'ogrepo-api'"
[host]="getSelectedRepositoryName()"
[identifiers]="['ogrepo-api', 'ogrepo-api_DEBUG', '(smbd)', '(nmbd)']"
[host]="getSelectedRepositoryIp()"
[oglogUrl]="getRepositoryIframeUrl()">
</app-status-logs>
</div>

View File

@ -103,6 +103,11 @@ export class OgrepositoryStatusComponent implements OnInit {
}
}
getSelectedRepositoryIp(): string {
const r = this.repositories.find(r => r.uuid === this.selectedRepositoryUuid);
return r ? r.ip : '';
}
getSelectedRepositoryName(): string {
const selectedRepo = this.repositories.find(repo => repo.uuid === this.selectedRepositoryUuid);
return selectedRepo ? selectedRepo.name : '';

View File

@ -5,6 +5,14 @@ import { ConfigService } from '@services/config.service';
import { TranslateService } from '@ngx-translate/core';
import { MatTabChangeEvent } from '@angular/material/tabs';
interface JournalEntry {
MESSAGE: string;
SYSLOG_IDENTIFIER?: string;
_HOSTNAME?: string;
__REALTIME_TIMESTAMP?: string;
PRIORITY?: string;
}
@Component({
selector: 'app-status-logs',
templateUrl: './status-logs.component.html',
@ -12,7 +20,7 @@ import { MatTabChangeEvent } from '@angular/material/tabs';
})
export class StatusLogsComponent implements OnInit, OnDestroy, AfterViewChecked {
@ViewChild('logContent') private logContainer!: ElementRef;
@Input() identifier: string = '';
@Input() identifiers: string[] = [];
@Input() host: string = '';
@Input() oglogUrl: SafeResourceUrl | null = null;
@Input() title: string = '';
@ -53,12 +61,12 @@ export class StatusLogsComponent implements OnInit, OnDestroy, AfterViewChecked
}
onTabChange(event: MatTabChangeEvent): void {
if (event.index === 0) { // Disk Logs tab
if (event.index === 0) {
if (this.isLive) {
this.loadDiskLogs();
this.startPolling();
}
} else { // oglog Logs tab or others
} else {
this.stopPolling();
}
}
@ -68,27 +76,39 @@ export class StatusLogsComponent implements OnInit, OnDestroy, AfterViewChecked
}
loadDiskLogs(): void {
if (!this.identifier) return;
if (!this.identifiers.length) return;
if (!this.isLive) {
this.loadingDiskLogs = true;
}
const url = `${this.configService.apiUrl}/opengnsys/system/disk-logs?SYSLOG_IDENTIFIER=${this.identifier}&host=${this.host}&lines=200`;
this.http.get<{ content: string }>(url).subscribe({
const idParam = this.identifiers.join(',');
const hostParam = this.host ? `&host=${encodeURIComponent(this.host)}` : '';
const url = `${this.configService.apiUrl}/opengnsys/system/disk-logs?SYSLOG_IDENTIFIER=${encodeURIComponent(idParam)}${hostParam}&lines=200`;
this.http.get<{ entries: JournalEntry[] }>(url).subscribe({
next: (response) => {
this.diskLogsContent = response.content || '';
this.diskLogsContent = this.formatEntries(response.entries || []);
this.loadingDiskLogs = false;
this.errorDiskLogs = null;
},
error: (err) => {
error: () => {
this.errorDiskLogs = 'Error al cargar logs de disco';
this.loadingDiskLogs = false;
}
});
}
private formatEntries(entries: JournalEntry[]): string {
return entries.map(entry => {
const ts = entry.__REALTIME_TIMESTAMP
? new Date(parseInt(entry.__REALTIME_TIMESTAMP, 10) / 1000).toISOString().replace('T', ' ').substring(0, 23)
: ' ';
const id = entry.SYSLOG_IDENTIFIER ?? '';
return `[${ts}] ${id}: ${entry.MESSAGE ?? ''}`;
}).join('\n');
}
private startPolling(): void {
this.stopPolling();
this.pollInterval = setInterval(() => {