로그 작성 시 주의사항
로그의 생명 주기입니다. 로그가 저장되는 저장소의 용량, 파일 혹은 DB라도 삭제는 언제할 것인지? 이러한 계획을 명확하게 수립하고 운영해야 디스크 용량 부족과 같은 갑작스러운 장애를 방지할 수 있습니다.
그리고 로그에 너무 쉽게 개인정보, 시스템 계정 정보가 작성되는 경우가 있습니다. 이는 개인정보법을 위배할 수도 보안적 취약점을 가지기 때문에 꼭 주의할 필요가 있습니다. 로그 생명 주기는 DevOps, Infra 관리를 시스템적으로 하기 때문에 사전에 충분히 감지 및 대처할 수 있지만 민감정보가 로그에 작성되는 것은 철저히 개발자의 실수입니다.
log4j는 로그를 자동으로 출력해 주는 오픈소스 라이브러리입니다.
출력하고자 하는 log를 "콘솔", "로그 파일", "DB 로그" 등으로 남길 수 있습니다.
- log4j는 속도에 최적화
- log4j는 이름있는 로그 계층에 기반
- log4j는 fail-stop이지만 신뢰성은 없음
- log4j는 thread-safe(멀티스레드 환경에서 사용해도 안전하다:역주).
- log4j는 융통성이 풍부
- 설정 파일은 property 파일과 XML 형식으로 실행 중 수정 적용 가능
- log4j는 처음부터 자바의 예외를 처리하기 위해 디자인
- log4j는 출력을 파일, 콘솔, java.io.OutputStream, java.io.Writer, TCP를 사용하는 원격서버, 원격 Unix Syslog 데몬, - 원격 JMS 구독자, 윈도우NT EventLog로 보낼 수 있고, 심지어는 e-mail로 보낼 수도 있음
- log4j는 다음 6단계의 장애레벨을 사용. < TRACE(추가), DEBUG, INFO, WARN, ERROR, FATAL >
- 로그 출력의 형식은 Layout 클래스를 확장함으로써 쉽게 바꿀 수 있음
- 로그가 출력될 대상과 출력 방법은 Appender 인터페이스로 할 수 있음
- log4j는 로거 하나에 다수의, 출력을 담당하는 appender를 할당할 수 있음
- log4j는 국제화를 지원
일반적으로 PatternLayout을 사용하는 것이 디버깅에 가장 적합함
먼저 Maven 프로젝트에 log4j를 dependency 추가합니다.
[pom.xml]
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
위의 xml 내용은 mvnrepository에 log4j를 검색해서 나오는 Apache Log4j의 최신버전 입니다.
그냥 pom.xml에 dependencies 안에 위의 내용을 붙여 넣어서 사용할 라이브러리라고 선언해줍니다.
src/main/resource 디렉터리 안에 "log4j.properties"를 추가합니다.
그리고 아래와 같은 내용을 붙여 넣습니다.
# rootLogger
# Logger Level(Fatal > Error > Warning > Info > Debug > Trace), 객체명, 객체명
log4j.rootLogger=DEBUG, consoleAppender, fileAppender, sql
# rootLogger 에서 정의한 객체에 타입과 기능을 정의
# log4j.appender.consoleAppender => Console에 출력해주는 객체
# org.apache.log4j.ConsoleAppender : 콘솔애 출력해 주겠다.
log4j.appender.consoleAppender=org.apache.log4j.ConsoleAppender
log4j.appender.consoleAppender.Threshold=All
# layout : console에 출력을 할 때 ConversionPattern 형태로 출력을 해준다.
log4j.appender.consoleAppender.layout=org.apache.log4j.PatternLayout
# log4j.appender.consoleAppender.layout.ConversionPattern=[%t] %-5p %c %x - %m%n
log4j.appender.consoleAppender.layout.ConversionPattern=[%d] [%-5p] %c %x - %m%n
# log4j.appender.fileAppender => 파일로 저장하겠다.
# org.apache.log4j.RollingFileAppender 하루에 한번씩 파일을 생성해서 로그를 저장해 주겠다.
log4j.appender.fileAppender=org.apache.log4j.DailyRollingFileAppender
# File : 파일의 위치가 어디고 어떠한 파일을 명으로 생성하겠다.
# log4j.appender.fileAppender.File=demoApplication.log
log4j.appender.fileAppender.File=c:/log/log4j.log
# 하루가 지난 파일은 goodee.log에서 goodee.2021-04-12 이렇게 바꾸겠다.
log4j.appender.fileAppender.DatePattern='.'yyyy-MM-dd
log4j.appender.fileAppender.Threshold=All
log4j.appender.fileAppender.layout=org.apache.log4j.PatternLayout
# log4j.appender.fileAppender.layout.ConversionPattern=[%t] %-5p %c %x - %m%n
log4j.appender.fileAppender.layout.ConversionPattern=[%d] [%-5p] [%13F\:%L] - %m%n
log4j.rootLogger=DEBUG, consoleAppender, fileAppender, sql
log4j.appender.consoleAppender=org.apache.log4j.ConsoleAppender
log4j.appender.consoleAppender.Threshold=All
log4j.appender.consoleAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.consoleAppender.layout.ConversionPattern=[%d] [%-5p] %c %x - %m%n
log4j.appender.fileAppender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.fileAppender.File=c:/log/log4j.log
log4j.appender.fileAppender.DatePattern='.'yyyy-MM-dd
log4j.appender.fileAppender.Threshold=All
log4j.appender.fileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.fileAppender.layout.ConversionPattern=[%d] [%-5p] [%13F\:%L] - %m%n
다음과 같이 userLogger를 출력해 본다.
위의 userLogger 코드에서 Log4j 레벨을 볼 수 있습니다.
위의 결과처럼 로그가 나오는 것은 "log4j.properties" 설정에 따라 위와 같은 모양이 나옵니다.
log4j.appender.consoleAppender.layout.ConversionPattern=[%d] [%-5p] %c %x - %m%n
Conversion 패턴입니다.
- [%d] : 날짜와 시간입니다.
- [%-5p] : 5자리 글자 고정으로 디버그 레벨을 나타냅니다.
- %c : 카테고리가 출력이 됩니다.
- %x : 로깅이 발생한 thread와 관련된 NDC(nested -diagnostic context) 출력됩니다.
- %m : 로그 내용이 출력됩니다.
- %n : 개행문자 입니다.
log4j.appender.fileAppender.File=c:/log/log4j.log
log4j는 log파일로 출력이 가능합니다.
위의 경로로 통해서 파일에 잘 출력이 되었나 확인해 봅니다.
JDBCAppender를 사용하여 데이터베이스에 log를 저장하는 방법입니다.
# 위에 선언된 객체인 sql에 JDBC에 저장할 수 있는 JDBCAppender를 연결한다
log4j.appender.sql=org.apache.log4j.jdbc.JDBCAppender
# 선언된 객체에 필요한 접속 정보 (driver, url, user, password)를 입력 한다
log4j.appender.sql.URL=[데이터베이스 URL]
log4j.appender.sql.driver=[드라이버]
log4j.appender.sql.user=[유저네임]
log4j.appender.sql.password=[패스워드]
# 테이블에 insert하는 쿼리를 작성한다
log4j.appender.sql.sql=INSERT INTO LOGS VALUES ('%x', SYSDATE ,'%C','%p','%m')
log4j.appender.sql.layout=org.apache.log4j.PatternLayout
주의 : 위의 설정의 중간쯤 보시면 접속정보를 적는 부분이 있습니다.
접속정보를 꼭 자신의 DB환경에 맞게 입력해 주시기 바랍니다.
[ ]도 지우시고 입력하셔야 합니다.
log4j.appender.sql.URL=jdbc:mysql://localhost/test
log4j.appender.sql.driver=com.mysql.jdbc.Driver
log4j.appender.sql.user=root
log4j.appender.sql.password=password
SYSDATE는 Oracle DB 기준입니다.
mysql을 사용하시는 분은 now() 를 사용하셔서 차질이 없기 바랍니다.
# 테이블에 insert하는 쿼리를 작성한다
log4j.appender.sql.sql=INSERT INTO LOGS VALUES ('%x', SYSDATE ,'%C','%p','%m')
log4j.appender.sql.layout=org.apache.log4j.PatternLayout
위의 Log4j_Test를 통해서 로그를 출력하면 자연스럽게 DB Table에 로그가 생기는것을 볼 수 있습니다.