태그 보관물: log

DailyRollingFileAppender & RollingFileAppender

입사하였을 때 팀에서 사용하던 로깅 방식은 RollingFileAppender 를 이용하여 로깅을 하는 방법이었습니다. MaxFileSize와 File생성 개수의 제한을 두고 사용을 했습니다. 하지만 그렇게 로그를 쓰는 방식은 로그를 보기가 좀 어렵다는 단점이 있습니다.

제가 서버를 직접 관리하면 로그를 보는 데는 문제가 되지 않겠지만 전화 지원 또는 메일로 로깅을 요청하는 경우에는 해당파일에 대한 로그가 정확하게 언제까지 쌓여 있는지 확인이 불가 했습니다.

그래서 제가 선택한 방법은 DailyRollingFileAppender를 이용하여 하루에 한번씩 로그 파일을 나누는 방법을 사용했습니다. 그렇게 되면 관리자에게 로그 파일을 요청할 때 하루 전과 오늘 날짜의 파일만 요청하면 장애 원인에 대한 처리를 원활 하게 할 수 있었습니다.

지금까지는 문제가 안되었지만 문제가 될만한 부분에 대한 말을 들었습니다.
RollingFileAppender는 MaxFileSize와 파일 개수의 제한이 있습니다. 그렇기 때문에 혹시 WAS혹은 Socket에서 잘못된 무한 루프가 돌게 되도 Disk가 Full 되는 경우는 발생이 안될 것 같습니다.

그렇지만 DailyRollingFileAppender의 경우에는 MaxFileSize와 파일 개수에 제한이 없습니다. 그렇기 때문에 하루를 기준으로 쌓게 되면 24시간 동안 무한루프를 돌게 되면 충분히 DISK가 Full이 될 수 있습니다. 즉 잠재적인 장애 원인이 됩니다.

이것을 해결하기 위해서는 DailyRollingFileAppender에 MaxFileSize와 파일 개수의 제한을 두는 부분을 추가해서 사용을 하면 해결이 가능할 것 같습니다.

이미 구글에서 검색을 하게 되면 DailyRollingFileAppender를 수정한 버전이 많이 있는것 같습니다. RollingFileAppender 와 DailyRollingFileAppender에 대해 문제점이 발생될 수 있는지 먼저 테스트를 해보고 수정 부분에 대해 다시 한번 테스트를 진행 해봐야겠습니다.

2번째 포스팅에서 테스트 결과로 확인을 해봐야겠습니다.

이 글은 java 카테고리에 분류되었고 태그가 있으며 님에 의해 에 작성되었습니다.

Application log 압축해서 다운 받아보자.

안녕하세요. 오늘도 열심히 일을 하는 초보 개발자 입니다. 솔루션이 아직 미흡해서 로그 관리 하기가 쉽지가 않습니다. 담당자에게 로그 파일을 요청을 하려면 원격 데스크톱 연결을 해서 파일을 복사해서 압축해서 메일로 보내달라고 해야 하는데 원격 데스크톱에 수시로 접속하는 저희 개발자들이야 쉽게 할 수 있지만 일반인 분들은 “얘네들이 무슨 소리를 하는 건가…“ 라는 표정을 보여주십니다. 그래서 조금 이라도 쉽게 하기 위해서 로그를 압축해서 관리자 PC로 다운 받을 수 있게 하면 좋겠다 라는 생각을 했습니다.

  1. 로그 디렉토리 경로를 구한다.
  2. 로그 파일을 압축한다.
  3. 압축 파일을 관리자 PC 에 다운 받게 한다.

로직은 위와 같은 순서로 생각을 했습니다. 

 


 

로직 처리

  1. 디렉토리 경로를 구하는 것은 생각보다 쉽지 않았습니다. 구글에서 검색해본 결과 보안 때문에 파일 선택에서 디렉토리 설정하는 것은 막혀 있다고 합니다. 그래도 하려면 ActiveX를 사용해서 해야 한다고 하는데 그렇게 까지는 하고 싶지 않습니다..
  2. 로그 파일 압축은 Java의 ZipOuputStream 을 사용해서 하려고 했습니다. 문제점은 저희 로그 파일이야 2 Depth 밖에 되지 않지만 만약 Depth 가 아주 높거나 하면 문제가 되는 겁니다. 그래서 Depth 가 크면 같은 로직으로 처리 되는 Recursion 을 사용해보자는 생각이 들었습니다. 그래서 “Java Directory Recursion” 구글링을 시작했습니다. 많은 분들이 저와 같은 생각을 하고 계신 것을 느꼈습니다. 그 중 하나를 찾아서 테스트 했습니다.
  3. 압축 파일을 관리자 PC에 다운 받게 하는 방법은 JSP 파일 다운로드 하는 방법을 참조 했습니다. response.setContentType 설정에 ‘application x-zip compressed’를 사용해서 다운을 받을 수 있게 해봤습니다.

 

