-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added support for different log formats in logcat, and updated the us…
…ability of it by adding --help etc.
- Loading branch information
Anders Storsveen
committed
Nov 29, 2012
1 parent
e73a529
commit 75534e0
Showing
3 changed files
with
287 additions
and
6 deletions.
There are no files selected for viewing
95 changes: 95 additions & 0 deletions
95
log/src/main/java/org/cloudname/log/format/FullFormatter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package org.cloudname.log.format; | ||
|
||
import org.cloudname.log.pb.Timber; | ||
|
||
/** | ||
* Format Timber.LogEvent messages to a single line using NL to | ||
* separate log records and TAB to separate the fields. The fields | ||
* are in order: | ||
* | ||
* <ul> | ||
* <li> timestamp in ISO8601 format | ||
* <li> hostname | ||
* <li> process id/thread id | ||
* <li> service name | ||
* <li> class | ||
* <li> type of log message | ||
* <li> log level | ||
* <li> consistency level | ||
* <li> log message payload | ||
* </ul> | ||
* | ||
* This formatter is quite a bit slower than the SingleLineFormatter, | ||
* but it is perhaps more pleasing to look at. | ||
* | ||
* @author borud | ||
*/ | ||
public class FullFormatter implements LogEventFormatter { | ||
@Override | ||
public String format(Timber.LogEvent logEvent) { | ||
StringBuilder buff = new StringBuilder(200); | ||
Util.formatTimeISO(logEvent.getTimestamp(), buff); | ||
|
||
buff.append('\t') | ||
.append(logEvent.getHost()) | ||
.append('\t') | ||
|
||
// Add process- and thread id if applicable | ||
.append((logEvent.hasPid() ? logEvent.getPid() : "-")) | ||
.append("/") | ||
.append((logEvent.hasTid() ? logEvent.getTid() : "-")) | ||
.append('\t') | ||
|
||
// Add service name | ||
.append(logEvent.getServiceName()) | ||
.append('\t') | ||
|
||
// Add source | ||
.append(classFromSource(logEvent.getSource())) | ||
.append('\t') | ||
|
||
// Type of log message | ||
.append(logEvent.getType()) | ||
.append('\t') | ||
|
||
// Level of log message | ||
.append(Util.logLevelNameForValue(logEvent.getLevel())) | ||
.append('\t') | ||
|
||
// Add consistency level | ||
.append(logEvent.getConsistencyLevel().toString().substring(0,2)) | ||
.append('\t'); | ||
|
||
// Add the payloads | ||
boolean first = true; | ||
for (Timber.Payload payload : logEvent.getPayloadList()) { | ||
String s = payload.getPayload().toStringUtf8(); | ||
|
||
buff.append((first?"":" | ")) | ||
.append(payload.getName()) | ||
.append(": ") | ||
.append(Util.escape(s)); | ||
|
||
first = false; | ||
} | ||
|
||
return buff.toString(); | ||
} | ||
|
||
/** | ||
* Given a fully qualified class name, return just the class name | ||
* without the package name. | ||
* | ||
* @param source A (possibly) fully qualified class name | ||
* @return the class name without the package. | ||
*/ | ||
private String classFromSource(String source) { | ||
int last = source.lastIndexOf('.'); | ||
if (-1 == last) { | ||
return source; | ||
} | ||
|
||
return source.substring(last + 1); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
140 changes: 140 additions & 0 deletions
140
log/src/test/java/org/cloudname/log/format/FullFormatterTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package org.cloudname.log.format; | ||
|
||
import com.google.protobuf.ByteString; | ||
import org.cloudname.log.pb.Timber; | ||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.hamcrest.core.StringStartsWith.startsWith; | ||
import static org.junit.Assert.assertEquals; | ||
import org.junit.BeforeClass; | ||
import org.junit.Test; | ||
|
||
import java.io.ByteArrayOutputStream; | ||
import java.io.PrintStream; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
|
||
/** | ||
* Unit test for FullFormatter. | ||
* | ||
* @author storsveen | ||
*/ | ||
public class FullFormatterTest { | ||
private static final Logger log = Logger.getLogger(CompactFormatterTest.class.getName()); | ||
|
||
private static final String eventString | ||
= "2011-11-28T16:46:22.123\texample.com\t0/1\tmyservice\tSingleLineFormatter\tT\tINFO\tBE\tmsg: this is a test"; | ||
|
||
private static final String eventStringWithException | ||
= "2011-11-28T16:46:22.123\texample.com\t0/1\tmyservice\tSingleLineFormatter\tT\tWARNING" + | ||
"\tBE\tmsg: this is a test with an exception | exception: java.lang.RuntimeException: " + | ||
"Testing\\n\\tat"; | ||
|
||
private static Timber.LogEvent event; | ||
private static Timber.LogEvent eventWithException; | ||
|
||
private static long instant = 1322498782123L; | ||
private static RuntimeException runtimeException = new RuntimeException("Testing"); | ||
|
||
@BeforeClass | ||
public static void setUp() { | ||
event = Timber.LogEvent.newBuilder() | ||
.setTimestamp(instant) | ||
.setConsistencyLevel(Timber.ConsistencyLevel.BESTEFFORT) | ||
.setLevel(Level.INFO.intValue()) | ||
.setHost("example.com") | ||
.setServiceName("myservice") | ||
.setSource(SingleLineFormatter.class.getName()) | ||
.setPid(0) | ||
.setTid((int) Thread.currentThread().getId()) | ||
.setType("T") | ||
.addPayload( | ||
Timber.Payload.newBuilder() | ||
.setName("msg") | ||
.setPayload(ByteString.copyFromUtf8("this is a test"))) | ||
.build(); | ||
|
||
ByteArrayOutputStream os = new ByteArrayOutputStream(); | ||
runtimeException.printStackTrace(new PrintStream(os)); | ||
|
||
eventWithException = Timber.LogEvent.newBuilder() | ||
.setTimestamp(instant) | ||
.setConsistencyLevel(Timber.ConsistencyLevel.BESTEFFORT) | ||
.setLevel(Level.WARNING.intValue()) | ||
.setHost("example.com") | ||
.setServiceName("myservice") | ||
.setSource(SingleLineFormatter.class.getName()) | ||
.setPid(0) | ||
.setTid((int) Thread.currentThread().getId()) | ||
.setType("T") | ||
.addPayload( | ||
Timber.Payload.newBuilder() | ||
.setName("msg") | ||
.setPayload(ByteString.copyFromUtf8("this is a test with an exception"))) | ||
.addPayload( | ||
Timber.Payload.newBuilder() | ||
.setName("exception") | ||
.setContentType("application/java-exception") | ||
.setPayload(ByteString.copyFrom(os.toByteArray()))) | ||
.build(); | ||
} | ||
|
||
/** | ||
* Tests that a simple event is as expected. | ||
* | ||
* @throws Exception | ||
*/ | ||
@Test | ||
public void simpleTest() throws Exception { | ||
FullFormatter form = new FullFormatter(); | ||
assertEquals(eventString, form.format(event)); | ||
} | ||
|
||
/** | ||
* Tests that a event with exception is as expected. | ||
* | ||
* @throws Exception | ||
*/ | ||
@Test | ||
public void exceptionTest() throws Exception { | ||
FullFormatter form = new FullFormatter(); | ||
assertThat(form.format(eventWithException), startsWith(eventStringWithException)); | ||
} | ||
|
||
/** | ||
* A micro benchmark. | ||
*/ | ||
@Test (timeout = 1000) | ||
public void microBenchmarkTest() { | ||
FullFormatter form = new FullFormatter(); | ||
int numIterations = 1000; | ||
|
||
long start = System.currentTimeMillis(); | ||
for (int i = 0; i < numIterations; i++) { | ||
form.format(event); | ||
} | ||
long duration = System.currentTimeMillis() - start; | ||
double formatsPerSecond = numIterations / ((double) duration / 1000.0); | ||
|
||
log.info("event formats per second: " + formatsPerSecond | ||
+ " (" + numIterations + " iterations took " + duration + " milliseconds)"); | ||
} | ||
|
||
/** | ||
* A micro benchmark with exceptions. | ||
*/ | ||
@Test (timeout = 1000) | ||
public void microBenchmarkWithExceptionTest() { | ||
FullFormatter form = new FullFormatter(); | ||
int numIterations = 1000; | ||
|
||
long start = System.currentTimeMillis(); | ||
for (int i = 0; i < numIterations; i++) { | ||
form.format(eventWithException); | ||
} | ||
long duration = System.currentTimeMillis() - start; | ||
double formatsPerSecond = numIterations / ((double) duration / 1000.0); | ||
|
||
log.info("event + exception formats per second: " + formatsPerSecond | ||
+ " (" + numIterations + " iterations took " + duration + " milliseconds)"); | ||
} | ||
} |