[log4j]어떻게 동작을 하나?

atie의 이미지
17994
points
2
points

http://logging.apache.org/log4j/docs/

업계 표준(?)인 log4j가 여기서는 생소한 듯 해서 소개 겸, DB 접속/해제하면 로그가 남는 간단한 유틸리티 클래스를 올려봅니다.
어떻게 동작이 되는지를 보이기 위해, 외부에서 프로퍼티를 쓰는 대신에 코드상에서 조절을 할 수 있도록 만들어 보았습니다. (이렇게 쓰는 것이 후일 확장을 필요하면 용이하기 하기도 하고요.)

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import org.apache.log4j.DailyRollingFileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

/**
 * 
 */

public class DBUtil {

	private static Object lock = new Object();
	private String whatToDo = "";
	private Connection conn = null;
	protected Logger log = null;
	protected PatternLayout pLayout = null;

	public DBUtil(String driver, String url, String usr, String pwd, String task) {
		whatToDo = task;
		try {
			log = Logger.getLogger(whatToDo);
			synchronized (lock) {
				if (log.getAppender(whatToDo) == null) {
					System.out.println("Creating logger for " + whatToDo);
					File f = new File(System.getProperty("ROOT"), "log");
					f.mkdirs();
					f = new File(f, whatToDo + ".log");
					pLayout = new PatternLayout();
					pLayout.setConversionPattern("%d [%t] (%F:%L) - %c - %m%n");
					DailyRollingFileAppender appender = new DailyRollingFileAppender(
							pLayout, f.getAbsolutePath(), "'.'yyyy-MM-dd");
					appender.setName(whatToDo);
					log.addAppender(appender);
					log.setLevel(Level.ALL);
					info(whatToDo + " task started.");
				}
			}
		} catch (Exception e) {
			System.out.println(e);
		}

		try {
			Class.forName(driver);
		} catch (ClassNotFoundException e) {
			log.error("Could not find " + driver);
		}
		
		try {
			conn = DriverManager.getConnection(url, usr, pwd);
		} catch (SQLException e) {
			log.fatal("Could not connect " + url);
		}
		log.debug(url + " connected");

	}

	public void close() throws SQLException {
		if (null != conn) {
			conn.close();
			conn = null;
			info(whatToDo + " task finished.");
		}
	}

	protected void debug(String msg) {
		if (log != null) {
			log.debug(msg);
		} else {
			System.out.println(msg);
		}
	}

	protected void info(String msg) {
		if (log != null) {
			log.info(msg);
		} else {
			System.out.println(msg);
		}
	}

	protected void warn(String msg) {
		if (log != null) {
			log.warn(msg);
		} else {
			System.out.println(msg);
		}
	}

	protected void error(String msg) {
		if (log != null) {
			log.error(msg);
		} else {
			System.out.println(msg);
		}
	}

	protected void fatal(String msg) {
		if (log != null) {
			log.fatal(msg);
		} else {
			System.out.println(msg);
		}
	}

}

atie의 이미지
17994
points

다시 보니, 버그가 있네요. 놀이터이니 안 고쳐 놓겠습니다. ㅎㅎ

0
points

다시 보니, 버그가 있네요. 놀이터이니 안 고쳐 놓겠습니다. ㅎㅎ

iolo의 이미지
2224
points

log4j는 저도 즐겨쓰는 라이브러리인데... 이렇게 소개하는 글을 보니

0
points

log4j는 저도 즐겨쓰는 라이브러리인데... 이렇게 소개하는 글을 보니 반갑네요.

그런데, 제 개인적인 견해로는, 위의 예제는 전형적인 log4j의 사용예라고 보기엔 좀 무리가 있을 듯 싶네요.

atie 씀:

어떻게 동작이 되는지를 보이기 위해, 외부에서 프로퍼티를 쓰는 대신에 코드상에서 조절을 할 수 있도록 만들어 보았습니다. (이렇게 쓰는 것이 후일 확장을 필요하면 용이하기 하기도 하고요.)

이것도 어떤 의미인지 잘 와닿지 않습니다만... 코드상에서 조절한다는 것은 그만큼 융통성이 떨어진다는, 즉 나중에 확장(?)/축소가 어려워진다는 거겠죠?

외람된 말씀이지만, 잘못된 예는 없는 것보다 못합니다.

atie의 이미지
17994
points

저는 잘못된 예라고 생각하지 않는데요. Logger, Appender,

0
points

저는 잘못된 예라고 생각하지 않는데요. Logger, Appender, Layout이 코드 상에서 보여지니 어떻게 연관이 되는지를 예제로 보기가 좋다는 생각입니다.

일반적인 예는 여기를 보면 될테죠.
http://logging.apache.org/log4j/docs/manual.html

프로퍼티 값, 하드코드 한 것은 단지 예일 뿐입니다. 외부로 빼는 것이야 언제든지 될테고요.

"확장한다"는 뜻은, 예를 들어 Multi-Thread에서 XSLT 프로세싱을 하는 경우에 이 클래스가 namespace에 등록이 되어있고, DB 접속 파라메터들이 xsl 상에 존재하면, 별다른 수정없이 (XConnection을 써야겠지만, 지금의 예제를 조금 수정해서 사용해도 됩니다.) 각각의 task에 해당되는 로그를 thread 별로 구분해서 남길 수 있습니다. 특별한 경우인가요?

코드 놀이터이니 가볍게 봐주세요. :wink:

댓글 보기 옵션

원하시는 댓글 전시 방법을 선택한 다음 "설정 저장"을 누르셔서 적용하십시오.