728x90

보안사고가 잦은 요즘 고객사에서 파일로 남기는 로그가 있었는데

모든 액션에 대해서 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 정보등이 담겨있다'; 

 

 

 

 출처 : http://m.blog.naver.com/0131v/110183988915

반응형

+ Recent posts