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

Applying a Google formatter #250

Merged
merged 1 commit into from
May 24, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,95 +28,99 @@
* properties that App Engine expects.
*/
public class JsonFormatter extends Formatter {
@Override
public String format(LogRecord record) {
Instant timestamp = Instant.ofEpochMilli(record.getMillis());
StringWriter out = new StringWriter();
@Override
public String format(LogRecord record) {
Instant timestamp = Instant.ofEpochMilli(record.getMillis());
StringWriter out = new StringWriter();

// Write using a simple JsonWriter rather than the more sophisticated Gson as we generally
// will not need to serialize complex objects that require introspection and reflection.
try (JsonWriter writer = new JsonWriter(out)) {
writer.setSerializeNulls(false);
writer.setHtmlSafe(false);
// Write using a simple JsonWriter rather than the more sophisticated Gson as we generally
// will not need to serialize complex objects that require introspection and reflection.
try (JsonWriter writer = new JsonWriter(out)) {
writer.setSerializeNulls(false);
writer.setHtmlSafe(false);

writer.beginObject();
writer.name("timestamp")
.beginObject()
.name("seconds").value(timestamp.getEpochSecond())
.name("nanos").value(timestamp.getNano())
.endObject();
writer.name("severity").value(severity(record.getLevel()));
writer.name("thread").value(Thread.currentThread().getName());
writer.name("message").value(formatMessage(record));
writer.beginObject();
writer
.name("timestamp")
.beginObject()
.name("seconds")
.value(timestamp.getEpochSecond())
.name("nanos")
.value(timestamp.getNano())
.endObject();
writer.name("severity").value(severity(record.getLevel()));
writer.name("thread").value(Thread.currentThread().getName());
writer.name("message").value(formatMessage(record));

// If there is a LogContext associated with this thread then add its properties.
LogContext logContext = LogContext.current();
if (logContext != null) {
logContext.forEach((name, value) -> {
try {
writer.name(name);
if (value == null) {
writer.nullValue();
} else if (value instanceof Boolean) {
writer.value((boolean) value);
} else if (value instanceof Number) {
writer.value((Number) value);
} else {
writer.value(value.toString());
}
} catch (IOException e) {
// Should not happen as StringWriter does not throw IOException
throw new AssertionError(e);
}
});
}
writer.endObject();
} catch (IOException e) {
// Should not happen as StringWriter does not throw IOException
throw new AssertionError(e);
}
out.append(System.lineSeparator());
return out.toString();
// If there is a LogContext associated with this thread then add its properties.
LogContext logContext = LogContext.current();
if (logContext != null) {
logContext.forEach(
(name, value) -> {
try {
writer.name(name);
if (value == null) {
writer.nullValue();
} else if (value instanceof Boolean) {
writer.value((boolean) value);
} else if (value instanceof Number) {
writer.value((Number) value);
} else {
writer.value(value.toString());
}
} catch (IOException e) {
// Should not happen as StringWriter does not throw IOException
throw new AssertionError(e);
}
});
}
writer.endObject();
} catch (IOException e) {
// Should not happen as StringWriter does not throw IOException
throw new AssertionError(e);
}
out.append(System.lineSeparator());
return out.toString();
}

@Override
public synchronized String formatMessage(LogRecord record) {
StringBuilder sb = new StringBuilder();
if (record.getSourceClassName() != null) {
sb.append(record.getSourceClassName());
} else {
sb.append(record.getLoggerName());
}
if (record.getSourceMethodName() != null) {
sb.append(' ');
sb.append(record.getSourceMethodName());
}
sb.append(": ");
sb.append(super.formatMessage(record));
Throwable thrown = record.getThrown();
if (thrown != null) {
StringWriter sw = new StringWriter();
try (PrintWriter pw = new PrintWriter(sw);) {
sb.append("\n");
thrown.printStackTrace(pw);
}
sb.append(sw.getBuffer());
}
return sb.toString();
@Override
public synchronized String formatMessage(LogRecord record) {
StringBuilder sb = new StringBuilder();
if (record.getSourceClassName() != null) {
sb.append(record.getSourceClassName());
} else {
sb.append(record.getLoggerName());
}
if (record.getSourceMethodName() != null) {
sb.append(' ');
sb.append(record.getSourceMethodName());
}
sb.append(": ");
sb.append(super.formatMessage(record));
Throwable thrown = record.getThrown();
if (thrown != null) {
StringWriter sw = new StringWriter();
try (PrintWriter pw = new PrintWriter(sw); ) {
sb.append("\n");
thrown.printStackTrace(pw);
}
sb.append(sw.getBuffer());
}
return sb.toString();
}

private static String severity(Level level) {
int intLevel = level.intValue();
private static String severity(Level level) {
int intLevel = level.intValue();

if (intLevel >= Level.SEVERE.intValue()) {
return "ERROR";
} else if (intLevel >= Level.WARNING.intValue()) {
return "WARNING";
} else if (intLevel >= Level.INFO.intValue()) {
return "INFO";
} else {
// There's no trace, so we'll map everything below this to debug.
return "DEBUG";
}
if (intLevel >= Level.SEVERE.intValue()) {
return "ERROR";
} else if (intLevel >= Level.WARNING.intValue()) {
return "WARNING";
} else if (intLevel >= Level.INFO.intValue()) {
return "INFO";
} else {
// There's no trace, so we'll map everything below this to debug.
return "DEBUG";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,19 @@
* <p>This is an implementation of a Mapped Diagnostic Context for use with the java.util.logging
* framework.
*/
public class LogContext extends ConcurrentHashMap<String, Object>{
public class LogContext extends ConcurrentHashMap<String, Object> {

private static final ThreadLocal<LogContext> threadContext = new ThreadLocal<LogContext>()
{
@Override
protected LogContext initialValue() {
return new LogContext();
}
};
private static final ThreadLocal<LogContext> threadContext =
new ThreadLocal<LogContext>() {
@Override
protected LogContext initialValue() {
return new LogContext();
}
};

private final Map<String, Object> values = new ConcurrentHashMap<>();

private LogContext() {
}
private LogContext() {}

/**
* Returns the log context associated with the current Thread.
Expand Down Expand Up @@ -79,5 +78,4 @@ public <T> T get(String name, Class<T> type) {
public Stream<Map.Entry<String, Object>> stream() {
return values.entrySet().stream();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,73 +27,76 @@

public class JsonFormatterTest {

private JsonFormatter formatter = new JsonFormatter();
private JsonFormatter formatter = new JsonFormatter();

@Test
public void formatProducesExpectedJsonData() throws Exception {
LogRecord record = new LogRecord(Level.INFO, "message");
record.setMillis(12345_678);
record.setLoggerName("logger");
LogContext.current().put("traceId", "abcdef");
@Test
public void formatProducesExpectedJsonData() throws Exception {
LogRecord record = new LogRecord(Level.INFO, "message");
record.setMillis(12345_678);
record.setLoggerName("logger");
LogContext.current().put("traceId", "abcdef");

String logLine = formatter.format(record);
assertThat(logLine, endsWith(System.lineSeparator()));
String logLine = formatter.format(record);
assertThat(logLine, endsWith(System.lineSeparator()));

JsonData data = new Gson().fromJson(logLine, JsonData.class);
assertEquals("INFO", data.severity);
assertEquals(12345, data.timestamp.seconds);
assertEquals(678_000_000, data.timestamp.nanos);
assertEquals(Thread.currentThread().getName(), data.thread);
assertEquals("logger: message", data.message);
assertEquals("abcdef", data.traceId);
}
JsonData data = new Gson().fromJson(logLine, JsonData.class);
assertEquals("INFO", data.severity);
assertEquals(12345, data.timestamp.seconds);
assertEquals(678_000_000, data.timestamp.nanos);
assertEquals(Thread.currentThread().getName(), data.thread);
assertEquals("logger: message", data.message);
assertEquals("abcdef", data.traceId);
}

@Test
public void messageIncludesLoggerName() throws Exception {
LogRecord record = new LogRecord(Level.INFO, "message");
record.setLoggerName("logger");
assertEquals("logger: message", formatter.formatMessage(record));
}
@Test
public void messageIncludesLoggerName() throws Exception {
LogRecord record = new LogRecord(Level.INFO, "message");
record.setLoggerName("logger");
assertEquals("logger: message", formatter.formatMessage(record));
}

@Test
public void messageIncludesClassName() throws Exception {
LogRecord record = new LogRecord(Level.INFO, "message");
record.setSourceClassName("class");
record.setLoggerName("logger");
assertEquals("class: message", formatter.formatMessage(record));
}
@Test
public void messageIncludesClassName() throws Exception {
LogRecord record = new LogRecord(Level.INFO, "message");
record.setSourceClassName("class");
record.setLoggerName("logger");
assertEquals("class: message", formatter.formatMessage(record));
}

@Test
public void messageIncludesMethodName() throws Exception {
LogRecord record = new LogRecord(Level.INFO, "message");
record.setSourceClassName("class");
record.setSourceMethodName("method");
assertEquals("class method: message", formatter.formatMessage(record));
}
@Test
public void messageIncludesMethodName() throws Exception {
LogRecord record = new LogRecord(Level.INFO, "message");
record.setSourceClassName("class");
record.setSourceMethodName("method");
assertEquals("class method: message", formatter.formatMessage(record));
}

@Test
public void messageIncludesStackTrace() throws Exception {
LogRecord record = new LogRecord(Level.INFO, "message");
record.setLoggerName("logger");
record.setThrown(new Throwable("thrown").fillInStackTrace());
String message = formatter.formatMessage(record);
BufferedReader reader = new BufferedReader(new StringReader(message));
assertEquals("logger: message", reader.readLine());
assertEquals("java.lang.Throwable: thrown", reader.readLine());
assertTrue(reader.readLine()
.startsWith("\tat " + getClass().getName() + ".messageIncludesStackTrace"));
}
@Test
public void messageIncludesStackTrace() throws Exception {
LogRecord record = new LogRecord(Level.INFO, "message");
record.setLoggerName("logger");
record.setThrown(new Throwable("thrown").fillInStackTrace());
String message = formatter.formatMessage(record);
BufferedReader reader = new BufferedReader(new StringReader(message));
assertEquals("logger: message", reader.readLine());
assertEquals("java.lang.Throwable: thrown", reader.readLine());
assertTrue(
reader
.readLine()
.startsWith("\tat " + getClass().getName() + ".messageIncludesStackTrace"));
}

// Something that JSON can parser the JSON into
public static class JsonData {
public static class LogTimestamp {
public long seconds;
public long nanos;
}
public LogTimestamp timestamp;
public String severity;
public String thread;
public String message;
public String traceId;
// Something that JSON can parser the JSON into
public static class JsonData {
public static class LogTimestamp {
public long seconds;
public long nanos;
}
}

public LogTimestamp timestamp;
public String severity;
public String thread;
public String message;
public String traceId;
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
/**
* Copyright 2011 Google Inc. All Rights Reserved.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.apphosting.runtime;

import static com.google.apphosting.runtime.SessionManagerUtil.deserialize;
Expand Down
Loading