[NestJS] 로깅 인프라 구축하기 2편

오영선·2023년 12월 5일
0

종합프로젝트

목록 보기
3/6

오늘의 목표 : this.loger..호출 시 MongoDB에 로깅 데이터를 저장하기

⚠️ 기본 코드는 docs.nestjs.com의 공식문서를 바탕으로 작성되었습니다.
https://docs.nestjs.com/techniques/mongodb

MongoDB 모듈 설치

npm install --save @nestjs/mongoose mongoose
를 통해 필요한 패키지를 먼저 설치한다.
❗이때 MongoDB를 설치해, 클라우드를 먼저 만들어둬야함

몽고 디비의 url 등록하기

app.modules.ts

  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    MongooseModule.forRoot(process.env.MONGO_DB_URL),
   

mondgoDB에서 사용할 도메인 작성

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import mongoose, { Document } from 'mongoose';

export type LoggingDocument = Logging & Document;
//MongoDB의 가장 작은 단위가 Document, 모듈에서 사용할 타입을 export 시켜줌

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import mongoose from 'mongoose';

@Schema({ timestamps: { createdAt: 'createdAt', updatedAt: 'updatedAt' } })
export class Logging {
  @Prop()
  level: string;

  @Prop({ required: true }) //to specify relation to another model
  message: string;

  @Prop({ default: new Date(), type: mongoose.Schema.Types.Date })
  timestamp: Date;
}

// 위의 작성한 클래스를 바탕으로 Mongoose에서 사용하는 스키마 클래스를 만들어준다.
export const LoggingSchema = SchemaFactory.createForClass(Logging);

Logging 클래스를 같은 이름의 MongoDB 컬렉션에 매핑하지만 끝에 's'를 추가하여 최종 몽고 컬렉션 이름은 loggings 된다. (공식 문서 참고)

@Prop() 데코레이터는 문서의 속성을 정의한다. 위의 스키마 정의에서 각 필드의 속성을 정의했다.

@Prop({
    require: true // 필수 필드 여부,
    unique: true // 유니크
    default: 0 // 기본값
    type: mongoose.Schema.Types.Number // 몽고 DB에서 사용하는 필드별 타입
    ref: 'ModelName' // 해당 필드가 다른 Collections를 참고 할 때 모델 이름을 적어줌
})

출처
출처2

나의 경우 Documents에 대해 아직 잘 모르기 때문에 빼고 작성해 주었다. 이후 공부가 끝나면 필요에 따라 추가할 예정😁

로깅 서비스에 로그 저장 로직 구현

먼저 logging.module.ts에 다음과 같이 추가해준다.

@Module({
  imports: [
    MongooseModule.forFeature([{ name: Logging.level, schema: LoggingSchema }]),
  ],
  ...
})

logging.service.ts

import { Injectable, LoggerService } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Logging } from 'src/entities/logging';

@Injectable()
export class LoggingService implements LoggerService {
  constructor(
    @InjectModel(Logging.name) private loggingModel: Model<Logging>,
  ) {}

  async log(message: any) {
    const createLog = await this.loggingModel.create({
      level: Level.log,
      message: message,
    });

    // console.log(createLog);
    console.log(message, 'log 저장 완료, 여기는 테스트');
  }

  error(message: any, ...optionalParams: any[]) {
    //...구현예정
  }

  warn(message: any, ...optionalParams: any[]) {
    //...구현예정
  }

  debug(message: any, ...optionalParams: any[]) {
    //...구현예정
  }

  verbose(message: any, ...optionalParams: any[]) {
    //...구현예정
  }
}

enum Level {
  log = '[LOG]',
  error = '[ERROR]',
  warn = '[WARN]',
  debug = '[DEBUG]',
  verbose = '[VERBOSE]',
}

나의 경우 이 과정에서 throw new ObjectParameterError(obj, 'obj', 'Document'); ObjectParameterError: Parameter "obj" to Document() must be an object, got "[ERROR]" (type string)
를 계속 만나서, 공식문서와 다르게 Document를 지우고 부분 수정했다.

또한, Level타입을 지정해주기 위해 Enum으로 로그의 레벨을 지정해주었다. enum name = values를 입력하면 enum을 사용할때 지정한 값이 할당된다고 한다.(Ts기준)

결과

import { Controller, Get } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { LoggingService } from './logging.service';

@ApiTags('logging')
@Controller('logging')
export class LoggingController {
  constructor(private readonly mylogger: LoggingService) {}

  @Get()
  async loggingTest() {
    console.log('로깅 출력 검사 : ');
    this.mylogger.error('this is error테스트입니다 12.05');
    this.mylogger.log('this is log테스트입니다 12.05');
    // this.appService.getHello();
  }
}

Log가 mongoDB의 클러스트에 잘 적용되는지 확인하기 위해 localhost:.../logger/ 에 로거를 찍어본다.

완성 Git

https://github.com/JaeMyeongSon/KNU-AI-BACKEND/pull/41

참고자료

[NestJS] NestJS에서 MongoDB

0개의 댓글