log4j, 파일, 디비 DB, JDBCAppender, 중복, 로그, MDC, NDC
보안사고가 잦은 요즘 고객사에서 파일로 남기는 로그가 있었는데
모든 액션에 대해서 6하원칙 원인 분석이 가능하도록 DB에 남겨달라는 요청이 있다.
확인을 해보니 log4j 에서 파일만 지원하는 줄 알았는데 콘솔, DB 에 저장 가능하다고 한다.
JDBCAppender 를 검색해보면 여러가지 나오는데
MDC까지 활용을 하면 log4j에서 지원하는 기본기능에 더해서 내가 원하는 변수들도 저장이 가능하다.
MDC는 hashtable 타입같은거고 NDC는 stack 형식이며
NDC는 메모리 부하가 있다고 하니 꼭 remove를 해야 한다.
웬만하면 MDC 쓰는 편이 명확하고 좋은 것 같음. (org.apache.log4j.MDC)
1. 스프링의 인터셉터를 생성 혹은 추가
<bean id="beanNameUrlMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="LogInterceptor"/>
</list>
</property>
<property name="order"><value>1</value></property>
</bean>
2. LogInterceptor 라는 bean 설정
<bean id="LogInterceptor" class="원하는 패키지 경로.LogInterceptor" />
3. LogInterceptor 클래스에서 HandlerInterceptorAdapter 를 extends 받아서 구현
아래 내용은 preHandle 메소드안에서 구현한다.
String url = request.getServletPath();
String ip = request.getRemoteAddr();
Enumeration param = request.getParameterNames();
while(param.hasMoreElements())
{
String name = (String)param.nextElement();
String value = request.getParameter(name);
if(null != value && !"".equals(value))
{
params += ("["+name+":"+value+"]");
}
}
MDC.put("ACCOUNT_ID", accountId);
MDC.put("ACCOUNT_IP", ip);
MDC.put("PAGE_URL", url);
MDC.put("PARAMS", params);
return true;
4. log4j.properties 에서 아래 내용 추가 (아래내용은 파일과 DB를 동시에 남기는 설정)
#================================================================================
# ibatis shkim.add.IBATIS_DB_LOG
#================================================================================
log4j.logger.com.ibatis=DEBUG, IBATIS_LOG, IBATIS_DB_LOG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG, IBATIS_LOG, IBATIS_DB_LOG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG, IBATIS_LOG, IBATIS_DB_LOG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG, IBATIS_LOG, IBATIS_DB_LOG
log4j.logger.java.sql.Connection=DEBUG, IBATIS_LOG, IBATIS_DB_LOG
log4j.logger.java.sql.Statement=DEBUG, IBATIS_LOG
log4j.logger.java.sql.PreparedStatement=DEBUG, IBATIS_LOG
#log4j.logger.java.sql.ResultSet=DEBUG, IBATIS_LOG
log4j.logger.spectra.base.sql.ibatis=DEBUG, IBATIS_LOG, IBATIS_DB_LOG
log4j.appender.IBATIS_LOG=org.apache.log4j.DailyRollingFileAppender
log4j.appender.IBATIS_LOG.Threshold=DEBUG
log4j.appender.IBATIS_LOG.File=원하는파일저장경로/ibatis.log
log4j.appender.IBATIS_LOG.DatePattern='.'yyyy-MM-dd
log4j.appender.IBATIS_LOG.layout=org.apache.log4j.PatternLayout
log4j.appender.IBATIS_LOG.layout.ConversionPattern=%d{MM-dd HH:mm:ss} %-10t %-10x %-5p %-24.24C{2} %-30.30M %m%n
log4j.appender.IBATIS_LOG.ImmediateFlush=True
#DB LOG SETTING s
log4j.appender.IBATIS_DB_LOG=org.apache.log4j.jdbcplus.JDBCAppender
log4j.appender.IBATIS_DB_LOG.url=jdbc:oracle:thin:@디비아이피혹은호스트:1521:orcl
log4j.appender.IBATIS_DB_LOG.dbclass=oracle.jdbc.driver.OracleDriver
log4j.appender.IBATIS_DB_LOG.username=디비접속계정
log4j.appender.IBATIS_DB_LOG.password=디비접속비밀번호
log4j.appender.IBATIS_DB_LOG.sql=INSERT INTO T_ACCOUNT_ACTION_LOG( LOG_DATE,ACCOUNT_ID,ACCOUNT_IP,PAGE_URL,QUERY_NAME,PARAMS ) values (to_char(SYSDATE, 'YYYYMMDDhh24miss'),'@MDC:ACCOUNT_ID@','@MDC:ACCOUNT_IP@','@MDC:PAGE_URL@','@MSG@','@MDC:PARAMS@')
log4j.appender.IBATIS_DB_LOG.layout=org.apache.log4j.PatternLayout
log4j.appender.IBATIS_DB_LOG.layout.ConversionPattern=%m%n
log4j.appender.IBATIS_DB_LOG.buffer=1
log4j.appender.IBATIS_DB_LOG.commit=true
log4j.appender.IBATIS_DB_LOG.quoteReplace=true
log4j.appender.IBATIS_DB_LOG.throwableMaxChars=3000
#DB LOG SETTING e
5. 테이블 생성 쿼리
--------------------------------------------------------------------------------
-- 상담사 로그 저장 테이블 생성 스크립트
-- 작성자 : shkim,
-- 작성일 : 2014.01.23
--------------------------------------------------------------------------------
-- Table 테이블명
CREATE TABLE 테이블명
(
LOG_DATE CHAR(14) DEFAULT to_char(sysdate, 'YYYYMMDDhh24miss'),
ACCOUNT_ID VARCHAR2(128 BYTE) ,
ACCOUNT_IP VARCHAR2(128 BYTE) ,
PAGE_URL VARCHAR2(128 BYTE) ,
QUERY_NAME VARCHAR2(500 BYTE) ,
PARAMS VARCHAR2(4000 BYTE)
);
CREATE INDEX IDX_LOG_DATE_ID_ASC ON 테이블명(LOG_DATE, ACCOUNT_ID);
CREATE INDEX IDX_LOG_DATE_ID_DESC ON 테이블명(LOG_DATE DESC, ACCOUNT_ID);
COMMENT ON TABLE 테이블명 IS 'enomix사용자액션저장테이블';
COMMENT ON COLUMN 테이블명.LOG_DATE IS '액션시간';
COMMENT ON COLUMN 테이블명.ACCOUNT_ID IS '사용자ID null일 경우 시스템호출 혹은 로그인 전 발생한 액션';
COMMENT ON COLUMN 테이블명.ACCOUNT_IP IS '사용자IP null일 경우 시스템호출';
COMMENT ON COLUMN 테이블명.PAGE_URL IS '호출URL null일 경우 시스템호출';
COMMENT ON COLUMN 테이블명.QUERY_NAME IS '호출쿼리명';
COMMENT ON COLUMN 테이블명.PARAMS IS '파라미터로 검색조건이나 검색기간 기타 request 정보등이 담겨있다';
출처 : 김상현 블로그 <https://m.blog.naver.com/PostView.nhn?blogId=0131v&logNo=110183988915&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F>
'DataBase > Oracle' 카테고리의 다른 글
분석함수 - RANK OVER(), ROW_NUMBER() OVER() (0) | 2017.02.04 |
---|---|
오라클 테이블스페이스 용량 조회, oracle tablespace 용량 조회 (0) | 2017.01.04 |
Pragma Autonomous_Transaction 사용방법 (0) | 2016.08.03 |
오라클 사용자 생성 및 권한주기 (0) | 2015.10.30 |
Merge 기본/활용 (0) | 2015.10.05 |