package com.sungardas.enhancedsnapshots.components.logwatcher;
import com.sungardas.enhancedsnapshots.components.ConfigurationMediator;
import org.apache.commons.io.input.ReversedLinesFileReader;
import org.apache.commons.io.input.Tailer;
import org.apache.commons.io.input.TailerListener;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.DependsOn;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.PreDestroy;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static java.util.Collections.reverse;
@Service
@DependsOn({"ConfigurationMediator", "MasterService"})
public class LogsWatcherService implements TailerListener {
private static final Logger LOG = LogManager.getLogger(LogsWatcherService.class);
private static final String LOGS_DESTINATION = "/logs";
private File logFile;
private Tailer tailer;
@Autowired
private ConfigurationMediator configurationMediator;
@Autowired
private SimpMessagingTemplate template;
@Value("${catalina.home}")
private String catalinaHome;
@PreDestroy
public void destroy() {
stop();
}
public void stop() {
if (tailer != null) {
tailer.stop();
LOG.info("Logs watcher stopped.");
}
}
public void start() {
if (tailer == null) {
tailer = Tailer.create(getLogsFile(), this, 500L, true);
LOG.info("Logs watcher started. File {} will be tracked for changes.", configurationMediator.getLogFileName());
}
}
private File getLogsFile() {
if (logFile == null) {
logFile = Paths.get(catalinaHome, configurationMediator.getLogFileName()).toFile();
}
return logFile;
}
@Override
public void init(Tailer tailer) {}
@Override
public void fileNotFound() {
LOG.warn("Log file {} was not found", configurationMediator.getLogFileName());
}
@Override
public void fileRotated() {}
@Override
public synchronized void handle(String line) {
template.convertAndSend(LOGS_DESTINATION, Arrays.asList(line));
}
@Override
public void handle(Exception ex) {
LOG.warn("Failed to read log file {}", configurationMediator.getLogFileName(), ex);
}
public synchronized void sendLatestLogs() {
List<String> list = new ArrayList<>();
try {
ReversedLinesFileReader reader = new ReversedLinesFileReader(getLogsFile());
while (list.size() < configurationMediator.getLogsBufferSize()) {
list.add(reader.readLine());
}
reverse(list);
template.convertAndSend(LOGS_DESTINATION, list);
} catch (IOException e) {
LOG.warn("Failed to read logs {}", e);
reverse(list);
template.convertAndSend(LOGS_DESTINATION, list);
}
}
}