Skip to content

Commit

Permalink
fix: remove logs from gitignore
Browse files Browse the repository at this point in the history
  • Loading branch information
rickimoore committed May 11, 2024
1 parent f20217c commit 3c44673
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 1 deletion.
1 change: 0 additions & 1 deletion backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
/build

# Logs
logs
*.log
npm-debug.log*
pnpm-debug.log*
Expand Down
26 changes: 26 additions & 0 deletions backend/src/logs/entities/log.entity.ts
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
}
33 changes: 33 additions & 0 deletions backend/src/logs/logs.controller.ts
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)
}
}
14 changes: 14 additions & 0 deletions backend/src/logs/logs.module.ts
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 {}
100 changes: 100 additions & 0 deletions backend/src/logs/logs.service.ts
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}})
}
}
18 changes: 18 additions & 0 deletions backend/src/logs/tests/logs.controller.spec.ts
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();
});
});
18 changes: 18 additions & 0 deletions backend/src/logs/tests/logs.service.spec.ts
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();
});
});

0 comments on commit 3c44673

Please sign in to comment.