Skip to content
Merged
4 changes: 4 additions & 0 deletions src/main/java/org/juv25d/ConnectionHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public ConnectionHandler(Socket socket, HttpParser httpParser, Logger logger, Pi

@Override
public void run() {
String connectionId = java.util.UUID.randomUUID().toString().substring(0, 8);
org.juv25d.logging.LogContext.setConnectionId(connectionId);
try (socket) {
var in = socket.getInputStream();
var out = socket.getOutputStream();
Expand Down Expand Up @@ -56,6 +58,8 @@ public void run() {

} catch (IOException e) {
logger.log(Level.SEVERE, "Error while handling request", e);
} finally {
org.juv25d.logging.LogContext.clear();
}
}
}
5 changes: 4 additions & 1 deletion src/main/java/org/juv25d/filter/LoggingFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

import org.juv25d.http.HttpRequest;
import org.juv25d.http.HttpResponse;
import org.juv25d.logging.ServerLogging;

import java.io.IOException;
import java.util.logging.Logger;

public class LoggingFilter implements Filter {
private static final Logger logger = ServerLogging.getLogger();

@Override
public void doFilter(HttpRequest req, HttpResponse res, FilterChain chain) throws IOException {
System.out.println(req.method() + " " + req.path());
logger.info(req.method() + " " + req.path());
chain.doFilter(req, res);
}
}
17 changes: 17 additions & 0 deletions src/main/java/org/juv25d/logging/LogContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.juv25d.logging;

public class LogContext {
private static final ThreadLocal<String> connectionId = new ThreadLocal<>();

public static void setConnectionId(String id) {
connectionId.set(id);
}

public static String getConnectionId() {
return connectionId.get();
}

public static void clear() {
connectionId.remove();
}
}
33 changes: 33 additions & 0 deletions src/main/java/org/juv25d/logging/ServerLogFormatter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.juv25d.logging;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;

public class ServerLogFormatter extends Formatter {
private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

@Override
public String format(LogRecord record) {
String connectionId = LogContext.getConnectionId();
String idPart = (connectionId != null) ? " [" + connectionId + "]" : "";

StringBuilder sb = new StringBuilder(
String.format("%s %s%s: %s%n",
ZonedDateTime.now(ZoneId.systemDefault()).format(dtf),
Comment thread
Tyreviel marked this conversation as resolved.
record.getLevel(),
idPart,
formatMessage(record)));

if (record.getThrown() != null) {
StringWriter sw = new StringWriter();
record.getThrown().printStackTrace(new PrintWriter(sw));
sb.append(sw);
}
return sb.toString();
}
}
3 changes: 1 addition & 2 deletions src/main/java/org/juv25d/logging/ServerLogging.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

public class ServerLogging {
private static final Logger logger =
Expand All @@ -20,7 +19,7 @@ static void configure(Logger logger) {

if (logger.getHandlers().length == 0) {
ConsoleHandler handler = new ConsoleHandler();
handler.setFormatter(new SimpleFormatter());
handler.setFormatter(new ServerLogFormatter());
logger.addHandler(handler);
}

Expand Down
24 changes: 17 additions & 7 deletions src/test/java/org/juv25d/filter/LoggingFilterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ void callsNextFilterInChain() throws IOException {

@Test
void logsHttpMethodAndPath() throws IOException {

LoggingFilter filter = new LoggingFilter();
HttpRequest req = mock(HttpRequest.class);
HttpResponse res = mock(HttpResponse.class);
Expand All @@ -35,17 +34,28 @@ void logsHttpMethodAndPath() throws IOException {
when(req.method()).thenReturn("GET");
when(req.path()).thenReturn("/test");

var originalOut = System.out;
var out = new java.io.ByteArrayOutputStream();
System.setOut(new java.io.PrintStream(out));
java.util.logging.Logger logger = org.juv25d.logging.ServerLogging.getLogger();
java.util.List<java.util.logging.LogRecord> records = new java.util.ArrayList<>();
java.util.logging.Handler handler = new java.util.logging.Handler() {
@Override
public void publish(java.util.logging.LogRecord record) {
records.add(record);
}
@Override
public void flush() {}
@Override
public void close() throws SecurityException {}
};
logger.addHandler(handler);

try {
filter.doFilter(req, res, chain);

String output = out.toString();
assertTrue(output.contains("GET /test"), "Output should contain logged method and path");
boolean found = records.stream()
.anyMatch(r -> r.getMessage().contains("GET /test"));
assertTrue(found, "Logger should have captured the method and path");
} finally {
System.setOut(originalOut);
logger.removeHandler(handler);
}
}
}
49 changes: 49 additions & 0 deletions src/test/java/org/juv25d/logging/ConnectionIdLoggingTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.juv25d.logging;

import org.junit.jupiter.api.Test;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertTrue;

class ConnectionIdLoggingTest {

@Test
void logMessageShouldIncludeConnectionId() {
// Arrange
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Logger logger = Logger.getLogger("test.connectionid");
logger.setUseParentHandlers(false);

List<String> formattedMessages = new ArrayList<>();
ServerLogFormatter formatter = new ServerLogFormatter();

Handler handler = new Handler() {
@Override
public void publish(LogRecord record) {
formattedMessages.add(formatter.format(record));
}
@Override
public void flush() {}
@Override
public void close() throws SecurityException {}
};
logger.addHandler(handler);

try {
String testId = "test-123";
LogContext.setConnectionId(testId);

// Act
logger.info("This is a test message");

// Assert
assertTrue(formattedMessages.get(0).contains("[" + testId + "]"),
"Log message should contain the connection ID. Found: " + formattedMessages.get(0));
} finally {
LogContext.clear();
Comment thread
Tyreviel marked this conversation as resolved.
}
}
}