|
|
from java
2009/07/13 16:40
Trackback Address >> http://www.sjava.net/trackback/129
sjava-logging library는 level에 따른 로깅 가능여부를 체크하고 있지는 않습니다.
아래의 Level은 로깅파일의 분류 및 파일의 내용에 기입을 하기 위한 클래스입니다.
그리고, Level에 대한 사용을 위해서는 LevelFactory를 사용하면 됩니다.
LevelFactory.java
package net.sjava.logging;
import java.util.Map;
import java.util.HashMap;
/**
*
* @author mcsong@gmail.com
* @since 2009. 7. 1.
*/
public class LevelFactory {
/** map of levels */
private Map<String, Level> levelMap;
/** singleton instance */
private static LevelFactory instance = new LevelFactory();
/** constructor */
private LevelFactory() {
this.levelMap = new HashMap<String, Level>();
this.levelMap.put("all", new Level(0, "all"));
this.levelMap.put("fatal", new Level(1, "fatal"));
this.levelMap.put("error", new Level(2, "error"));
this.levelMap.put("warn", new Level(3, "warn"));
this.levelMap.put("info", new Level(4, "info"));
this.levelMap.put("debug", new Level(5, "debug"));
this.levelMap.put("trace", new Level(6, "trace"));
this.levelMap.put("system", new Level(7, "system"));
}
/**
*
* @return
*/
public static LevelFactory getInstance() {
return instance;
}
/**
*
* @param level
* @return
*/
public Level getLevel(int level) {
switch (level) {
case 1:
return this.getLevel("fatal");
case 2:
return this.getLevel("error");
case 3:
return this.getLevel("warn");
case 4:
return this.getLevel("info");
case 5:
return this.getLevel("debug");
case 6:
return this.getLevel("trace");
case 7:
return this.getLevel("system");
default:
return this.getLevel("all");
}
}
/**
*
* @param name
* @return
*/
public Level getLevel(String name) {
if (name == null)
return null;
if(!this.levelMap.containsKey(name.toLowerCase()))
return (Level)this.levelMap.get("all");
return (Level)this.levelMap.get(name.toLowerCase());
}
}
Level.java
package net.sjava.logging;
/**
*
* @author mcsong@gmail.com
* @since 2009. 6. 19.
*/
public class Level {
/** level number */
public int level;
/** level name */
public String name;
/**
* Constructor
*
* @param level
* @param name
*/
public Level(int level, String name) {
this.level = level;
this.name = name;
}
/**
* @return the level
*/
public int getLevel() {
return level;
}
/**
* @param level the level to set
*/
public void setLevel(int level) {
this.level = level;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "name is " + this.name + ", level is " + this.level;
}
}
Trackback Address >> http://www.sjava.net/trackback/128
java logging library 입니다.
file에 write 하는 BufferedWriter의 성능을 높이기 위한 tip이 적용되어 있습니다.
config 처리는 sjava-config 코드를 복사해서 패키지 이름만 바꿨습니다. ^^;;
아래 예제는 설정파일과 sjava-logging-1.0.jar를 클래스 패스가 잡힌 위치에 복사를 하시고 돌리시면 됩니다.
예제
package net.sjava.logging.test;
import net.sjava.logging.Logger;
import java.util.Date;
import java.text.SimpleDateFormat;
public class LoggingTest {
private static SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss SSS");
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//load();
// add shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
net.sjava.logging.util.BufferedWriterCacheUtility.shutdown();
}
});
System.out.println("s - " + format.format(new Date()));
for(int i=0; i < 1000000; i++) {
Logger.getInstance().log("aaaaaaaaaaaaaaa");
Logger.getInstance().log("aaaaaaaaaaaaccccccccccccccccccaaa");
Logger.getInstance().log("metoo", "푸푸푸푸푸박.. ");
Logger.getInstance().log("abcded", "abcde", "aaaa b aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
}
System.out.println("e - " + format.format(new Date()));
}
}
설정파일
<?xml version="1.0" encoding="utf-8"?>
<sjava-logging>
<!-- array variable delimeter is "," -->
<!-- do not delete -->
<sjava-service name="config">
<key name="watch" value="false" /> <!-- true, false -->
<key name="period" value="60" /> <!-- 60 seconds -->
</sjava-service>
<!-- 로그서버 설정 -->
<sjava-service name="logging">
<key name="baseDir" value="d:\sjava-logging" />
<key name="serviceDir" value="default" />
<key name="fileName" value="default" />
<key name="fileExt" value="log" />
<key name="bufferSize" value="1024" />
<!-- dayily(1), hourly(2), minutes(3) -->
<key name="strategy" value="2" />
</sjava-service>
</sjava-logging>
바이너리 & 소스
Trackback Address >> http://www.sjava.net/trackback/127
Trackback Address >> http://www.sjava.net/trackback/126
from java
2009/07/08 12:07
파일에 로그를 남긴다거나 데이타를 쓰기위해서 java.io.File 객체를 써도 되지만, 성능을 위해서 BufferedWriter를 많이 이용하게 됩니다. 특히 로그 라이브러리나 로깅 유틸리티 클래스에서 거의 대부분 사용할 것으로 생각이 드네요..
그래서, 생각한 방법이 BufferedWriter를 캐싱하는 것입니다.
아래 코드의 shutdown() 메쏘드는 ShudownHooking으로 등록된 쓰레드가 프로세스가 종료되면 호출을 해서 버퍼에 남아있는 내용을 기록하도록 되어 있습니다.
BufferedWriterCacheUtility.java
package net.sjava.io.test;
import java.util.Map;
import java.util.LinkedHashMap;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.util.Iterator;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BufferedWriterCacheUtility {
/** max cache size */
private static final int size = 10;
/** lock */
private static Lock lock = new ReentrantLock();
/** initialized lru cache */
private static Map<String, BufferedWriter> cache = new LinkedHashMap<String, BufferedWriter> (size, .75F, true) {
private static final long serialVersionUID = 1L;
protected boolean removeEldestEntry(Map.Entry<String, BufferedWriter> eldest) {
if(size() > size) {
try {
// flush and close before deleted
eldest.getValue().close();
} catch(java.io.IOException e) {
// ignore
}
}
return size() > size;
}
};
/**
*
* @param fileName
* @return
*/
public static BufferedWriter createBufferedWriter(String fileName) {
lock.lock();
try{
if(cache.containsKey(fileName))
return cache.get(fileName);
return new BufferedWriter(new FileWriter(fileName, true), 1024);
} catch(java.io.IOException e) {
e.printStackTrace();
return null;
} finally {
lock.unlock();
}
}
/**
*
* @param fileName
* @param writer
*/
public static void close(String fileName, BufferedWriter writer) {
lock.lock();
try {
cache.put(fileName, writer);
} finally {
lock.unlock();
}
}
/** shutdown hooking thread call */
public static void shutdown() {
// 아래의 코드를 통해서 종료가 되더라도 다 flush 하고 종료한다.
Iterator<BufferedWriter> iter = null;
try {
iter = cache.values().iterator();
while (iter.hasNext()){
iter.next().close();
//iter.next().close();
}
}catch(java.io.IOException e) {
e.printStackTrace();
}
}
}
아래 코드는 BufferedWriter를 사용하는 방법에 대한 3가지의 예입니다.
물론 2번째(bwriter02)를 사용하는 예가 가장 빠르겠지만, 3번째 예는 여러개의 fileName을 가지고 file write를 하기에 가장 좋은 방법으로 생각이 듭니다.
BufferedWriterTest.java
package net.sjava.io.test;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
public class BufferedWriterTest {
private static SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss SSS");
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//load();
System.out.println("s - " + format.format(new Date()));
BufferedWriter bwriter01 = null;
try {
for(int i=0; i < 100000; i++) {
bwriter01 = new BufferedWriter(new FileWriter("c:\\test01.txt", true), 1024);
bwriter01.write("aaaaaaaaaaaaccccccccccccccccccaaa");
bwriter01.newLine();
bwriter01.flush();
bwriter01.close();
}
} catch(java.io.IOException e) {
e.printStackTrace();
}
System.out.println("e - " + format.format(new Date()));
System.out.println("s - " + format.format(new Date()));
BufferedWriter bwriter02 = null;
try {
bwriter02 = new BufferedWriter(new FileWriter("c:\\test02.txt", true), 1024);
for(int i=0; i < 100000; i++) {
bwriter02.write("aaaaaaaaaaaaccccccccccccccccccaaa");
bwriter02.newLine();
}
bwriter02.flush();
bwriter02.close();
} catch(java.io.IOException e) {
e.printStackTrace();
}
System.out.println("e - " + format.format(new Date()));
// 날짜별 혹은 서비스별로 로깅을 해야 될경우
System.out.println("s - " + format.format(new Date()));
BufferedWriter bwriter03 = null;
try {
for(int i=0; i < 100000; i++) {
bwriter03 = BufferedWriterCacheUtility.createBufferedWriter("c:\\test03.txt");
bwriter03.write("aaaaaaaaaaaaccccccccccccccccccaaa");
bwriter03.newLine();
BufferedWriterCacheUtility.close("c:\\test03.txt", bwriter03);
}
} catch(java.io.IOException e) {
e.printStackTrace();
}
System.out.println("e - " + format.format(new Date()));
}
}
여담이지만, java.io.BufferedWriter 소스를 보면, write시에 lock을 잡고 씁니다.
아래와 같은 코드를 많이 사용하지만요..
lock.lock();
try {
bWriter.write("000000000000000");
}catch(java.io.IOException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
위 코드보다는 아래코드를 사용하는게 맞겠습니다.
try {
bWriter.write("000000000000000");
}catch(java.io.IOException e) {
e.printStackTrace();
}
Trackback Address >> http://www.sjava.net/trackback/125
from ooad
2009/07/06 10:30
Trackback Address >> http://www.sjava.net/trackback/124
Trackback Address >> http://www.sjava.net/trackback/123
from java
2009/07/01 10:57
일정 시간이 지난뒤에 실행을 시켜주는 Utility 클래스로 Java에서는 Timer 클래스가 있습니다.
Timer 클래스를 사용하다 보니, 동일한 기능의 다른 메쏘드(schedule, scheduleAtFixedRate)가 있어서 차이점에 대해서 살펴보았습니다.
Java API에서는 Timer의 schedule과 scheduleAtFixedRate 메쏘드 둘다,
지정한 태스크가 지정한 지연의 후에 시작되어 「고정 빈도 실행」을 반복하도록 스케줄 합니다. 그 후는 지정한 기간과는 별도로 거의 일정한 간격으로 실행됩니다.
Java API의 schedule 메쏘드에 대한 내용은,
고정 지연 실행에서는 전의 실행의 실제의 실행 시간을 기준으로의해 각각의 실행이 스케줄 됩니다. 어떠한 이유로써 실행이 지연 했을 경우 (가비지 컬렉션, 그 외의 백그라운드 작업 등), 그 후의 실행도 지연 됩니다. 최종적으로 실행의 빈도는 보통, 지정한 기간의 대응하는 빈도보다 약간 늦어집니다 (기본이 되는 Object.wait(long)를 지지하고 있는 시스템 클록이 정확이라고 하는 전제로).
Java API의 scheduleAtFixedRate 메쏘드에 대한 내용은,
고정 빈도 실행에서는 최초의 실행의 스케줄 된 실행 시간을 기준으로의해 각각의 실행이 스케줄 됩니다. 어떠한 이유로써 실행이 지연 했을 경우 (가비지 컬렉션 또는 그 외의 백그라운드 작업 등), 「지연을 되찾는다」위해 2개 이상의 실행이 연속해 행해집니다. 최종적으로 실행의 빈도는 지정한 기간의 대응하는 빈도와 같게 됩니다 (기본이 되는 Object.wait(long)를 지지하고 있는 시스템 클록이 정확이라고 하는 전제로).
따라서, 위 내용을 토대로 schedule되는 job의 수행 횟수 또는 비교적 critical한 수행을 해야 되는 경우에는 scheduleAtFixedRate 메쏘드를 사용해야 될것 같습니다.
예제코드
TimerTest.java
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
Timer timer = new Timer("test");
timer.schedule(new TimerTask() {
public void run(){
try {
Thread.sleep(2000);
System.out.println("- schedule job run at " + new java.util.Date());
} catch(Exception e) {
e.printStackTrace();
}
}
}, 0, 1000 * 1); // 10 초
timer.scheduleAtFixedRate(new TimerTask() {
public void run(){
try {
Thread.sleep(2000);
System.out.println("- scheduleatfixedrate run at " + new java.util.Date());
} catch(Exception e) {
e.printStackTrace();
}
}
}, 0, 1000 * 1); // 10 초
}
}
예제화면
그리고, Timer에 schedule된 Task가 중간에 exception이 발생하면, 그 Timer의 모든 task들이 실행이 안 되네요. ^^;;
* reference
- http://rijusnotes.blogspot.com/2009/06/how-to-implement-scheduler-in-java.html
- http://blog.naver.com/saojung50/120050451007
Trackback Address >> http://www.sjava.net/trackback/122
|
|
|