From f0a7b545916153a622fd658038e78e36000afa77 Mon Sep 17 00:00:00 2001 From: DongHoonYu96 Date: Tue, 26 Nov 2024 23:10:27 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20[BE]=20=EB=AA=A8=EB=8B=88=ED=84=B0?= =?UTF-8?q?=EB=A7=81=20=EA=B5=AC=ED=98=84=20v4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cpu, mem, connection 상황 출력 --- BE/src/app.module.ts | 140 +++++++------- BE/src/common/CommonModule.ts | 9 + .../SocketEventLoggerInterceptor.ts | 71 +++++-- BE/src/common/service/SystemMetricsService.ts | 175 ++++++++++++++++++ BE/src/game/game.module.ts | 6 +- 5 files changed, 317 insertions(+), 84 deletions(-) create mode 100644 BE/src/common/CommonModule.ts create mode 100644 BE/src/common/service/SystemMetricsService.ts diff --git a/BE/src/app.module.ts b/BE/src/app.module.ts index 846cb45c..3fd5aca9 100644 --- a/BE/src/app.module.ts +++ b/BE/src/app.module.ts @@ -1,70 +1,70 @@ -import { ClassSerializerInterceptor, Module } from '@nestjs/common'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; -import { GameModule } from './game/game.module'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { RedisModule } from '@nestjs-modules/ioredis'; -import { ConfigModule } from '@nestjs/config'; -import { QuizSetModel } from './quiz-set/entities/quiz-set.entity'; -import { QuizModel } from './quiz-set/entities/quiz.entity'; -import { QuizChoiceModel } from './quiz-set/entities/quiz-choice.entity'; -import { UserModel } from './user/entities/user.entity'; -import { UserQuizArchiveModel } from './user/entities/user-quiz-archive.entity'; -import { InitDBModule } from './InitDB/InitDB.module'; -import { UserModule } from './user/user.module'; -import { QuizSetModule } from './quiz-set/quiz-set.module'; -import { WaitingRoomModule } from './waiting-room/waiting-room.module'; -import { TimeController } from './time/time.controller'; -import { TimeModule } from './time/time.module'; -import { AuthModule } from './auth/auth.module'; -import { ScheduleModule } from '@nestjs/schedule'; -import { GameRedisMemoryService } from './game/redis/game-redis-memory.service'; -import { APP_INTERCEPTOR } from '@nestjs/core'; - -@Module({ - imports: [ - ConfigModule.forRoot({ - envFilePath: '../.env', - isGlobal: true - }), - GameModule, - // 스케줄러 모듈 추가 (Redis 메모리 관리 서비스의 @Cron 데코레이터 사용을 위해) - ScheduleModule.forRoot(), - TypeOrmModule.forRoot({ - type: 'mysql', - host: process.env.DB_HOST || 'localhost', - port: +process.env.DB_PORT || 3306, - username: process.env.DB_USER || 'root', - password: process.env.DB_PASSWD || 'test', - database: process.env.DB_NAME || 'test_db', - entities: [QuizSetModel, QuizModel, QuizChoiceModel, UserModel, UserQuizArchiveModel], - synchronize: process.env.DEV ? true : false, // 개발 모드에서만 활성화 - logging: true, // 모든 쿼리 로깅 - logger: 'advanced-console' - // extra: { - // // 글로벌 batch size 설정 - // maxBatchSize: 100 - // } - }), - RedisModule.forRoot({ - type: 'single', - url: process.env.REDIS_URL || 'redis://localhost:6379' - }), - QuizSetModule, - UserModule, - InitDBModule, - WaitingRoomModule, - TimeModule, - AuthModule - ], - controllers: [AppController, TimeController], - providers: [ - AppService, - GameRedisMemoryService, - { - provide: APP_INTERCEPTOR, - useClass: ClassSerializerInterceptor - } - ] -}) -export class AppModule {} +import { ClassSerializerInterceptor, Module } from '@nestjs/common'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; +import { GameModule } from './game/game.module'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { RedisModule } from '@nestjs-modules/ioredis'; +import { ConfigModule } from '@nestjs/config'; +import { QuizSetModel } from './quiz-set/entities/quiz-set.entity'; +import { QuizModel } from './quiz-set/entities/quiz.entity'; +import { QuizChoiceModel } from './quiz-set/entities/quiz-choice.entity'; +import { UserModel } from './user/entities/user.entity'; +import { UserQuizArchiveModel } from './user/entities/user-quiz-archive.entity'; +import { InitDBModule } from './InitDB/InitDB.module'; +import { UserModule } from './user/user.module'; +import { QuizSetModule } from './quiz-set/quiz-set.module'; +import { WaitingRoomModule } from './waiting-room/waiting-room.module'; +import { TimeController } from './time/time.controller'; +import { TimeModule } from './time/time.module'; +import { AuthModule } from './auth/auth.module'; +import { ScheduleModule } from '@nestjs/schedule'; +import { GameRedisMemoryService } from './game/redis/game-redis-memory.service'; +import { APP_INTERCEPTOR } from '@nestjs/core'; + +@Module({ + imports: [ + ConfigModule.forRoot({ + envFilePath: '../.env', + isGlobal: true + }), + GameModule, + // 스케줄러 모듈 추가 (Redis 메모리 관리 서비스의 @Cron 데코레이터 사용을 위해) + ScheduleModule.forRoot(), + TypeOrmModule.forRoot({ + type: 'mysql', + host: process.env.DB_HOST || 'localhost', + port: +process.env.DB_PORT || 3306, + username: process.env.DB_USER || 'root', + password: process.env.DB_PASSWD || 'test', + database: process.env.DB_NAME || 'test_db', + entities: [QuizSetModel, QuizModel, QuizChoiceModel, UserModel, UserQuizArchiveModel], + synchronize: process.env.DEV ? true : false, // 개발 모드에서만 활성화 + logging: true, // 모든 쿼리 로깅 + logger: 'advanced-console' + // extra: { + // // 글로벌 batch size 설정 + // maxBatchSize: 100 + // } + }), + RedisModule.forRoot({ + type: 'single', + url: process.env.REDIS_URL || 'redis://localhost:6379' + }), + QuizSetModule, + UserModule, + InitDBModule, + WaitingRoomModule, + TimeModule, + AuthModule + ], + controllers: [AppController, TimeController], + providers: [ + AppService, + GameRedisMemoryService, + { + provide: APP_INTERCEPTOR, + useClass: ClassSerializerInterceptor + } + ] +}) +export class AppModule {} diff --git a/BE/src/common/CommonModule.ts b/BE/src/common/CommonModule.ts new file mode 100644 index 00000000..91c76dbe --- /dev/null +++ b/BE/src/common/CommonModule.ts @@ -0,0 +1,9 @@ +import { SocketEventLoggerInterceptor } from './interceptor/SocketEventLoggerInterceptor'; +import { Module } from '@nestjs/common'; +import { SystemMetricsService } from './service/SystemMetricsService'; + +@Module({ + providers: [SystemMetricsService, SocketEventLoggerInterceptor], + exports: [SocketEventLoggerInterceptor] +}) +export class CommonModule {} diff --git a/BE/src/common/interceptor/SocketEventLoggerInterceptor.ts b/BE/src/common/interceptor/SocketEventLoggerInterceptor.ts index e8da0326..1af331e8 100644 --- a/BE/src/common/interceptor/SocketEventLoggerInterceptor.ts +++ b/BE/src/common/interceptor/SocketEventLoggerInterceptor.ts @@ -1,8 +1,8 @@ import { firstValueFrom, Observable } from 'rxjs'; import { CallHandler, ExecutionContext, Injectable, Logger, NestInterceptor } from '@nestjs/common'; -import { ModuleRef } from '@nestjs/core'; import { Socket } from 'socket.io'; -import { AsyncLocalStorage } from 'async_hooks'; // 이 부분 추가 +import { AsyncLocalStorage } from 'async_hooks'; +import { SystemMetricsService } from '../service/SystemMetricsService'; // 이 부분 추가 /** * @class TraceStore @@ -54,7 +54,7 @@ export class SocketEventLoggerInterceptor implements NestInterceptor { private readonly logger = new Logger('SocketEventLogger'); private readonly EXECUTION_TIME_THRESHOLD = 1000; - constructor(private readonly moduleRef: ModuleRef) {} + constructor(private readonly systemMetricsService: SystemMetricsService) {} intercept(context: ExecutionContext, next: CallHandler): Observable { if (context.getType() !== 'ws') { @@ -72,29 +72,50 @@ export class SocketEventLoggerInterceptor implements NestInterceptor { const traceContext = new TraceContext(); return new Observable((subscriber) => { - // AsyncLocalStorage를 사용하여 추적 컨텍스트 설정 TraceStore.getStore().run(traceContext, async () => { try { - // 핸들러 실행 전 로그 traceContext.addLog(`[${className}.${methodName}] Started`); - - // 원본 핸들러 실행 const result = await firstValueFrom(next.handle()); - const executionTime = Date.now() - startTime; const logs = traceContext.getLogs(); + // 시스템 메트릭 수집 + const metrics = await this.systemMetricsService.getMetrics(); + if (executionTime >= this.EXECUTION_TIME_THRESHOLD) { this.logger.warn( - '🐢 Slow Socket Event Detected!\n' + + '\n=============================\n' + + '🐢 Slow Socket Event Detected!\n' + logs.join('\n') + - `\nTotal Execution Time: ${executionTime}ms` + `\nTotal Execution Time: ${executionTime}ms\n` + + '\nSystem Metrics:\n' + + `CPU Usage: ${metrics.cpu.toFixed(2)}%\n` + + '\nMemory Usage:\n' + + `System Total: ${metrics.memory.system.total}GB\n` + + `System Used: ${metrics.memory.system.used}GB (${metrics.memory.system.usagePercentage}%)\n` + + `System Free: ${metrics.memory.system.free}GB\n` + + `Process Heap: ${metrics.memory.process.heapUsed}MB / ${metrics.memory.process.heapTotal}MB\n` + + `Process RSS: ${metrics.memory.process.rss}MB\n` + + '\nMySQL Connections:\n' + + `Total: ${metrics.mysql.total}, ` + + `Active: ${metrics.mysql.active}, ` + + `Idle: ${metrics.mysql.idle}, ` + + `Waiting: ${metrics.mysql.waiting}\n` + + '\nRedis Connections:\n' + + `Connected Clients: ${metrics.redis.connectedClients}, ` + + `Used Memory: ${metrics.redis.usedMemoryMB}MB\n` + + `클라이언트 큐 길이: ${metrics.redis.queueLength}\n` + + // `현재 처리중인 명령어 수 : ${metrics.redis.cmdstat}\n` + + '=============================' ); } else { this.logger.log( - '🚀 Socket Event Processed\n' + + '\n=============================\n' + + '🚀 Socket Event Processed\n' + logs.join('\n') + - `\nTotal Execution Time: ${executionTime}ms` + `\nTotal Execution Time: ${executionTime}ms\n` + + '=============================' + // 정상 처리시에는 간단한 로그만 ); } @@ -102,8 +123,32 @@ export class SocketEventLoggerInterceptor implements NestInterceptor { subscriber.complete(); } catch (error) { const logs = traceContext.getLogs(); + // 에러 발생시에도 시스템 메트릭 수집 + const metrics = await this.systemMetricsService.getMetrics(); + this.logger.error( - '❌ Socket Event Error\n' + logs.join('\n') + `\nError: ${error.message}` + '❌ Socket Event Error\n' + + logs.join('\n') + + `\nError: ${error.message}\n` + + '\nSystem Metrics:\n' + + `CPU Usage: ${metrics.cpu.toFixed(2)}%\n` + + '\nMemory Usage:\n' + + `System Total: ${metrics.memory.system.total}GB\n` + + `System Used: ${metrics.memory.system.used}GB (${metrics.memory.system.usagePercentage}%)\n` + + `System Free: ${metrics.memory.system.free}GB\n` + + `Process Heap: ${metrics.memory.process.heapUsed}MB / ${metrics.memory.process.heapTotal}MB\n` + + `Process RSS: ${metrics.memory.process.rss}MB\n` + + '\nMySQL Connections:\n' + + `Total: ${metrics.mysql.total}, ` + + `Active: ${metrics.mysql.active}, ` + + `Idle: ${metrics.mysql.idle}, ` + + `Waiting: ${metrics.mysql.waiting}\n` + + '\nRedis Connections:\n' + + `Connected Clients: ${metrics.redis.connectedClients}, ` + + `Used Memory: ${metrics.redis.usedMemoryMB}MB\n` + + `클라이언트 큐 길이: ${metrics.redis.queueLength}\n` + + // `현재 처리중인 명령어 수 : ${metrics.redis.cmdstat}\n` + + '=============================' ); subscriber.error(error); } diff --git a/BE/src/common/service/SystemMetricsService.ts b/BE/src/common/service/SystemMetricsService.ts new file mode 100644 index 00000000..667bbd48 --- /dev/null +++ b/BE/src/common/service/SystemMetricsService.ts @@ -0,0 +1,175 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRedis } from '@nestjs-modules/ioredis'; +import Redis from 'ioredis'; +import { InjectDataSource } from '@nestjs/typeorm'; +import { DataSource } from 'typeorm'; + +/** + * @interface SystemMetrics + * @description 시스템 메트릭 인터페이스 + */ +interface SystemMetrics { + cpu: number; + memory: { + system: { + total: number; // GB + used: number; // GB + free: number; // GB + usagePercentage: number; // % + }; + process: { + heapTotal: number; // MB + heapUsed: number; // MB + rss: number; // MB + external: number; // MB + }; + }; + mysql: { + total: number; + active: number; + idle: number; + connected?: number; + waiting?: number; + }; + redis: { + connectedClients: number; + usedMemoryMB: number; + clientList: number; + queueLength: number; + cmdstat: string; + }; +} + +/** + * @class SystemMetricsService + * @description 시스템 메트릭 수집 서비스 + */ +@Injectable() +export class SystemMetricsService { + constructor( + @InjectRedis() private readonly redis: Redis, + @InjectDataSource() private readonly dataSource: DataSource + ) {} + + async getMetrics(): Promise { + const [cpuUsage, memoryUsage] = await Promise.all([this.getCpuUsage(), this.getMemoryUsage()]); + + return { + cpu: cpuUsage, + memory: memoryUsage, + mysql: await this.getMySQLMetrics(), + redis: await this.getRedisMetrics() + }; + } + + private async getCpuUsage(): Promise { + const cpus = require('os').cpus(); + const cpuCount = cpus.length; + + const loadAvg = require('os').loadavg(); + return (loadAvg[0] / cpuCount) * 100; + } + + private getMemoryUsage() { + const os = require('os'); + + // 시스템 전체 메모리 + const totalMemory = os.totalmem(); + const freeMemory = os.freemem(); + const usedMemory = totalMemory - freeMemory; + + // Node.js 프로세스 메모리 + const processMemory = process.memoryUsage(); + + return { + system: { + total: Math.round(totalMemory / 1024 / 1024 / 1024), // GB + used: Math.round(usedMemory / 1024 / 1024 / 1024), // GB + free: Math.round(freeMemory / 1024 / 1024 / 1024), // GB + usagePercentage: Math.round((usedMemory / totalMemory) * 100) + }, + process: { + heapTotal: Math.round(processMemory.heapTotal / 1024 / 1024), // MB + heapUsed: Math.round(processMemory.heapUsed / 1024 / 1024), // MB + rss: Math.round(processMemory.rss / 1024 / 1024), // MB + external: Math.round(processMemory.external / 1024 / 1024) // MB + } + }; + } + + private async getMySQLMetrics(): Promise<{ + total: number; + active: number; + idle: number; + connected?: number; + waiting?: number; + }> { + try { + // TypeORM의 connection options에서 직접 가져오기 + const connectionOptions = this.dataSource.options; + const poolSize = (connectionOptions as any).extra?.connectionLimit || 10; // 기본값 + + // 현재 연결 상태 + const queryRunner = this.dataSource.createQueryRunner(); + const result = await queryRunner.query( + 'SHOW STATUS WHERE Variable_name IN ("Threads_connected", "Threads_running", "Threads_cached")' + ); + await queryRunner.release(); + + const metrics = result.reduce((acc, row) => { + acc[row.Variable_name] = parseInt(row.Value); + return acc; + }, {}); + + return { + total: poolSize, + active: metrics.Threads_running || 0, + idle: metrics.Threads_cached || 0, + connected: metrics.Threads_connected || 0 + }; + } catch (error) { + return { + total: 0, + active: 0, + idle: 0, + waiting: 0 + }; + } + } + + private async getRedisMetrics() { + const info = await this.redis.info(); + const clientList = await this.redis.client('LIST'); + + // Redis INFO 명령어 결과 파싱 + const connected_clients = parseInt(info.match(/connected_clients:(\d+)/)?.[1] || '0'); + const used_memory = parseInt(info.match(/used_memory:(\d+)/)?.[1] || '0'); + + const { queueLength, cmdstat, totalCommands } = await this.getCommandStats(); + + return { + connectedClients: connected_clients, + usedMemoryMB: Math.round(used_memory / 1024 / 1024), + clientList: String(clientList).split('\n').length, + queueLength, + cmdstat + }; + } + + private async getCommandStats() { + // 현재 처리 중인 명령어 수 + const cmdstat = await this.redis.info('commandstats'); + + // 클라이언트 큐 길이 + const queueLength = (this.redis as any).commandQueue?.length || 0; + + // 처리된 총 명령어 수 + const totalCommands = await this.redis.info('stats'); + + return { + queueLength, + totalCommands, + cmdstat + }; + } +} diff --git a/BE/src/game/game.module.ts b/BE/src/game/game.module.ts index eaaf4a0a..d7db1840 100644 --- a/BE/src/game/game.module.ts +++ b/BE/src/game/game.module.ts @@ -16,6 +16,8 @@ import { PlayerSubscriber } from './redis/subscribers/player.subscriber'; import { RoomCleanupSubscriber } from './redis/subscribers/room.cleanup.subscriber'; import { JwtModule } from '@nestjs/jwt'; import { AuthModule } from '../auth/auth.module'; +import { SocketEventLoggerInterceptor } from '../common/interceptor/SocketEventLoggerInterceptor'; +import { SystemMetricsService } from '../common/service/SystemMetricsService'; @Module({ imports: [RedisModule, QuizSetModule, JwtModule, AuthModule], @@ -32,7 +34,9 @@ import { AuthModule } from '../auth/auth.module'; TimerSubscriber, RoomSubscriber, PlayerSubscriber, - RoomCleanupSubscriber + RoomCleanupSubscriber, + SocketEventLoggerInterceptor, + SystemMetricsService ], exports: [GameService] }) From c6ee27d4cc458c259ca37e39424be966c327ea46 Mon Sep 17 00:00:00 2001 From: DongHoonYu96 Date: Wed, 27 Nov 2024 00:24:24 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20[BE]=20admin=20ui=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://admin.socket.io/#/ 여기접속후 서버주소 입력하면 모니터링 가능 --- BE/package-lock.json | 24 ++++++++++++++++++++++++ BE/package.json | 1 + BE/src/game/game.gateway.ts | 13 ++++++++++--- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/BE/package-lock.json b/BE/package-lock.json index 076bd76f..709c477e 100644 --- a/BE/package-lock.json +++ b/BE/package-lock.json @@ -23,6 +23,7 @@ "@nestjs/swagger": "^8.0.5", "@nestjs/typeorm": "^10.0.2", "@nestjs/websockets": "^10.4.7", + "@socket.io/admin-ui": "^0.5.1", "axios": "^1.7.7", "bcrypt": "^5.1.1", "class-transformer": "^0.5.1", @@ -2432,6 +2433,19 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@socket.io/admin-ui": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@socket.io/admin-ui/-/admin-ui-0.5.1.tgz", + "integrity": "sha512-1dlGL2FGm6T+uL1e6iDvbo2eCINwvW7iVbjIblwh5kPPRM1SP8lmZrbFZf4QNJ/cqQ+JLcx49eXGM9WAB4TK7w==", + "dependencies": { + "@types/bcryptjs": "^2.4.2", + "bcryptjs": "^2.4.3", + "debug": "~4.3.1" + }, + "peerDependencies": { + "socket.io": ">=3.1.0" + } + }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", @@ -2517,6 +2531,11 @@ "@types/node": "*" } }, + "node_modules/@types/bcryptjs": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", + "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==" + }, "node_modules/@types/body-parser": { "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", @@ -3654,6 +3673,11 @@ "node": ">= 10.0.0" } }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", diff --git a/BE/package.json b/BE/package.json index d0b8a0b9..8b8ee5a6 100644 --- a/BE/package.json +++ b/BE/package.json @@ -43,6 +43,7 @@ "@nestjs/swagger": "^8.0.5", "@nestjs/typeorm": "^10.0.2", "@nestjs/websockets": "^10.4.7", + "@socket.io/admin-ui": "^0.5.1", "axios": "^1.7.7", "bcrypt": "^5.1.1", "class-transformer": "^0.5.1", diff --git a/BE/src/game/game.gateway.ts b/BE/src/game/game.gateway.ts index e70a1221..ba1a9f8c 100644 --- a/BE/src/game/game.gateway.ts +++ b/BE/src/game/game.gateway.ts @@ -5,7 +5,8 @@ import { WebSocketGateway, WebSocketServer } from '@nestjs/websockets'; -import { Server, Socket } from 'socket.io'; +import { Namespace, Server, Socket } from 'socket.io'; +import { instrument } from '@socket.io/admin-ui'; import { Logger, UseFilters, UseGuards, UseInterceptors, UsePipes } from '@nestjs/common'; import { WsExceptionFilter } from '../common/filters/ws-exception.filter'; import SocketEvents from '../common/constants/socket-events'; @@ -30,7 +31,8 @@ import { SocketEventLoggerInterceptor } from '../common/interceptor/SocketEventL @UseFilters(new WsExceptionFilter()) @WebSocketGateway({ cors: { - origin: '*' + origin: ['*,', 'https://admin.socket.io'], + credentials: true }, namespace: '/game' }) @@ -129,7 +131,12 @@ export class GameGateway { await this.gameRoomService.kickRoom(kickRoomDto, client.id); } - afterInit() { + afterInit(nameSpace: Namespace) { + instrument(nameSpace.server, { + auth: false, + mode: 'development' + }); + this.logger.verbose('Socket.IO Admin UI initialized'); this.logger.verbose('WebSocket 서버 초기화 완료했어요!'); this.gameService.subscribeRedisEvent(this.server).then(() => { From 0a9670a28500af546f0bc8cf6ebeefed8ef62d67 Mon Sep 17 00:00:00 2001 From: DongHoonYu96 Date: Wed, 27 Nov 2024 00:43:33 +0900 Subject: [PATCH 3/3] =?UTF-8?q?chore:=20[BE]=20=EC=9E=91=EB=8F=99=EC=95=88?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EB=B6=80=EB=B6=84=20=EC=A3=BC=EC=84=9D=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BE/src/common/interceptor/SocketEventLoggerInterceptor.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BE/src/common/interceptor/SocketEventLoggerInterceptor.ts b/BE/src/common/interceptor/SocketEventLoggerInterceptor.ts index 1af331e8..5b63ad8b 100644 --- a/BE/src/common/interceptor/SocketEventLoggerInterceptor.ts +++ b/BE/src/common/interceptor/SocketEventLoggerInterceptor.ts @@ -104,7 +104,7 @@ export class SocketEventLoggerInterceptor implements NestInterceptor { '\nRedis Connections:\n' + `Connected Clients: ${metrics.redis.connectedClients}, ` + `Used Memory: ${metrics.redis.usedMemoryMB}MB\n` + - `클라이언트 큐 길이: ${metrics.redis.queueLength}\n` + + // `클라이언트 큐 길이: ${metrics.redis.queueLength}\n` + // `현재 처리중인 명령어 수 : ${metrics.redis.cmdstat}\n` + '=============================' ); @@ -146,7 +146,7 @@ export class SocketEventLoggerInterceptor implements NestInterceptor { '\nRedis Connections:\n' + `Connected Clients: ${metrics.redis.connectedClients}, ` + `Used Memory: ${metrics.redis.usedMemoryMB}MB\n` + - `클라이언트 큐 길이: ${metrics.redis.queueLength}\n` + + // `클라이언트 큐 길이: ${metrics.redis.queueLength}\n` + // `현재 처리중인 명령어 수 : ${metrics.redis.cmdstat}\n` + '=============================' );