使用Java WatchService监视和解析日志文件

时间:2020-01-23 17:39:51

标签: java logging watchservice

我正在尝试使用Java 8中的Java WatchService 来监视文件夹以获取特定日志文件的更新。

此日志文件是使用java.util.logging.Logger创建的,并具有常规的FileHander,该文件将在达到特定大小后旋转日志文件。它最初创建tracelog0.log,并且在轮换日志之后创建tracelog1.log。所有新条目仍将转到tracelog0.log。

我收到了StandardWatchEventKinds.ENTRY_MODIFY个事件。但是问题是,当旋转日志文件时,我没有得到任何事件,并且日志监视线程似乎被杀死。我也添加了一个新的StandardWatchEventKinds.ENTRY_DELETE事件,但仍然无法正常工作。 这是我执行监视的线程。请让我知道这是否正确。请为这种情况建议其他解决方案。

class WatcherThread implements Runnable {
    public static final String WORKING_DIRECTORY = "/var/log/data/";
    Path logDir = Paths.get(WORKING_DIRECTORY);
    WatchEvent.Kind<?> [] kinds = { StandardWatchEventKinds.ENTRY_CREATE, 
            StandardWatchEventKinds.ENTRY_DELETE,
            StandardWatchEventKinds.ENTRY_MODIFY};
    boolean runThread = true;
    private WatchService watcher;
    private boolean logRotated = false;

    public WatcherThread(){
        try {
            watcher = logDir.getFileSystem().newWatchService();
            logDir.register(watcher, kinds);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void run() {

        while(runThread) {
            // Get next event or wait if none are yet present
            try {
                WatchKey key = watcher.take();
                for (WatchEvent<?> event : key.pollEvents()) {

                    // Retrieve event kind
                    WatchEvent.Kind<?> kind = event.kind();

                    if (StandardWatchEventKinds.OVERFLOW == kind) {
                        continue;
                    }else {
                        WatchEvent<Path> ev = (WatchEvent<Path>)event;
                        Path filename = ev.context();
                        Path child = logDir.resolve(filename);

                        System.out.println("New file created Filename: "+child.getFileName());
                        if(child.getFileName().startsWith("tracelog")) {
                            System.out.println("tracelog file rotated.");
                            //Possible tracelog0.log file is rotated. 
                            logRotated = true;
                        }
                    }
                }
                boolean isValid = key.reset();
                if(!isValid) {
                    System.out.println("Unable to reset the Key exiting!!!");
                    runThread = false;
                }
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

    public boolean isLogRotated() {
        return logRotated;
    }
}

1 个答案:

答案 0 :(得分:1)

我想我已经解决了这个问题。该问题归因于java.util.Logger框架。当日志文件轮换发生时,它不会删除实际的日志文件。

当前日志由Logger存储在缓存中。当需要根据日志大小旋转日志文件时。它创建一个新文件并将内容复制到新文件。

Example 
When the server starts the below files get created 
/var/log/data/tracelog0.log 
/var/log/data/tracelog0.log.lck
when log file rotates it creates a new file tracelog1.log
/var/log/data/tracelog0.log 
/var/log/data/tracelog0.log.lck
/var/log/data/tracelog1.log

因此仅触发MODIFY和CREATE事件。 DELETE事件不会被触发。

我认为这可能会根据我们使用的Logger有所不同。最好看看记录器如何旋转日志文件。