Skip to content

Commit 84e6392

Browse files
committed
switch to a less fragile, "not hard-coded" approach to get log path
1 parent 24fe53c commit 84e6392

1 file changed

Lines changed: 107 additions & 7 deletions

File tree

Lines changed: 107 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,32 @@
11
package de.rwth.idsg.steve.web.controller;
22

33
import lombok.extern.slf4j.Slf4j;
4+
import org.apache.logging.log4j.LogManager;
5+
import org.apache.logging.log4j.core.Appender;
6+
import org.apache.logging.log4j.core.LoggerContext;
7+
import org.apache.logging.log4j.core.appender.FileAppender;
8+
import org.apache.logging.log4j.core.appender.MemoryMappedFileAppender;
9+
import org.apache.logging.log4j.core.appender.RandomAccessFileAppender;
10+
import org.apache.logging.log4j.core.appender.RollingFileAppender;
11+
import org.apache.logging.log4j.core.appender.RollingRandomAccessFileAppender;
12+
import org.apache.logging.log4j.core.impl.Log4jContextFactory;
13+
import org.apache.logging.log4j.core.selector.ContextSelector;
14+
import org.apache.logging.log4j.spi.LoggerContextFactory;
415
import org.springframework.stereotype.Controller;
516
import org.springframework.web.bind.annotation.RequestMapping;
617
import org.springframework.web.bind.annotation.RequestMethod;
718

19+
import javax.annotation.PostConstruct;
820
import javax.servlet.http.HttpServletResponse;
921
import java.io.IOException;
1022
import java.io.PrintWriter;
1123
import java.nio.charset.StandardCharsets;
1224
import java.nio.file.Files;
1325
import java.nio.file.Path;
1426
import java.nio.file.Paths;
27+
import java.util.ArrayList;
28+
import java.util.List;
29+
import java.util.Random;
1530

1631
/**
1732
* @author Sevket Goekay <goekay@dbis.rwth-aachen.de>
@@ -22,23 +37,108 @@
2237
@RequestMapping(value = "/manager")
2338
public class LogController {
2439

25-
private final Path logPath = Paths.get(System.getProperty("user.home"), "logs", "steve.log");
40+
private List<Path> logPathList;
41+
private Random random = new Random();
42+
private static final String ERROR_MESSAGE = "Not available";
43+
44+
@PostConstruct
45+
private void init() {
46+
logPathList = getActiveLogFilePaths();
47+
}
2648

2749
@RequestMapping(value = "/log", method = RequestMethod.GET)
2850
public void log(HttpServletResponse response) {
51+
response.setContentType("text/plain");
2952

3053
try (PrintWriter writer = response.getWriter()) {
31-
response.setContentType("text/plain");
32-
33-
Files.lines(logPath, StandardCharsets.UTF_8)
34-
.forEach(writer::println);
35-
54+
Path p = decidePath();
55+
if (p == null) {
56+
writer.write(ERROR_MESSAGE);
57+
} else {
58+
Files.lines(p, StandardCharsets.UTF_8)
59+
.forEach(writer::println);
60+
}
3661
} catch (IOException e) {
3762
log.error("Exception happened", e);
3863
}
3964
}
4065

4166
public String getLogFilePath() {
42-
return logPath.toAbsolutePath().toString();
67+
Path p = decidePath();
68+
if (p == null) {
69+
return ERROR_MESSAGE;
70+
} else {
71+
return p.toAbsolutePath().toString();
72+
}
73+
}
74+
75+
// -------------------------------------------------------------------------
76+
// Private helpers
77+
// -------------------------------------------------------------------------
78+
79+
private Path decidePath() {
80+
if (logPathList.isEmpty()) {
81+
return null;
82+
} else if (logPathList.size() == 1) {
83+
return logPathList.get(0);
84+
} else {
85+
return rollTheDice();
86+
}
87+
}
88+
89+
/**
90+
* If the user configured multiple file appenders, which log file should we choose?
91+
* Clearly, the only sane solution is rolling the dice.
92+
* Easter egg mode: On
93+
*/
94+
private Path rollTheDice() {
95+
log.trace("Rolling the dice...");
96+
int index = random.nextInt(logPathList.size());
97+
return logPathList.get(index);
98+
}
99+
100+
/**
101+
* We cannot presume that the default file name/location setting won't be changed by the user.
102+
* Therefore, we should be able to retrieve that info from the underlying logging mechanism
103+
* by iterating over appenders.
104+
*/
105+
private List<Path> getActiveLogFilePaths() {
106+
LoggerContextFactory factory = LogManager.getFactory();
107+
ContextSelector selector = ((Log4jContextFactory) factory).getSelector();
108+
109+
List<Path> fileNameList = new ArrayList<>();
110+
for (LoggerContext ctx : selector.getLoggerContexts()) {
111+
for (Appender appender : ctx.getConfiguration().getAppenders().values()) {
112+
String fileName = extractFileName(appender);
113+
if (fileName != null) {
114+
fileNameList.add(Paths.get(fileName));
115+
}
116+
}
117+
}
118+
return fileNameList;
119+
}
120+
121+
/**
122+
* File appender types do not share a "write-to-file" superclass.
123+
*/
124+
private String extractFileName(Appender a) {
125+
if (a instanceof FileAppender) {
126+
return ((FileAppender) a).getFileName();
127+
128+
} else if (a instanceof RollingFileAppender) {
129+
return ((RollingFileAppender) a).getFileName();
130+
131+
} else if (a instanceof RollingRandomAccessFileAppender) {
132+
return ((RollingRandomAccessFileAppender) a).getFileName();
133+
134+
} else if (a instanceof RandomAccessFileAppender) {
135+
return ((RandomAccessFileAppender) a).getFileName();
136+
137+
} else if (a instanceof MemoryMappedFileAppender) {
138+
return ((MemoryMappedFileAppender) a).getFileName();
139+
140+
} else {
141+
return null;
142+
}
43143
}
44144
}

0 commit comments

Comments
 (0)