diff --git a/apps/enclave/libsockthread/src/logger.cpp b/apps/enclave/libsockthread/src/logger.cpp
index c894978bde56afd7285d639c66ee9b8ba591e0eb..99460bd595b486ab9a43b14e2b5136bd67c76a8a 100644
--- a/apps/enclave/libsockthread/src/logger.cpp
+++ b/apps/enclave/libsockthread/src/logger.cpp
@@ -28,12 +28,12 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <cassert>
 #include <cstdarg>
 #include <cstdio>
 #include <iostream>
 #include <string>
 using namespace std;
+#include "mutex.hpp"
 #include "time.hpp"
 #include "logger.hpp"
 using namespace Libsockthread;
@@ -91,19 +91,27 @@ void Logger::log(priority_t priority, const char* format, ...)
 	string s;
 	Time t;
 	logger_m.lock();
-	assert(logf != 0);
 
-	fprintf(logf, "%c@%s: ", ll, t.utc(s).c_str());
-	vfprintf(logf, format, ap);
-	fputc('\n', logf);
+	if (logf != 0) {
+		/*
+		 * Remember!  If you change the format here, change it in the else too
+		 */
+		fprintf(logf, "%c %s ", ll, t.utc(s).c_str());
+		vfprintf(logf, format, ap);
+		fputc('\n', logf);
+		if (fflush(logf) == EOF) {
+			cerr_m.lock();
+			cerr << "fflush() failed: " << strerror(errno) << '\n';
+			cerr_m.unlock();
+		}
+	} else {
+		// if they don't have an open log file, just use stderr
+		fprintf(stderr, "%c %s ", ll, t.utc(s).c_str());
+		vfprintf(stderr, format, ap);
+		fputc('\n', stderr);
+	}
 
 	va_end(ap);
-
-	if (fflush(logf) == EOF) {
-		cerr_m.lock();
-		cerr << "fflush() failed: " << strerror(errno) << '\n';
-		cerr_m.unlock();
-	}
 	logger_m.unlock();
 
 	return;
@@ -115,16 +123,40 @@ void Logger::log(priority_t priority, const char* format, ...)
  *
  * file - file location to open
  */
