-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f20217c
commit 3c44673
Showing
7 changed files
with
209 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,6 @@ | |
/build | ||
|
||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
pnpm-debug.log* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import {Table, Column, Model, PrimaryKey, AutoIncrement, Unique} from 'sequelize-typescript' | ||
import { LogLevels, LogType } from '../../../../src/types'; | ||
|
||
|
||
@Table({ | ||
tableName: 'logs', | ||
}) | ||
export class Log extends Model { | ||
@PrimaryKey | ||
@AutoIncrement | ||
@Column | ||
id: number; | ||
|
||
@Column | ||
type: LogType; | ||
|
||
@Column | ||
level: LogLevels; | ||
|
||
@Unique('compositeIndex') | ||
@Column | ||
data: string; | ||
|
||
@Column | ||
isHidden: boolean | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// src/logs/logs.controller.ts | ||
import { Controller, Get, Res, Req, Param, UseGuards } from '@nestjs/common'; | ||
import { Request, Response } from 'express'; | ||
import { LogsService } from './logs.service'; | ||
import { SessionGuard } from '../session.guard'; | ||
|
||
@Controller('logs') | ||
@UseGuards(SessionGuard) | ||
export class LogsController { | ||
constructor(private logsService: LogsService) {} | ||
|
||
@Get('validator') | ||
getValidatorLogs(@Res() res: Response, @Req() req: Request) { | ||
const validatorUrl = process.env.VALIDATOR_URL; | ||
this.logsService.getSseStream(req, res, `${validatorUrl}/lighthouse/logs`); | ||
} | ||
|
||
@Get('beacon') | ||
getBeaconLogs(@Res() res: Response, @Req() req: Request) { | ||
const beaconUrl = process.env.BEACON_URL; | ||
this.logsService.getSseStream(req, res, `${beaconUrl}/lighthouse/logs`); | ||
} | ||
|
||
@Get('metrics') | ||
getLogMetrics() { | ||
return this.logsService.readLogMetrics() | ||
} | ||
|
||
@Get('dismiss/:index') | ||
dismissLogAlert(@Param('index') index: string) { | ||
return this.logsService.dismissLog(index) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { LogsController } from './logs.controller'; | ||
import { UtilsModule } from '../utils/utils.module'; | ||
import { LogsService } from './logs.service'; | ||
import { SequelizeModule } from '@nestjs/sequelize'; | ||
import { Log } from './entities/log.entity'; | ||
|
||
@Module({ | ||
imports: [UtilsModule, SequelizeModule.forFeature([Log])], | ||
controllers: [LogsController], | ||
providers: [LogsService], | ||
exports: [LogsService] | ||
}) | ||
export class LogsModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { Injectable } from '@nestjs/common'; | ||
import {Subject} from 'rxjs'; | ||
import { Request, Response } from 'express'; | ||
import * as EventSource from 'eventsource'; | ||
import { LogLevels, LogType, SSELog } from '../../../src/types'; | ||
import { InjectModel } from '@nestjs/sequelize'; | ||
import { Log } from './entities/log.entity'; | ||
|
||
@Injectable() | ||
export class LogsService { | ||
constructor( | ||
@InjectModel(Log) | ||
private logRepository: typeof Log | ||
) {} | ||
|
||
private sseStreams: Map<string, Subject<any>> = new Map(); | ||
|
||
public async startSse(url: string, type: LogType) { | ||
console.log(`starting sse ${url}, ${type}...`) | ||
const eventSource = new EventSource(url); | ||
|
||
const sseStream: Subject<any> = new Subject(); | ||
this.sseStreams.set(url, sseStream) | ||
|
||
|
||
eventSource.onmessage = (event) => { | ||
let newData | ||
|
||
try { | ||
newData = JSON.parse(JSON.parse(event.data)) | ||
} catch (e) { | ||
newData = JSON.parse(event.data) as SSELog | ||
} | ||
|
||
const { level } = newData | ||
|
||
if(level !== LogLevels.INFO) { | ||
this.logRepository.create({type, level, data: JSON.stringify(newData), isHidden: false}, {ignoreDuplicates: true}) | ||
console.log(newData, type,'------------------------------------------ log --------------------------------------') | ||
} | ||
|
||
sseStream.next(event.data); | ||
}; | ||
} | ||
|
||
public getSseStream(req: Request, res: Response, url: string) { | ||
const sseStream = this.sseStreams.get(url); | ||
if (sseStream) { | ||
res.writeHead(200, { | ||
'Content-Type': 'text/event-stream', | ||
'Cache-Control': 'no-cache', | ||
Connection: 'keep-alive', | ||
'X-Accel-Buffering': 'no', | ||
}); | ||
res.flushHeaders(); | ||
|
||
sseStream.subscribe(data => { | ||
res.write(`data: ${data}\n\n`); | ||
}); | ||
|
||
const heartbeatInterval = setInterval(() => { | ||
res.write(': keep-alive\n\n'); | ||
}, 10000); | ||
|
||
req.on('close', () => { | ||
clearInterval(heartbeatInterval); | ||
res.end(); | ||
}); | ||
} else { | ||
console.error('SSE stream not found for URL:', url); | ||
res.status(404).end(); | ||
} | ||
} | ||
|
||
async readLogMetrics(type?: LogType) { | ||
let warnOptions = { where: { level: LogLevels.WARN } } as any | ||
let errorOptions = { where: { level: LogLevels.ERRO } } as any | ||
let critOptions = { where: { level: LogLevels.CRIT } } as any | ||
|
||
if(type) { | ||
warnOptions.where.type = type | ||
errorOptions.where.type = type | ||
critOptions.where.type = type | ||
} | ||
|
||
const warningLogs = (await this.logRepository.findAll(warnOptions)).map(data => data.dataValues) | ||
const errorLogs = (await this.logRepository.findAll(errorOptions)).map(data => data.dataValues) | ||
const criticalLogs = (await this.logRepository.findAll(critOptions)).map(data => data.dataValues) | ||
|
||
return { | ||
warningLogs, | ||
errorLogs, | ||
criticalLogs | ||
} | ||
} | ||
|
||
async dismissLog(id: string) { | ||
return await this.logRepository.update({isHidden: true}, {where: {id}}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { LogsController } from '../logs.controller'; | ||
|
||
describe('LogsController', () => { | ||
let controller: LogsController; | ||
|
||
beforeEach(async () => { | ||
const module: TestingModule = await Test.createTestingModule({ | ||
controllers: [LogsController], | ||
}).compile(); | ||
|
||
controller = module.get<LogsController>(LogsController); | ||
}); | ||
|
||
it('should be defined', () => { | ||
expect(controller).toBeDefined(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { LogsService } from '../logs.service'; | ||
|
||
describe('LogsService', () => { | ||
let service: LogsService; | ||
|
||
beforeEach(async () => { | ||
const module: TestingModule = await Test.createTestingModule({ | ||
providers: [LogsService], | ||
}).compile(); | ||
|
||
service = module.get<LogsService>(LogsService); | ||
}); | ||
|
||
it('should be defined', () => { | ||
expect(service).toBeDefined(); | ||
}); | ||
}); |