Source Code

FileRecurser.java

import java.io.File;
import java.io.FilenameFilter;
import java.util.Collection;
import java.util.Vector;

/**
* 디렉토리에서 파일 목록을 구하는 클래스
* 참조 : {@link http://snippets.dzone.com/posts/show/1875}
*
*/
public class FileRecurser {

/**
* 디렉토리에서 파일 목록을 리턴한다.
* @param directory 탐색 경로
* @param filter
* @param recurse
* @return array of File
*/
public static File[] listFilesAsArray(File directory, FilenameFilter filter, int recurse) {
// 재귀 호출을 시작한다.
Collection files = listFiles(directory, filter, recurse);
File[] arr = new File[files.size()];
return files.toArray(arr);
}

/**
* 해당하는 디렉토리에서 파일만 저장하는 객체를 리턴한다.
* @param directory
* @param filter
* @param recurse
* @return Vector
*/
private static Collection listFiles(File directory,
FilenameFilter filter, int recurse) {
// 해당 디렉토리에 있는 파일 목록을 저장하는 객체
Vector files = new Vector();
// 모든 파일과 디렉토리 목록을 꺼낸다.
File[] entries = directory.listFiles();
// 목록이 없다면 종료.
if(entries != null) {
for (File entry : entries) {
// 필터와 파일명에 '.log' 를 포함한다면 파일 목록 객체에 넣는다.
if(filter == null || filter.accept(directory, entry.getName())) {
files.add(entry);
}

/*
* 재귀를 한다.
* 해당 디렉토리에 파일이 없을때까지 반복한다.
*/
if((recurse 0 && entry.isDirectory())) {
recurse--;
files.addAll(listFiles(entry, filter, recurse));
recurse++;
}
}
}
return files;
}

}

Controller.downloadLogFile

/**
* 로그 파일을 다운 받는다.
* @param request
* @param response
*/
public void downloadLogFile(HttpServletRequest request, HttpServletResponse response) {

// Buffer 사이즈를 설정한다.
byte[] buffer = new byte[4096];

// 파일 이름용 시간 포맷을 구한다.
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddhhmmss");
ServletContext ctx = request.getSession().getServletContext();
String path = ctx.getRealPath("/WEB-INF/upload") + File.separator;

// 파일 명을 설정한다.

String fileName = path + formatter.format(new Date())+"_uc.zip";

try {
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(fileName));
File logDir = new File("D:\\cafe\\logs");
// 필터를 설정한다.
FilenameFilter logFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
// 파일명에 .log 가 포함되면 log파일이다.
return name.contains(".log");
}
};
FileRecurser fr = new FileRecurser();
// 파일 목록을 구한다.
File[] logFiles = fr.listFilesAsArray(logDir, logFilter, -1);
for (File file : logFiles) {
FileInputStream fis = new FileInputStream(file);
out.putNextEntry(new ZipEntry(file.getName()));
int len = 0;
while((len = fis.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
out.closeEntry();
fis.close();
}
out.close();

} catch (FileNotFoundException e) {
logger.warn("디렉토리를 찾을 수 없습니다.", e);
} catch (Exception e) {
logger.warn("예외 발생", e);
}
// ZIP 파일 다운로드 설정을 한다.
response.setContentType("application/x-zip-compressed; charset=utf-8");
response.setHeader("Content-Disposition", "inline; filename="+new File(fileName).getName());

try {
OutputStream out = response.getOutputStream();
InputStream in = new FileInputStream(new File(fileName));
byte[] buf = new byte[4096];
int read = in.read(buffer);
while (read != -1) {
out.write(buffer, 0, read);
read = in.read(buffer);
}
} catch (FileNotFoundException e) {
logger.warn("파일을 찾을 수 없습니다.",e);
} catch (Exception e) {
logger.warn("예외가 발생 했습니다.", e);
}
}// downloadLogFile

ContentType 설정을 통해서 다운 받을 수 있게 한다. 위와 같은 생각을 하게 된 것은 텍스트 파일의 경우에는 압축하면 용량이 많이 줄어서 대용량 메일이 아니더라도 보낼 수 있기 때문에 생각하게 되었습니다.파일을 첨부 하려고 했는데 첨부가 안되네요.

 


참고

  1. Recursion 을 사용한 파일 탐색
  2. While을 사용한 파일 탐색
  3. Zip 파일을 사용한 로그 압축하기
  4. JSP 파일 다운로드