Java File 모니터링

Java File Walk활용하여 파일을 모니터링해보자

git source 소스 링크

왜 이러한 것이 추가되었을까에 대한 고찰?

협력사 또는 회사 내부에서 특정 시간에 데이터(파일)들이 꾸준하게 ftp를 통해 파일이 생성되어진다고 가정을 하였을떄!

  • 배치로 작동하는것이 옳을가? (만약 파일이 너무 무거워서 배치가 돌아야 할 시간에 정상적으로 업로드 되지 않은 경우)
  • 누군가 같은 정해진 네이밍으로 한 파일을 올리고 잘못올림을 감지하고 다시 올렸을 경우(어찌 할것인가? 직접 서버로 들어가서 수정된시간을 볼것인가?)

위와 같은 고민에서 시작한 선배 개발자의 의견에 키워드를 얻게되었고 해결방법에 대한 가이드를 전달받아 이 블로그를 작성합니다.

1. 키워드

WatchService ( 자바 1.7 도입 ) - 옵져버라 생각

StandardWatchEventKinds

  • ENTRY_CREATE : 생성시
  • ENTRY_DELETE : 삭제시
  • ENTRY_MODIFY : 수정시

2. 파일 생성 감지

생성, 수정, 삭제에 대한 피드

FileObserver.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public static void main(String[] args) {

String searchFileFolder = "search_file";
String targetDirectory = getWorkingDirectory() + "/" + searchFileFolder;
observeFileCreated(targetDirectory);
}

private static void observeFileCreated(String targetDirectory) {


Path faxFolder = Paths.get(targetDirectory);

try {

WatchService fileWatchService = FileSystems.getDefault().newWatchService();
faxFolder.register(fileWatchService, StandardWatchEventKinds.ENTRY_CREATE);

boolean valid = true;
do {
WatchKey watchKey = fileWatchService.take();

for (WatchEvent event : watchKey.pollEvents()) {
WatchEvent.Kind kind = event.kind();
if (StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())) {
String fileName = event.context().toString();
System.out.println("start to notify file Created :" + fileName + " , time : " + LocalDateTime.now());
}
}
valid = watchKey.reset();

} while (valid);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}

run후 파일을 새로 생성해보자

console.log

1
2
start to notify file Created :test1 복사본.txt , time : 2019-08-11T16:11:29.992
start to notify file Created :test3 복사본.txt , time : 2019-08-11T16:11:29.992

  1. 파일 생성, 삭제 수정에 대한 모든 부분을 커버할수 있도록 해보자

FileObserverUpgrade.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public static void main(String[] args) {

String searchFileFolder = "search_file";
String targetDirectory = getWorkingDirectory() + "/" + searchFileFolder;
observeFileStatus(targetDirectory);

}

private static void observeFileStatus(String targetDirectory) {


Path faxFolder = Paths.get(targetDirectory);

try {

//워치 서비스에 이벤트들 등
WatchService fileWatchService = FileSystems.getDefault().newWatchService();
faxFolder.register(fileWatchService,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_MODIFY,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.OVERFLOW

);

boolean valid = true;
do {
WatchKey watchKey = fileWatchService.take();

for (WatchEvent event : watchKey.pollEvents()) {

if (StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())) {
String fileName = event.context().toString();
System.out.println("start to notify file Created :" + fileName + " , time : " + LocalDateTime.now());
}else if(StandardWatchEventKinds.ENTRY_MODIFY.equals(event.kind())){
String fileName = event.context().toString();
System.out.println("start to notify file modified :" + fileName + " , time : " + LocalDateTime.now());
}else if(StandardWatchEventKinds.ENTRY_DELETE.equals(event.kind())){
String fileName = event.context().toString();
System.out.println("start to notify file deleted :" + fileName + " , time : " + LocalDateTime.now());
}else if(StandardWatchEventKinds.OVERFLOW.equals(event.kind())) {
String fileName = event.context().toString();
System.out.println("start to notify OVERFLOW time : " + LocalDateTime.now());
}else{
System.out.println("UNKNOWN EVENT ......");
}
}
valid = watchKey.reset();

} while (valid);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}

console.log

1
2
3
4
start to notify file Created :test1 복사본 2.txt , time : 2019-08-11T16:19:18.057
start to notify file modified :.DS_Store , time : 2019-08-11T16:19:37.999
start to notify file deleted :test1 복사본 2.txt , time : 2019-08-11T16:19:37.999
start to notify file modified :test3 복사본.txt , time : 2019-08-11T16:19:57.999

정상작동 체크!

물론 비정상적으로 작동하는 부분 체크나, 대용량 처리 등의 테스트는 반드시 필요함을 인지해야한다. 아마 이러한 부분을 다른 방법으로 쓸수 있는 여러가지 서비스들이 있을 것이다. 대표적으로 aws cloud watch같은 경우 버튼 몇번과 해당 디렉토리 설정해주는 config만 변경시 모든 로그를 땡겨서 쓸수 있다. cloud watch의 filter 로그 검색기능은 환상적이다.