diff --git a/pom.xml b/pom.xml index b277042a8e..f65f3e04b4 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,12 @@ log4j 1.2.16 + + com.googlecode.jmockit + jmockit + 0.999.12 + test + junit junit @@ -78,6 +84,39 @@ + + + + ${basedir}/src/main/java + + **/*.json + **/*.yml + + + + ${basedir}/src/main/resources + + **/*.* + + + + + + + ${basedir}/src/test/java + + **/*.json + **/*.yml + **/*.txt + + + + ${basedir}/src/test/resources + + **/*.* + + + \ No newline at end of file diff --git a/src/main/java/net/kencochrane/sentry/RavenClient.java b/src/main/java/net/kencochrane/sentry/RavenClient.java index 7f746802ce..21308877dd 100644 --- a/src/main/java/net/kencochrane/sentry/RavenClient.java +++ b/src/main/java/net/kencochrane/sentry/RavenClient.java @@ -22,6 +22,15 @@ class RavenClient { private static final String RAVEN_JAVA_VERSION = "Raven-Java 0.2"; private RavenConfig config; private String sentryDSN; + private String lastID; + + public RavenClient() { + this.sentryDSN = System.getenv("SENTRY_DSN"); + if (this.sentryDSN == null || this.sentryDSN.length() == 0) { + throw new RuntimeException("You must provide a DSN to RavenClient"); + } + this.config = new RavenConfig(this.sentryDSN); + } public RavenClient(String sentryDSN) { this.sentryDSN = sentryDSN; @@ -49,6 +58,14 @@ public void setSentryDSN(String sentryDSN) { this.sentryDSN = sentryDSN; } + public void setLastID(String lastID) { + this.lastID = lastID; + } + + public String getLastID() { + return lastID; + } + /** * Build up the JSON body for the POST that is sent to sentry * @@ -61,7 +78,8 @@ public void setSentryDSN(String sentryDSN) { */ private String buildJSON(String message, String timestamp, String loggerClass, int logLevel, String culprit, Throwable exception) { JSONObject obj = new JSONObject(); - obj.put("event_id", RavenUtils.getRandomUUID()); //Hexadecimal string representing a uuid4 value. + String lastID = RavenUtils.getRandomUUID(); + obj.put("event_id", lastID); //Hexadecimal string representing a uuid4 value. obj.put("checksum", RavenUtils.calculateChecksum(message)); if (exception == null) { obj.put("culprit", culprit); @@ -76,6 +94,7 @@ private String buildJSON(String message, String timestamp, String loggerClass, i obj.put("level", logLevel); obj.put("logger", loggerClass); obj.put("server_name", RavenUtils.getHostname()); + setLastID(lastID); return obj.toJSONString(); } @@ -243,6 +262,9 @@ private void sendMessage(String messageBody, long timestamp) { /** * Send the log message to the sentry server. * + * This method is deprecated. You should use captureMessage instead. + * + * @deprecated * @param theLogMessage The log message * @param timestamp unix timestamp * @param loggerClass The class associated with the log message @@ -257,4 +279,48 @@ public void logMessage(String theLogMessage, long timestamp, String loggerClass, sendMessage(message, timestamp); } + + /** + * Send the log message to the sentry server. + * + * @param message The log message + * @param timestamp unix timestamp + * @param loggerClass The class associated with the log message + * @param logLevel int value for Log level for message (DEBUG, ERROR, INFO, etc.) + * @param culprit Who we think caused the problem. + */ + public String captureMessage(String message, long timestamp, String loggerClass, int logLevel, String culprit) { + String timestampDate = RavenUtils.getTimestampString(timestamp); + + String body = buildMessage(message, timestampDate, loggerClass, logLevel, culprit, null); + sendMessage(body, timestamp); + return getLastID(); + } + + public String captureMessage(String message) { + long timestamp = System.currentTimeMillis() / 1000L; + return captureMessage(message, timestamp, "root", 50, null); + } + + /** + * Send the log message to the sentry server. + * + * @param exception exception that occurred + * @param timestamp unix timestamp + * @param loggerClass The class associated with the log message + * @param logLevel int value for Log level for message (DEBUG, ERROR, INFO, etc.) + * @param culprit Who we think caused the problem. + */ + public String captureException(Throwable exception, long timestamp, String loggerClass, int logLevel, String culprit) { + String timestampDate = RavenUtils.getTimestampString(timestamp); + + String body = buildMessage(exception.getMessage(), timestampDate, loggerClass, logLevel, culprit, exception); + sendMessage(body, timestamp); + return getLastID(); + } + + public String captureException(Throwable exception) { + long timestamp = System.currentTimeMillis() / 1000L; + return captureException(exception, timestamp, "root", 50, null); + } } \ No newline at end of file diff --git a/src/test/java/net/kencochrane/sentry/SentryClientTest.java b/src/test/java/net/kencochrane/sentry/SentryClientTest.java new file mode 100644 index 0000000000..c110a5c236 --- /dev/null +++ b/src/test/java/net/kencochrane/sentry/SentryClientTest.java @@ -0,0 +1,74 @@ +package net.kencochrane.sentry; + +import mockit.Mocked; +import mockit.Expectations; +import mockit.Verifications; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class SentryClientTest { + public void triggerRuntimeException() { + try { + triggerNullPointer(); + } catch (Exception e) { + throw new RuntimeException("Error triggering null pointer", e); + } + } + + public String triggerNullPointer() { + String c = null; + return c.toLowerCase(); + } + + @Test(expected=RuntimeException.class) + public void testMissingDSN() { + RavenClient client = new RavenClient(); + } + + @Test + public void testConfigureFromDSN() { + RavenClient client = new RavenClient("http://public:secret@example.com/path/1"); + assertEquals(client.getSentryDSN(), "http://public:secret@example.com/path/1"); + } + + @Test + public void testConfigureFromEnvironment() { + new Expectations() + { + @Mocked("getenv") System mockedSystem; + + { + System.getenv("SENTRY_DSN"); returns("http://public:secret@example.com/path/1"); + } + }; + RavenClient client = new RavenClient(); + assertEquals(client.getSentryDSN(), "http://public:secret@example.com/path/1"); + } + + @Test + public void testCaptureExceptionWithOnlyThrowable() { + RavenClient client = new RavenClient("http://public:secret@example.com/path/1"); + + new Expectations() + { + + @Mocked("getRandomUUID") RavenUtils mockedRavenUtils; + + { + RavenUtils.getRandomUUID(); returns("1234567890"); + } + + // TODO: this should be mocked, somehow + // RavenClient.sendMessage(); minTimes = 1; maxTimes = 1; + }; + + + try { + triggerRuntimeException(); + } catch (RuntimeException e) { + String ident = client.captureException(e); + assertEquals(ident, "1234567890"); + } + } +} \ No newline at end of file