Skip to content
This repository was archived by the owner on Sep 16, 2021. It is now read-only.

Commit 79cf4fa

Browse files
authored
Issue #333 Async FileHandler (#334)
* Issue #333 Async FileHandler * Issue #333 Simplified Async FileHandler * Issue #333 Use thread ID
1 parent 3dcc032 commit 79cf4fa

File tree

4 files changed

+52
-7
lines changed

4 files changed

+52
-7
lines changed

appengine-java-logging/src/main/java/com/google/apphosting/logging/JsonFormatter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public String format(LogRecord record) {
5252
.value(timestamp.getNano())
5353
.endObject();
5454
writer.name("severity").value(severity(record.getLevel()));
55-
writer.name("thread").value(Thread.currentThread().getName());
55+
writer.name("thread").value(Integer.toHexString(record.getThreadID()));
5656
writer.name("message").value(formatMessage(record));
5757

5858
// If there is a LogContext associated with this thread then add its properties.

appengine-java-logging/src/test/java/com/google/apphosting/logging/JsonFormatterTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public void formatProducesExpectedJsonData() throws Exception {
4848
assertEquals("INFO", data.severity);
4949
assertEquals(12345, data.timestamp.seconds);
5050
assertEquals(678_000_000, data.timestamp.nanos);
51-
assertEquals(Thread.currentThread().getName(), data.thread);
51+
assertEquals(Long.toHexString(Thread.currentThread().getId()), data.thread);
5252
assertEquals("logger: message", data.message);
5353
assertEquals("abcdef", data.traceId);
5454
}

appengine-managed-runtime/src/main/java/com/google/apphosting/vmruntime/VmRuntimeFileLogHandler.java

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,20 @@
1919
import com.google.apphosting.logging.JsonFormatter;
2020

2121
import java.io.IOException;
22-
import java.util.logging.ConsoleHandler;
22+
import java.util.concurrent.BlockingQueue;
23+
import java.util.concurrent.LinkedBlockingQueue;
24+
import java.util.concurrent.TimeUnit;
2325
import java.util.logging.FileHandler;
2426
import java.util.logging.Handler;
2527
import java.util.logging.Level;
2628
import java.util.logging.LogManager;
29+
import java.util.logging.LogRecord;
2730
import java.util.logging.Logger;
2831

2932
/**
3033
* {@code VmRuntimeFileLogHandler} is installed on the root logger. It converts all messages
3134
* to the json format understood by the cloud logging agent and logs to a file in a volume shared
3235
* with the cloud logging agent.
33-
*
3436
*/
3537
public class VmRuntimeFileLogHandler extends FileHandler {
3638

@@ -45,11 +47,16 @@ public class VmRuntimeFileLogHandler extends FileHandler {
4547
private static final int LOG_MAX_SIZE = 100 * 1024 * 1024;
4648
private static final int LOG_MAX_FILES = 3;
4749
public static final String JAVA_UTIL_LOGGING_CONFIG_PROPERTY = "java.util.logging.config.file";
48-
50+
51+
private static final LogRecord CLOSE_RECORD = new LogRecord(Level.ALL, "CLOSE");
52+
private final BlockingQueue<LogRecord> queue = new LinkedBlockingQueue<>();
53+
54+
4955
private VmRuntimeFileLogHandler() throws IOException {
5056
super(fileLogPattern(), LOG_MAX_SIZE, LOG_MAX_FILES, true);
5157
setLevel(Level.FINEST);
5258
setFormatter(new JsonFormatter());
59+
new LoggerThread().start();
5360
}
5461

5562
private static String fileLogPattern() {
@@ -102,4 +109,39 @@ private static void reloadLoggingProperties(LogManager logManager) {
102109
System.err.println(e.getClass().getName() + ": " + e.getMessage());
103110
}
104111
}
112+
113+
@Override
114+
public void close() throws SecurityException {
115+
super.close();
116+
queue.offer(CLOSE_RECORD);
117+
}
118+
119+
@Override
120+
public void publish(LogRecord record) {
121+
if (isLoggable(record)) {
122+
queue.offer(record);
123+
}
124+
}
125+
126+
private void superPublish(LogRecord record) {
127+
super.publish(record);
128+
}
129+
130+
class LoggerThread extends Thread {
131+
@Override
132+
public void run() {
133+
while (true) {
134+
try {
135+
LogRecord record = queue.poll(1, TimeUnit.HOURS);
136+
if (record == CLOSE_RECORD) {
137+
return;
138+
} else {
139+
superPublish(record);
140+
}
141+
} catch (InterruptedException e) {
142+
return;
143+
}
144+
}
145+
}
146+
}
105147
}

jetty9-compat-base/src/test/java/com/google/apphosting/vmruntime/jetty9/LoggingIT.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ public void testGet() throws Exception {
5252

5353
assertTrue(log.exists());
5454

55+
// wait for async write
56+
Thread.sleep(1000);
57+
5558
// Look for the log entry with our query string
5659
try (BufferedReader in =
5760
new BufferedReader(
@@ -71,12 +74,12 @@ public void testGet() throws Exception {
7174
data = new Gson().fromJson(line, JsonData.class);
7275
assertThat(data.severity, equalTo("ERROR"));
7376
assertThat(
74-
data.message, org.hamcrest.Matchers.containsString("LoggingServlet doGet: not null"));
77+
data.message, org.hamcrest.Matchers.containsString("com.foo.bar: not null"));
7578

7679
line = in.readLine();
7780
data = new Gson().fromJson(line, JsonData.class);
7881
assertThat(data.severity, equalTo("ERROR"));
79-
assertThat(data.message, org.hamcrest.Matchers.containsString("LoggingServlet doGet: null"));
82+
assertThat(data.message, org.hamcrest.Matchers.containsString("com.foo.bar: null"));
8083
}
8184
}
8285

0 commit comments

Comments
 (0)