-void Logger::open(const string& file)
+bool Logger::open(const string& file)
 {
 	close();
 	logger_m.lock();
 	logf = fopen(file.c_str(), "a");
 	logger_m.unlock();
-	if (logf == NULL) {
+	if (logf != NULL) {
+		return true;
+	} else {
 		cerr_m.lock();
 		cerr << "fopen() failed (" << file << "): " << strerror(errno) << '\n';
 		cerr_m.unlock();
-		throw Logger_error("Error opening log file");
+		return false;
 	}
 }
+
+#ifdef UNIT_TEST
+// g++ -Wall -c thread.cpp -o thread.o
+// g++ -Wall -c mutex.cpp -o mutex.o
+// g++ -Wall -c time.cpp -o time.o
+// g++ -Wall -DUNIT_TEST -c logger.cpp -o logger.o
+// g++ -Wall -DUNIT_TEST logger.o mutex.o thread.o time.o -o logger -lpthread
+int main(void)
+{
+	Logger logger;
+
+	logger.open("delete.me");
+	logger.set_loglevel(Logger::MINOR);
+	logger.close();
+	LWARNS("This should appear on stderr");
+	logger.open("delete.me.also");
+	LINFO("%s\n", "hey it works");
+	LDEBUGS("This shouldn't be saved in the file.");
+
+	return 0;
+}
+#endif  // UNIT_TEST
diff --git a/apps/enclave/libsockthread/src/logger.hpp b/apps/enclave/libsockthread/src/logger.hpp
index a51f1b150da161935e156cc92aab6f00bf2ce704..47c26064be6f59527eeb75706bf2081b7686fbc1 100644
--- a/apps/enclave/libsockthread/src/logger.hpp
+++ b/apps/enclave/libsockthread/src/logger.hpp
@@ -31,6 +31,41 @@
 #ifndef LIBSOCKTHREAD_LOGGER_HPP
 #define LIBSOCKTHREAD_LOGGER_HPP
 
+/*
+ * Some helpful macros:
+ *
+ * LDEBUG - debugging messages
+ * LMINOR - unimportant messages
+ * LINFO - informational messages
+ * LWARN - errors we automatically recover from
+ * LERROR - major, important errors
+ *
+ * Obviously, these only work if your Logger object is called "logger" and is
+ * global
+ */
+// Prints out the file name, function name, and line number before the message
+#define LDEBUG(format, ...) logger.log(Logger::DEBUG, "%s:%s:%d:" \
+	format, __FILE__, __func__, __LINE__, __VA_ARGS__)
+// This is the same as above, except it doesn't accept varargs
+#define LDEBUGS(str) logger.log(Logger::DEBUG, "%s:%s:%d:" \
+	str, __FILE__, __func__, __LINE__);
+#define LMINOR(format, ...) logger.log(Logger::MINOR, "%s:%s:%d:" \
+	format, __FILE__, __func__, __LINE__, __VA_ARGS__)
+#define LMINORS(str) logger.log(Logger::MINOR, "%s:%s:%d:" \
+	str, __FILE__, __func__, __LINE__);
+#define LINFO(format, ...) logger.log(Logger::INFO, "%s:%s:%d:" \
+	format, __FILE__, __func__, __LINE__, __VA_ARGS__)
+#define LINFOS(str) logger.log(Logger::INFO, "%s:%s:%d:" \
+	str, __FILE__, __func__, __LINE__);
+#define LWARN(format, ...) logger.log(Logger::WARN, "%s:%s:%d:" \
+	format, __FILE__, __func__, __LINE__, __VA_ARGS__)
+#define LWARNS(str) logger.log(Logger::WARN, "%s:%s:%d:" \
+	str, __FILE__, __func__, __LINE__);
+#define LERROR(format, ...) logger.log(Logger::ERROR, "%s:%s:%d:" \
+	format, __FILE__, __func__, __LINE__, __VA_ARGS__)
+#define LERRORS(str) logger.log(Logger::ERROR, "%s:%s:%d:" \
+	str, __FILE__, __func__, __LINE__);
+
 namespace Libsockthread {
 	class Logger {
 		public:
@@ -43,23 +78,18 @@ namespace Libsockthread {
 
 			void close(void);
 			void log(priority_t priority, const char* format, ...);
-			priority_t get_loglevel(void) const
-				{ mutex.lock(); priority_t ll = loglevel; mutex.unlock(); return ll; }
-			void open(const string& file);  // throws Logger_error
+			priority_t get_loglevel(void)
+				{ logger_m.lock(); priority_t ll = loglevel; logger_m.unlock();
+					return ll; }
+			bool open(const string& file);
 			void set_loglevel(priority_t priority)
-				{ mutex.lock(); loglevel = priority; mutex.unlock(); }
+				{ logger_m.lock(); loglevel = priority; logger_m.unlock(); }
 		private:
 			Mutex cerr_m;
 			FILE* logf;
 			priority_t loglevel;
 			Mutex logger_m;
 	};
-
-	class Logger_error : public runtime_error {
-		public:
-			Logger_error(const string& s)
-				: runtime_error(s) { }
-	};
 }
 
 #endif  // LIBSOCKTHREAD_LOGGER_HPP
diff --git a/apps/enclave/libsockthread/src/time.cpp b/apps/enclave/libsockthread/src/time.cpp
index e67793261e71cbd0578af9e291c88673a59a2e87..50927307ce41493e4e11db181f174639f5b0887f 100644
--- a/apps/enclave/libsockthread/src/time.cpp
+++ b/apps/enclave/libsockthread/src/time.cpp
@@ -44,7 +44,7 @@ string& Time::utc(string &s) const
 
 	tm = gmtime(&unixtime);
 	char t[21];
-	strftime(t, sizeof t, "%Y-%m-%d %H:%M:%SZ", tm);
+	strftime(t, sizeof t, "%Y-%m-%dT%H:%M:%SZ", tm);
 	return s = t;
 }