diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6775e3fff..846980de3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -200,6 +200,16 @@ message(STATUS "StoRM - Using Compiler Configuration: ${STORM_COMPILED_BY}")
 # in the the system does not have a library
 add_subdirectory(resources/3rdparty)
 
+#############################################################
+##
+##	l3pp
+##
+#############################################################
+
+# l3pp is set up as external project
+include_directories(${l3pp_INCLUDE})
+add_dependencies(resources l3pp)
+
 #############################################################
 ##
 ##	gmm
diff --git a/resources/3rdparty/CMakeLists.txt b/resources/3rdparty/CMakeLists.txt
index 9b30445f3..88263eaad 100644
--- a/resources/3rdparty/CMakeLists.txt
+++ b/resources/3rdparty/CMakeLists.txt
@@ -81,3 +81,16 @@ set(GTEST_INCLUDE_DIR ${source_dir}/include PARENT_SCOPE)
 # Specify MainTest's link libraries
 ExternalProject_Get_Property(googletest binary_dir)
 set(GTEST_LIBRARIES ${binary_dir}/libgtest.a ${binary_dir}/libgtest_main.a PARENT_SCOPE)
+
+ExternalProject_Add(
+    l3pp
+    GIT_REPOSITORY https://github.com/hbruintjes/l3pp.git
+    GIT_TAG master
+    SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/l3pp
+    CONFIGURE_COMMAND ""
+    BUILD_COMMAND ""
+    INSTALL_COMMAND ""
+    LOG_INSTALL ON
+)
+ExternalProject_Get_Property(l3pp source_dir)
+set(l3pp_INCLUDE "${source_dir}/" PARENT_SCOPE)
diff --git a/resources/3rdparty/l3pp/LICENSE b/resources/3rdparty/l3pp/LICENSE
new file mode 100644
index 000000000..16ace88d6
--- /dev/null
+++ b/resources/3rdparty/l3pp/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 nafur
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/resources/3rdparty/l3pp/Readme.md b/resources/3rdparty/l3pp/Readme.md
new file mode 100644
index 000000000..b0c4cadd7
--- /dev/null
+++ b/resources/3rdparty/l3pp/Readme.md
@@ -0,0 +1,107 @@
+L3++: Lightweight Logging Library for C++
+=====
+
+L3++ is a self-contained, single-header, cross-platform logging library for C++.
+
+The main goals for this library are simplicity, modularity and ease of use.
+This library is released under the MIT License.
+
+Copyright (C) 2015 Gereon Kremer
+
+
+Concepts
+=====
+
+L3++ is based on the following conceptual components:
+
+* RecordInfo: A record info stores auxiliary information of a log message like the filename, line number and function name where the log message was emitted.
+* Logger: A logger categorizes log messages, usually according to logical components or modules in the source code.
+* Sink: A sink represents a logging output, for example the terminal or a log file.
+* Formatter: A formatter is associated with a sink and converts a log message into an actual string.
+
+
+Log levels
+-----
+The following log levels exist (from `l3pp::LogLevel`):
+* ALL
+* TRACE
+* DEBUG
+* INFO
+* WARN
+* ERR
+* FATAL
+* OFF
+
+Hierarchical Loggers
+-----
+Loggers are hierarchically structured strings like `"app.module.submodule"`. In this example, `submodule` is considered a sublogger of `module` and `app` the parent of `module`. A sublogger implicitly inherits all sinks and the log level of the parent, unless explicitly configured otherwise.
+
+The hierarchical tree of loggers always contains the root logger at the top. The root logger itself does not have a parent, nor a name. It can be accessed via `l3pp::Logging::getRootLogger()`.
+
+Each logger is assigned a log level, or is configured to inherit the log level of the parent (with the special log level `l3pp::LogLevel::INHERIT`). Note that the root logger cannot inherit a log level. Any log entry with a lower level is filtered out and will not be logged.
+
+A logger can also be assigned one or more sinks. By default, a logger will log to both the sinks of its parent, as well as its own sinks. Should a logger only use it own sinks, it should be set to non-additive (using `Logger::setAdditive(false)`).
+
+Sinks
+-----
+A sink provides an output for loggers. Loggers may define multiple sinks, and sinks may be shared between loggers. Sinks are associated with a formatter and a log level. The log level specifies the minimum level of a message for it to be output (independent of the log level of a logger), and by default permits all log messages. A formatter formats the log messages before being output. By default, a simple formatter is used which prints the log level, message and a newline, but other formatters can be specified.
+
+Formatters
+-----
+A formatter shapes a log message before being sent to its final destination. A non-configurable simple formatter exists, as well as a template-based formatter. The latter specifies the format of a message by means of its template arguments, see `l3pp::makeTemplateFormatter`.
+
+
+Basic Usage
+=====
+
+A logger object can be accessed via `l3pp::Logger::getLogger()` or `l3pp::Logger::getRootLogger()`. By default, the root logger does not output anywhere. Therefore, a sink should be added. An initial configuration may look like this:
+
+    l3pp::Logger::initialize();
+    l3pp::SinkPtr sink = log4carl::StreamSink::create(std::clog);
+    l3pp::Logger::getRootLogger()->addSink(sink);
+    l3pp::Logger::getRootLogger()->setLevel(log4carl::LogLevel::INFO);
+
+In this demo, a single sink is created that passes log messages to the standard logging stream `std::clog`. All messages must have at least level `LVL_INFO` before being printed.
+
+The actual logging is performed using a handful of macros.
+These macros
+
+
+Considerations
+=====
+
+Performance
+-----
+While the use of hierarchical loggers and multiple sinks with associated formatters gives a lot of flexibility, it comes at a certain price. As the configuration is done at runtime (and may even change at runtime), the question whether a certain message is printed can only be answered at runtime. Therefore, every message, whether you will ever see it or not, has to pass through the logger and cost runtime.
+
+To mitigate this, we suggest the following:
+
+Create a preprocessor flag (like `ENABLE_LOGGING`) and define your own set of logging macros.
+If this flag is defined, make your macros forward to the `L3PP_LOG_*` macros.
+If this flag is not defined, make your macros do nothing.
+
+
+Multiple usages in the same project
+-----
+Assume you have an application that uses L3++ for logging as well as some other library that also uses L3++.
+L3++ will play nicely in this scenario (partly, it was designed for this case).
+
+However, you should take care of a few things:
+* Colliding loggers: Prefix your loggers with some unique prefix.
+* Colliding macros: If you implement the aforementioned `ENABLE_LOGGING` macro, prefix your macros with your project name. Otherwise, these macros will collide.
+
+
+Implementation Details
+=====
+
+Sinks
+-----
+A sink is a class that provides some `log` method. Any class that inherits from `l3pp::Sink` can be used.
+
+As of now, two implementations are available: 
+* FileSink: Writes to a output file.
+* StreamSink: Writes to any given `std::ostream`, for example to `std::cout`.
+
+Formatters
+-----
+A formatter is a functor that given a log entry, provides a formatted string. The base class `Formatter` provides some very simple formatting, whereas `TemplateFormatter` provides more control over the shape. Internally, a `TemplateFormatter` streams its arguments to a stream before constructing the string. The special types `FieldStr` and `TimeStr` can be used to format particular attributes of a log entry.
diff --git a/resources/3rdparty/l3pp/formatter.h b/resources/3rdparty/l3pp/formatter.h
new file mode 100644
index 000000000..846a8d5e2
--- /dev/null
+++ b/resources/3rdparty/l3pp/formatter.h
@@ -0,0 +1,158 @@
+/**
+ * @file formatter.h
+ * @author Harold Bruintjes <h.bruintjes@cs.rwth-aachen.de>
+ *
+ * Define the Formatter class, used to format output of a sink
+ */
+
+#pragma once
+
+#include <string>
+#include <tuple>
+
+namespace l3pp {
+
+/**
+ * Formats a log messages. This is a base class that simply print the message
+ * with the log level prefix, see derived classes such as TemplatedFormatter
+ * for more interesting data.
+ */
+class Formatter {
+	friend class Logger;
+
+	static void initialize();
+
+	virtual std::string format(EntryContext const& context, std::string const& msg) const;
+public:
+	virtual ~Formatter() {}
+
+	std::string operator()(EntryContext const& context, std::string const& msg) {
+		return format(context, msg);
+	}
+};
+typedef std::shared_ptr<Formatter> FormatterPtr;
+
+/**
+ * Possible fields for FieldStr instance
+ */
+enum class Field {
+	/// Name of the file (everything following the last path separator)
+	FileName,
+	/// Full path of the file
+	FilePath,
+	/// Line number
+	Line,
+	/// Name of function currently executed
+	Function,
+	/// Name of the logger
+	LoggerName,
+	/// Message to be logged
+	Message,
+	/// Level of the log entry
+	LogLevel,
+	/// Number of milliseconds since the logger was initialized
+	WallTime,
+};
+
+/**
+ * Controls justification of formatted log fields.
+ */
+enum class Justification {
+	/// Left align field
+	LEFT,
+	/// Right align field
+	RIGHT
+};
+
+
+
+/**
+ * Formatter for log entry fields, with the exception of time stamp formatting
+ * (see TimeStr for that). The Field template argument determines which field
+ * is printed, see logging::Field.
+ * The other template arguments control the alignment of the output string.
+ */
+template<Field field, int Width = 0, Justification j = Justification::RIGHT, char Fill = ' '>
+class FieldStr {
+public:
+	void stream(std::ostream& os, EntryContext const& context, std::string const& msg) const;
+};
+
+/**
+ * Formatter for log time stamps. The constructor expects a single string
+ * argument which is a formatter for the time stamp. For the specification of
+ * this format string see the documentation for std::put_time . You can use for
+ * example "%c" or "%T".
+ * The template arguments control the alignment of the output string.
+ */
+class TimeStr {
+	std::string formatStr;
+
+public:
+	TimeStr(char const* format) : formatStr(format) {
+	}
+	TimeStr(std::string const& format) : formatStr(format) {
+	}
+
+	void stream(std::ostream& os, EntryContext const& context, std::string const&) const;
+};
+
+/**
+ * Formatter which formats the output based on the (templated) arguments given.
+ * The arguments can be anything that implements the stream operator <<, but
+ * more interestingly also the various FormatField subclasses. These classes
+ * can output the various fields associated with a log entry.
+ */
+template<typename ... Formatters>
+class TemplateFormatter : public Formatter {
+	std::tuple<Formatters...> formatters;
+
+	template <int N>
+	typename std::enable_if<N < (sizeof...(Formatters))>::type
+	formatTuple(EntryContext const& context, std::string const& msg, std::ostream& os) const {
+		formatElement(std::get<N>(formatters), os, context, msg);
+		formatTuple<N+1>(context, msg, os);
+	}
+
+	template <int N>
+	typename std::enable_if<(N >= sizeof...(Formatters))>::type
+	formatTuple(EntryContext const&, std::string const&, std::ostream&) const {
+	}
+
+	template<Field field, int Width, Justification j, char Fill>
+	void formatElement(FieldStr<field, Width, j, Fill> const& t, std::ostream& stream, EntryContext const& context, std::string const& msg) const {
+		t.stream(stream, context, msg);
+	}
+
+	void formatElement(TimeStr const& t, std::ostream& stream, EntryContext const& context, std::string const& msg) const {
+		t.stream(stream, context, msg);
+	}
+
+	template<typename T>
+	void formatElement(T const& t, std::ostream& stream, EntryContext const&, std::string const&) const {
+		stream << t;
+	}
+public:
+	TemplateFormatter(Formatters ... formatters) :
+		formatters(std::forward<Formatters>(formatters)...)
+	{
+	}
+
+	std::string format(EntryContext const& context, std::string const& msg) const override;
+};
+
+/**
+ * Helper function to create a TemplateFormatter. Simply call with some
+ * formatable arguments, e.g.,
+ * @code{.cpp}
+ * logging::makeTemplateFormatter(
+ *     logging::FieldStr<logging::Field::LogLevel>(), " - ",
+ *     logging::FieldStr<logging::Field::Message>(), "\n");
+ * @endcode
+ */
+template<typename ... Formatters>
+FormatterPtr makeTemplateFormatter(Formatters&& ... formatters) {
+	return std::make_shared<TemplateFormatter<Formatters...>>(std::forward<Formatters>(formatters)...);
+}
+
+}
diff --git a/resources/3rdparty/l3pp/impl/formatter.h b/resources/3rdparty/l3pp/impl/formatter.h
new file mode 100644
index 000000000..c4e29d18a
--- /dev/null
+++ b/resources/3rdparty/l3pp/impl/formatter.h
@@ -0,0 +1,106 @@
+/**
+ * @file formatter.h
+ * @author Harold Bruintjes <h.bruintjes@cs.rwth-aachen.de>
+ *
+ * Implementation of Formatter classes
+ */
+
+#pragma once
+
+#include <chrono>
+#include <ctime>
+#include <iomanip>
+#include <sstream>
+#include <cstring> //strrchr
+
+namespace l3pp {
+
+namespace detail {
+	/**
+	 * Internal function to get wall-time
+	 */
+	inline static std::chrono::system_clock::time_point GetStartTime() {
+		static std::chrono::system_clock::time_point startTime = std::chrono::system_clock::now();
+		return startTime;
+	}
+}
+
+inline void Formatter::initialize() {
+	// Init wall-time
+	detail::GetStartTime();
+}
+
+inline std::string Formatter::format(EntryContext const& context, std::string const& msg) const {
+	std::stringstream stream;
+	stream << context.level << " - " << msg << '\n';
+	return stream.str();
+}
+
+template<Field field, int Width, Justification j, char Fill>
+inline void FieldStr<field, Width, j, Fill>::stream(std::ostream& os, EntryContext const& context, std::string const& msg) const {
+	os << std::setw(Width);
+	os << std::setfill(Fill);
+	switch(j) {
+		case Justification::LEFT:
+			os << std::left;
+		case Justification::RIGHT:
+			os << std::right;
+	}
+
+	switch(field) {
+		case Field::FileName:
+#ifdef _WIN32
+			os << strrchr(context.filename, '\\')+1;
+#else
+			os << strrchr(context.filename, '/')+1;
+#endif
+			break;
+		case Field::FilePath:
+			os << context.filename;
+			break;
+		case Field::Line:
+			os << context.line;
+			break;
+		case Field::Function:
+			os << context.funcname;
+			break;
+		case Field::LoggerName:
+			os << context.logger->getName();
+			break;
+		case Field::Message:
+			os << msg;
+			break;
+		case Field::LogLevel:
+			os << context.level;
+			break;
+		case Field::WallTime:
+			auto runtime = context.timestamp - detail::GetStartTime();
+			os << std::chrono::duration_cast<std::chrono::milliseconds>(runtime).count();
+			break;
+	}
+}
+
+inline void TimeStr::stream(std::ostream& os, EntryContext const& context, std::string const&) const {
+	auto time = std::chrono::system_clock::to_time_t(context.timestamp);
+	auto timeinfo = localtime (&time);
+#if __GNUC__ >= 5 || __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 7) || _MSC_VER >= 1700
+//TODO: Need better way to detect thing
+	os << std::put_time(timeinfo, formatStr.c_str());
+#else
+	char buffer[1024];
+	if (strftime(buffer, 1024, formatStr.c_str(), timeinfo)) {
+		os << buffer;
+	}
+#endif
+}
+
+template<typename ... Formatters>
+inline std::string TemplateFormatter<Formatters...>::format(EntryContext const& context, std::string const& msg) const {
+	std::stringstream stream;
+
+	formatTuple<0>(context, msg, stream);
+
+	return stream.str();
+}
+
+}
diff --git a/resources/3rdparty/l3pp/impl/logger.h b/resources/3rdparty/l3pp/impl/logger.h
new file mode 100644
index 000000000..1b14e8bdb
--- /dev/null
+++ b/resources/3rdparty/l3pp/impl/logger.h
@@ -0,0 +1,123 @@
+/**
+ * @file logger.h
+ *
+ * Defines the base Logger class
+ */
+
+#pragma once
+
+#include <vector>
+#include <algorithm>
+#include <map>
+#include <sstream>
+
+namespace l3pp {
+
+namespace detail {
+	/**
+	 * Internal function to get all configured loggers. Should not be used
+	 * directly, see Logger::getLogger()
+	 */
+	static inline std::map<std::string, LogPtr>& GetLoggers() {
+		static std::map<std::string, LogPtr> loggers;
+		return loggers;
+	}
+}
+
+inline LogStream::~LogStream() {
+	if (level != LogLevel::OFF) {
+		logger.log(level, stream.str(), context);
+	}
+}
+
+inline void Logger::logEntry(EntryContext const& context, std::string const& msg) {
+	for(auto& sink: sinks) {
+		sink->log(context, msg);
+	}
+	if (additive && parent) {
+		parent->logEntry(context, msg);
+	}
+}
+
+inline void Logger::removeSink(SinkPtr sink) {
+	std::vector<SinkPtr>::iterator pos = std::find(sinks.begin(), sinks.end(), sink);
+	if (pos != sinks.end()) {
+		sinks.erase(pos);
+	}
+}
+
+inline void Logger::log(LogLevel level, std::string const& msg, EntryContext context) {
+	if (level < getLevel()) {
+		return;
+	}
+
+	context.level = level;
+	context.logger = this;
+	logEntry(context, msg);
+}
+
+inline LogStream Logger::log(LogLevel level, EntryContext context) {
+	if (level < getLevel()) {
+		// Effectively disables the stream
+		return LogStream(*this, LogLevel::OFF, context);
+	} else {
+		return LogStream(*this, level, context);
+	}
+}
+
+inline void Logger::initialize() {
+	// Setup root logger
+	getRootLogger();
+	// Set wall time
+	Formatter::initialize();
+}
+
+inline void Logger::deinitialize() {
+	detail::GetLoggers().clear();
+	getRootLogger()->sinks.clear();
+}
+
+inline LogPtr Logger::getRootLogger() {
+	static LogPtr rootLogger = LogPtr(new Logger());
+	return rootLogger;
+}
+
+inline LogPtr Logger::getLogger(std::string name) {
+	if (name.size() == 0) {
+		// Root logger
+		return getRootLogger();
+	}
+	auto& loggers = detail::GetLoggers();
+	auto it = loggers.find(name);
+	if (it != loggers.end()) {
+		return it->second;
+	} else {
+		auto n = name.rfind('.');
+		LogPtr parent;
+		if (n == std::string::npos) {
+			parent = getRootLogger();
+		} else{
+			parent = getLogger(name.substr(0, n));
+		}
+		LogPtr newLogger = LogPtr(new Logger(name, parent));
+		loggers.emplace(name, newLogger);
+		return newLogger;
+	}
+}
+
+template<typename T>
+inline LogStream const& operator<<(LogStream const& stream, T const& val) {
+	if (stream.level != LogLevel::OFF) {
+		stream.stream << val;
+	}
+	return stream;
+}
+
+inline LogStream const& operator<<(LogStream const& stream, std::ostream& (*F)(std::ostream&)) {
+	if (stream.level != LogLevel::OFF) {
+		stream.stream << F;
+	}
+	return stream;
+}
+
+}
diff --git a/resources/3rdparty/l3pp/impl/logging.h b/resources/3rdparty/l3pp/impl/logging.h
new file mode 100644
index 000000000..290317478
--- /dev/null
+++ b/resources/3rdparty/l3pp/impl/logging.h
@@ -0,0 +1,32 @@
+/**
+ * @file logging.h
+ *
+ * Implementation of general logging functionality
+ */
+
+#pragma once
+
+#include <ostream>
+
+namespace l3pp {
+
+/**
+ * Streaming operator for LogLevel.
+ * @param os Output stream.
+ * @param level LogLevel.
+ * @return os.
+ */
+inline std::ostream& operator<<(std::ostream& os, LogLevel level) {
+	switch (level) {
+		case LogLevel::TRACE:   return os << "TRACE";
+		case LogLevel::DEBUG:   return os << "DEBUG";
+		case LogLevel::INFO:    return os << "INFO";
+		case LogLevel::WARN:    return os << "WARN";
+		case LogLevel::ERR:     return os << "ERROR";
+		case LogLevel::FATAL:   return os << "FATAL";
+		case LogLevel::OFF:     return os << "OFF";
+		default:                return os << "???";
+	}
+}
+
+}
diff --git a/resources/3rdparty/l3pp/impl/sink.h b/resources/3rdparty/l3pp/impl/sink.h
new file mode 100644
index 000000000..19a22bca9
--- /dev/null
+++ b/resources/3rdparty/l3pp/impl/sink.h
@@ -0,0 +1,18 @@
+/**
+ * @file sink.h
+ *
+ * Implementation for Sinks
+ */
+
+#pragma once
+
+namespace l3pp {
+
+inline void Sink::log(EntryContext const& context, std::string const& message) const {
+	if (context.level >= this->level) {
+		logEntry((*formatter)(context, message));
+	}
+}
+
+}
+
diff --git a/resources/3rdparty/l3pp/l3pp.h b/resources/3rdparty/l3pp/l3pp.h
new file mode 100644
index 000000000..ea44a45ec
--- /dev/null
+++ b/resources/3rdparty/l3pp/l3pp.h
@@ -0,0 +1,165 @@
+/**
+ * @file l3pp.h
+ * @author Gereon Kremer <gereon.kremer@cs.rwth-aachen.de>
+ * @author Harold Bruintjes <h.bruintjes@cs.rwth-aachen.de>
+ *
+ * The lightweight logging library for C++.
+ *
+ * This logging facility is fairly generic and is used as a simple and
+ * header-only alternative to more advanced solutions like log4cplus or
+ * boost::log.
+ *
+ * The basic components are Sinks, Formatters and Loggers.
+ *
+ * A Sink represents a logging output like a terminal or a log file.
+ * This implementation provides a FileSink and a StreamSink, but the basic
+ * Sink class can be extended as necessary.
+ *
+ * A Formatter is associated with a Sink and produces the actual string that is
+ * sent to the Sink.
+ * Usually, it adds auxiliary information like the current time, LogLevel and
+ * source location to the string logged by the user.
+ * The Formatter implements a reasonable default behavior for simple logging,
+ * but it can be subclassed and modified as necessary.
+ *
+ * The Logger class finally plugs all these components together.
+ * Individual loggers can log to one or more sinks (inheritable) and are
+ * associated with an (inheritable) log level.
+ *
+ * Initial configuration may look like this:
+ * @code{.cpp}
+ * l3pp::Logger::initialize();
+ * l3pp::SinkPtr sink = l3pp::StreamSink::create(std::clog);
+ * l3pp::Logger::getRootLogger()->addSink(sink);
+ * l3pp::Logger::getRootLogger()->setLevel(l3pp::LogLevel::INFO);
+ * @endcode
+ * 
+ * Macro facilitate the usage:
+ * <ul>
+ * <li>`L3PP_LOG_<LVL>(logger, msg)` produces a normal log message where
+ * logger should be string identifying the logger (or a LogPtr) and msg is the
+ * message to be logged.</li>
+ * </ul>
+ * Any message (`msg`) can be an arbitrary expression that one would
+ * stream to an `std::ostream` like `stream << (msg);`. The default formatter
+ * adds newlines.
+ * Manipulators are generally supported. However, for performance avoid std::endl
+ * and use '\n' directly.
+ */
+
+#pragma once
+
+#include <chrono>
+#include <memory>
+
+namespace l3pp {
+
+/**
+ * Indicated which log messages should be forwarded to some sink.
+ * 
+ * All messages which have a level that is equal or greater than the specified
+ * value will be forwarded.
+ */
+enum class LogLevel {
+	/// Log messages used for tracing the program flow in detail.
+	TRACE,
+	/// Log messages used for debugging.
+	DEBUG,
+	/// Log messages used for information.
+	INFO,
+	/// Log messages used to warn about an undesired state.
+	WARN,
+	/// Log messages used for errors that can be handled.
+	ERR,
+	/// Log messages used for errors that lead to program termination.
+	FATAL,
+	/// Log no messages.
+	OFF,
+	/// Parent level
+	INHERIT,
+	/// Default log level.
+	DEFAULT = WARN,
+	/// All log messages.
+	ALL = TRACE
+};
+
+/**
+ * Streaming operator for LogLevel.
+ * @param os Output stream.
+ * @param level LogLevel.
+ * @return os.
+ */
+inline std::ostream& operator<<(std::ostream& os, LogLevel level);
+
+class Logger;
+
+/**
+ * Contextual information for a new log entry, contains such this as location,
+ * log info (level, logger) and the time of the event.
+ * A context will be created automatically by using the macros
+ */
+struct EntryContext {
+	// Program location
+	const char* filename;
+	size_t line;
+	const char* funcname;
+
+	// Time of entry
+	std::chrono::system_clock::time_point timestamp;
+
+	// Log event info
+	Logger const* logger;
+	LogLevel level;
+
+	EntryContext(const char* filename, size_t line, const char* funcname) :
+		filename(filename), line(line), funcname(funcname),
+		timestamp(std::chrono::system_clock::now()), logger(nullptr),
+		level(LogLevel::OFF)
+	{
+	}
+
+	EntryContext() :
+		filename(""), line(0), funcname(""),
+		timestamp(std::chrono::system_clock::now()), logger(nullptr),
+		level(LogLevel::OFF)
+	{
+	}
+};
+
+}
+
+#include "formatter.h"
+#include "sink.h"
+#include "logger.h"
+
+#include "impl/logging.h"
+#include "impl/logger.h"
+#include "impl/formatter.h"
+#include "impl/sink.h"
+
+#ifdef _MSC_VER
+#define __func__ __FUNCTION__
+#endif
+
+/// Create a record info.
+#define __L3PP_LOG_RECORD l3pp::EntryContext(__FILE__, __LINE__, __func__)
+/// Basic logging macro.
+#define __L3PP_LOG(level, channel, expr) do { \
+    auto L3PP_channel = ::l3pp::Logger::getLogger(channel); \
+    if (L3PP_channel->getLevel() <= level) { \
+        L3PP_channel->log(level, __L3PP_LOG_RECORD) << expr; \
+    } \
+} while(false)
+
+/// Log with level TRACE.
+#define L3PP_LOG_TRACE(channel, expr) __L3PP_LOG(::l3pp::LogLevel::TRACE, channel, expr)
+/// Log with level DEBUG.
+#define L3PP_LOG_DEBUG(channel, expr) __L3PP_LOG(::l3pp::LogLevel::DEBUG, channel, expr)
+/// Log with level INFO.
+#define L3PP_LOG_INFO(channel, expr) __L3PP_LOG(::l3pp::LogLevel::INFO, channel, expr)
+/// Log with level WARN.
+#define L3PP_LOG_WARN(channel, expr) __L3PP_LOG(::l3pp::LogLevel::WARN, channel, expr)
+/// Log with level ERROR.
+#define L3PP_LOG_ERROR(channel, expr) __L3PP_LOG(::l3pp::LogLevel::ERR, channel, expr)
+/// Log with level FATAL.
+#define L3PP_LOG_FATAL(channel, expr) __L3PP_LOG(::l3pp::LogLevel::FATAL, channel, expr)
diff --git a/resources/3rdparty/l3pp/logger.h b/resources/3rdparty/l3pp/logger.h
new file mode 100644
index 000000000..6dab1cbcb
--- /dev/null
+++ b/resources/3rdparty/l3pp/logger.h
@@ -0,0 +1,179 @@
+/**
+ * @file logger.h
+ *
+ * Defines the base Logger class
+ */
+
+#pragma once
+
+#include <vector>
+#include <sstream>
+
+namespace l3pp {
+
+/**
+ * LogStream is a logger object that can be streamed into, writing an entry
+ * to the logger associated upon destruction. Instances of this classer are
+ * returned by Logger log() functions, so they can be used as such:
+ * logger->debug() << "Message";
+ */
+class LogStream {
+	friend class Logger;
+
+	Logger& logger;
+	LogLevel level;
+	EntryContext context;
+	mutable std::ostringstream stream;
+
+	LogStream(Logger& logger, LogLevel level, EntryContext context) :
+		logger(logger), level(level), context(context)
+	{
+	}
+
+	LogStream(const LogStream&) = delete;
+	LogStream& operator=(const LogStream&) = delete;
+public:
+	LogStream(LogStream&& other) :
+		logger(other.logger), level(other.level), context(std::move(other.context))/*,
+		stream(std::move(other.stream))*/
+	{
+		stream.str(other.stream.str());
+	}
+	~LogStream();
+
+	template<typename T>
+	friend LogStream const& operator<<(LogStream const& stream, T const& val);
+	friend LogStream const& operator<<(LogStream const& stream, std::ostream& (*F)(std::ostream&));
+};
+
+/**
+ * Main logger class. Keeps track of all Logger instances, and can be used to
+ * log various messages. Before the logging library is used, make sure to
+ * call Logger::initialize(). Loggers are hierarchically nested, by means of
+ * names separated by a period. All loggers are a (indirect) child of the root
+ * logger, see Logger::getRootLogger() and Logger::getLogger().
+ * A logger is associated with a LogLevel. Any entry with a level below this
+ * level will be filtered out. A LogLevel of INHERIT means the parent log
+ * level will be compared against instead.
+ * A logger can be associated with 1 or more Sinks. A log entry is printed to
+ * each associated sink. If the Logger is set additive (see getAdditive(),
+ * setAdditive()) parent sinks are logged to as well (by default true).
+ * Logging can be performed either as a single string message, or by using a
+ * stream. The latter requires the end() method to be called before the entry
+ * is logged. For convenience, various logging macros are defined at the end
+ * of this header.
+ */
+class Logger {
+	friend class Formatter;
+
+	typedef std::shared_ptr<Logger> LogPtr;
+
+	LogPtr parent;
+	std::string name;
+	LogLevel level;
+	std::vector<SinkPtr> sinks;
+	bool additive;
+
+	// Logger constructors are private
+	Logger() : parent(nullptr), name(""), level(LogLevel::DEFAULT),
+		additive(true)
+	{
+
+	}
+
+	Logger(std::string const& name, LogPtr parent) : parent(parent), name(name),
+		level(LogLevel::INHERIT), additive(true)
+	{
+	}
+
+	void logEntry(EntryContext const& context, std::string const& msg);
+
+public:
+	void addSink(SinkPtr sink) {
+		sinks.push_back(sink);
+	}
+
+	void removeSink(SinkPtr sink);
+
+	void setLevel(LogLevel level) {
+		if (level == LogLevel::INHERIT && !parent) {
+			return;
+		}
+		this->level = level;
+	}
+
+	LogLevel getLevel() const {
+		if (level == LogLevel::INHERIT) {
+			return parent->getLevel();
+		}
+		return level;
+	}
+
+	std::string const& getName() const {
+		return name;
+	}
+
+	bool getAdditive() const {
+		return additive;
+	}
+
+	void setAdditive(bool additive) {
+		this->additive = additive;
+	}
+
+	void log(LogLevel level, std::string const& msg, EntryContext context = EntryContext());
+
+	void trace(std::string const& msg, EntryContext context = EntryContext()) {
+		log(LogLevel::TRACE, msg, context);
+	}
+	void debug(std::string const& msg, EntryContext context = EntryContext()) {
+		log(LogLevel::DEBUG, msg, context);
+	}
+	void info(std::string const& msg, EntryContext context = EntryContext()) {
+		log(LogLevel::INFO, msg, context);
+	}
+	void warn(std::string const& msg, EntryContext context = EntryContext()) {
+		log(LogLevel::WARN, msg, context);
+	}
+	void error(std::string const& msg, EntryContext context = EntryContext()) {
+		log(LogLevel::ERR, msg, context);
+	}
+	void fatal(std::string const& msg, EntryContext context = EntryContext()) {
+		log(LogLevel::FATAL, msg, context);
+	}
+
+	LogStream log(LogLevel level, EntryContext context = EntryContext());
+
+	LogStream trace(EntryContext context = EntryContext()) {
+		return log(LogLevel::TRACE, context);
+	}
+	LogStream debug(EntryContext context = EntryContext()) {
+		return log(LogLevel::DEBUG, context);
+	}
+	LogStream info(EntryContext context = EntryContext()) {
+		return log(LogLevel::INFO, context);
+	}
+	LogStream warn(EntryContext context = EntryContext()) {
+		return log(LogLevel::WARN, context);
+	}
+	LogStream error(EntryContext context = EntryContext()) {
+		return log(LogLevel::ERR, context);
+	}
+	LogStream fatal(EntryContext context = EntryContext()) {
+		return log(LogLevel::FATAL, context);
+	}
+
+	static void initialize();
+	static void deinitialize();
+
+	static LogPtr getRootLogger();
+
+	static LogPtr getLogger(LogPtr logger) {
+		return logger;
+	}
+
+	static LogPtr getLogger(std::string name);
+};
+typedef std::shared_ptr<Logger> LogPtr;
+
+}
diff --git a/resources/3rdparty/l3pp/sink.h b/resources/3rdparty/l3pp/sink.h
new file mode 100644
index 000000000..9b381ffb7
--- /dev/null
+++ b/resources/3rdparty/l3pp/sink.h
@@ -0,0 +1,108 @@
+/**
+ * @file sink.h
+ *
+ * Defines classes for log sinks (i.e. outputs)
+ */
+
+#pragma once
+
+#include <ostream>
+#include <fstream>
+
+namespace l3pp {
+
+/**
+ * Base class for a logging sink. It can only log some log entry to which some
+ * formatting is applied (see Formatter). A Sink may be given a log level,
+ * which filters out all entries below that level. By default is logs all
+ * entries.
+ */
+class Sink {
+	LogLevel level;
+	FormatterPtr formatter;
+
+	virtual void logEntry(std::string const& entry) const = 0;
+public:
+	Sink() : level(LogLevel::ALL), formatter(std::make_shared<Formatter>()) {
+
+	}
+	Sink(FormatterPtr formatter) : level(LogLevel::ALL), formatter(formatter) {
+
+	}
+	/**
+	 * Default destructor.
+     */
+	virtual ~Sink() {}
+
+	LogLevel getLevel() const {
+		return level;
+	}
+
+	void setLevel(LogLevel level) {
+		this->level = level;
+	}
+
+	FormatterPtr getFormatter() const {
+		return formatter;
+	}
+
+	void setFormatter(FormatterPtr formatter) {
+		this->formatter = formatter;
+	}
+
+	/**
+	 * Logs the given message with context info
+	 */
+	void log(EntryContext const& context, std::string const& message) const;
+};
+typedef std::shared_ptr<Sink> SinkPtr;
+
+/**
+ * Logging sink that wraps an arbitrary `std::ostream`.
+ * It is meant to be used for streams like `std::cout` or `std::cerr`.
+ */
+class StreamSink: public Sink {
+	/// Output stream.
+	mutable std::ostream os;
+
+	void logEntry(std::string const& entry) const override {
+		os << entry << std::flush;
+	}
+
+	explicit StreamSink(std::ostream& _os) :
+		os(_os.rdbuf()) {}
+public:
+	/**
+	 * Create a StreamSink from some output stream.
+     * @param os Output stream.
+     */
+	static SinkPtr create(std::ostream& os) {
+		return SinkPtr(new StreamSink(os));
+	}
+};
+/**
+ * Logging sink for file output.
+ */
+class FileSink: public Sink {
+	/// File output stream.
+	mutable std::ofstream os;
+
+	void logEntry(std::string const& entry) const override {
+		os << entry << std::flush;
+	}
+
+	explicit FileSink(const std::string& filename) :
+		os(filename, std::ios::out) {}
+public:
+	/**
+	 * Create a FileSink that logs to the specified file.
+	 * The file is truncated upon construction.
+     * @param filename
+     */
+	static SinkPtr create(const std::string& filename) {
+		return SinkPtr(new FileSink(filename));
+	}
+};
+
+}
+
diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp
index 4fb6131df..3f0682e54 100644
--- a/src/builder/ExplicitDFTModelBuilder.cpp
+++ b/src/builder/ExplicitDFTModelBuilder.cpp
@@ -86,7 +86,7 @@ namespace storm {
             } else {
                 STORM_LOG_TRACE("Transition matrix: too big to print");
             }
-            STORM_LOG_TRACE("Exit rates: " << modelComponents.exitRates);
+            STORM_LOG_TRACE("Exit rates: " << storm::utility::vector::toString<ValueType>(modelComponents.exitRates));
             STORM_LOG_TRACE("Markovian states: " << modelComponents.markovianStates);
             
             // Build state labeling
diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp
index c9e88410d..0c2e80f53 100644
--- a/src/cli/cli.cpp
+++ b/src/cli/cli.cpp
@@ -186,14 +186,13 @@ namespace storm {
             }
             
             if (storm::settings::getModule<storm::settings::modules::GeneralSettings>().isVerboseSet()) {
-                STORM_GLOBAL_LOGLEVEL_INFO();
+                storm::utility::setLogLevel(l3pp::LogLevel::INFO);
             }
             if (storm::settings::getModule<storm::settings::modules::DebugSettings>().isDebugSet()) {
-                STORM_GLOBAL_LOGLEVEL_DEBUG();
-                
+                storm::utility::setLogLevel(l3pp::LogLevel::DEBUG);
             }
             if (storm::settings::getModule<storm::settings::modules::DebugSettings>().isTraceSet()) {
-                STORM_GLOBAL_LOGLEVEL_TRACE();
+                 storm::utility::setLogLevel(l3pp::LogLevel::TRACE);
             }
             if (storm::settings::getModule<storm::settings::modules::DebugSettings>().isLogfileSet()) {
                 storm::utility::initializeFileLogging();
diff --git a/src/settings/modules/DebugSettings.cpp b/src/settings/modules/DebugSettings.cpp
index 0f37e7ce7..92e8de9a9 100644
--- a/src/settings/modules/DebugSettings.cpp
+++ b/src/settings/modules/DebugSettings.cpp
@@ -38,7 +38,7 @@ namespace storm {
             }
             
             std::string DebugSettings::getLogfilename() const {
-                return this->getOption(traceOptionName).getArgumentByName("filename").getValueAsString();
+                return this->getOption(logfileOptionName).getArgumentByName("filename").getValueAsString();
             }
             
             bool DebugSettings::isTestSet() const {
@@ -47,4 +47,4 @@ namespace storm {
             
         } // namespace modules
     } // namespace settings
-} // namespace storm
\ No newline at end of file
+} // namespace storm
diff --git a/src/utility/initialize.cpp b/src/utility/initialize.cpp
index ac139d1c9..273d0dee0 100644
--- a/src/utility/initialize.cpp
+++ b/src/utility/initialize.cpp
@@ -1,30 +1,55 @@
 #include "initialize.h"
 
-#include "src/utility/macros.h"
 #include "src/settings/SettingsManager.h"
 #include "src/settings/modules/DebugSettings.h"
 
-int storm_runtime_loglevel = STORM_LOGLEVEL_WARN;
+#include <iostream>
+#include <fstream>
 
 namespace storm {
     namespace utility {
-        
+
         void initializeLogger() {
-            // Intentionally left empty.
+            l3pp::Logger::initialize();
+            // By default output to std::cout
+            l3pp::SinkPtr sink = l3pp::StreamSink::create(std::cout);
+            l3pp::Logger::getRootLogger()->addSink(sink);
+            // Default to warn, set by user to something else
+            l3pp::Logger::getRootLogger()->setLevel(l3pp::LogLevel::WARN);
+
+            l3pp::FormatterPtr fptr = l3pp::makeTemplateFormatter(
+                    l3pp::FieldStr<l3pp::Field::LogLevel, 5, l3pp::Justification::LEFT>(),
+                    " (", l3pp::FieldStr<l3pp::Field::FileName>(), ':', l3pp::FieldStr<l3pp::Field::Line>(), "): ",
+                    l3pp::FieldStr<l3pp::Field::Message>(), '\n'
+                );
+            sink->setFormatter(fptr);
         }
-        
+
         void setUp() {
             initializeLogger();
             std::cout.precision(10);
         }
-        
+
         void cleanUp() {
             // Intentionally left empty.
         }
-        
+
+        void setLogLevel(l3pp::LogLevel level) {
+            l3pp::Logger::getRootLogger()->setLevel(level);
+            if (level <= l3pp::LogLevel::DEBUG) {
+#if STORM_LOG_DISABLE_DEBUG
+                std::cout << "***** warning ***** requested loglevel is not compiled\n";
+#endif
+            }
+        }
+
         void initializeFileLogging() {
-            // FIXME.
+            if (storm::settings::getModule<storm::settings::modules::DebugSettings>().isLogfileSet()) {
+                std::string logFileName = storm::settings::getModule<storm::settings::modules::DebugSettings>().getLogfilename();
+                l3pp::SinkPtr sink = l3pp::FileSink::create(logFileName);
+                l3pp::Logger::getRootLogger()->addSink(sink);
+            }
         }
-        
+
     }
 }
diff --git a/src/utility/initialize.h b/src/utility/initialize.h
index 6241add70..48e4855c9 100644
--- a/src/utility/initialize.h
+++ b/src/utility/initialize.h
@@ -1,6 +1,8 @@
 #ifndef STORM_UTILITY_INITIALIZE_H
 #define	STORM_UTILITY_INITIALIZE_H
 
+#include "src/utility/logging.h"
+
 namespace storm {
     namespace utility {
         /*!
@@ -17,6 +19,11 @@ namespace storm {
          */
         void cleanUp();
 
+        /*!
+         * Set the global log level
+         */
+        void setLogLevel(l3pp::LogLevel level);
+
         /*!
          * Sets up the logging to file.
          */
diff --git a/src/utility/logging.h b/src/utility/logging.h
new file mode 100644
index 000000000..2fc58a008
--- /dev/null
+++ b/src/utility/logging.h
@@ -0,0 +1,23 @@
+#ifndef STORM_UTILITY_LOGGING_H_
+#define STORM_UTILITY_LOGGING_H_
+
+#include <l3pp.h>
+
+#if !defined(STORM_LOG_DISABLE_DEBUG) && !defined(STORM_LOG_DISABLE_TRACE)
+#define STORM_LOG_TRACE(message) L3PP_LOG_TRACE(l3pp::Logger::getRootLogger(), message)
+#else
+#define STORM_LOG_TRACE(message) (void)(0)
+#endif
+
+#if !defined(STORM_LOG_DISABLE_DEBUG)
+#define STORM_LOG_DEBUG(message) L3PP_LOG_DEBUG(l3pp::Logger::getRootLogger(), message)
+#else
+#define STORM_LOG_DEBUG(message) (void)(0)
+#endif
+
+// Define STORM_LOG_WARN, STORM_LOG_ERROR and STORM_LOG_INFO to log the given message with the corresponding log levels.
+#define STORM_LOG_INFO(message) L3PP_LOG_INFO(l3pp::Logger::getRootLogger(), message)
+#define STORM_LOG_WARN(message) L3PP_LOG_WARN(l3pp::Logger::getRootLogger(), message)
+#define STORM_LOG_ERROR(message) L3PP_LOG_ERROR(l3pp::Logger::getRootLogger(), message)
+
+#endif /* STORM_UTILITY_LOGGING_H_ */
diff --git a/src/utility/macros.h b/src/utility/macros.h
index b72cf5f26..2d49be58b 100644
--- a/src/utility/macros.h
+++ b/src/utility/macros.h
@@ -1,128 +1,47 @@
 #ifndef STORM_UTILITY_MACROS_H_
 #define STORM_UTILITY_MACROS_H_
 
-#include <cassert>
-#include <string.h>
-
-#include "storm-config.h"
+#include "src/utility/logging.h"
 
 #include <iostream>
-#include <sstream>
-
-extern int storm_runtime_loglevel;
-
-#define STORM_LOGLEVEL_ERROR 0
-#define STORM_LOGLEVEL_WARN 1
-#define STORM_LOGLEVEL_INFO 2
-#define STORM_LOGLEVEL_DEBUG 3
-#define STORM_LOGLEVEL_TRACE 4
-
-#ifdef STORM_LOG_DISABLE_DEBUG
-#define STORM_LOG_DISABLE_TRACE
-#endif
-
-
-#define __SHORT_FORM_OF_FILE__ \
-(strrchr(__FILE__,'/') \
-? strrchr(__FILE__,'/')+1 \
-: __FILE__ \
-)
-
-#ifndef STORM_LOG_DISABLE_DEBUG
-#define STORM_LOG_DEBUG(message)                                    \
-do {                                                                \
-    if(storm_runtime_loglevel >= STORM_LOGLEVEL_DEBUG) {            \
-        std::stringstream __ss;                                     \
-        __ss << message;                                            \
-        std::cout << "DEBUG (" << __SHORT_FORM_OF_FILE__ << ":" << __LINE__ << "): " <<  __ss.str() << std::endl;        \
-    }                                                               \
-} while (false)
-#else
-#define STORM_LOG_DEBUG(message)                                    \
-do {                                                                \
-} while (false)                                                        
-#endif
-
-#ifndef STORM_LOG_DISABLE_TRACE
-#define STORM_LOG_TRACE(message)                                \
-do {                                                            \
-    if(storm_runtime_loglevel >= STORM_LOGLEVEL_TRACE) {        \
-        std::stringstream __ss;                                 \
-        __ss << message;                                        \
-        std::cout << "TRACE (" << __SHORT_FORM_OF_FILE__ << ":" << __LINE__ << "): " <<  __ss.str() << std::endl;       \
-    }                                                           \
-} while(false)  
-#else
-#define STORM_LOG_TRACE(message)                                \
-do {                                                            \
-} while (false)    
-#endif
-
+#include <cassert>
 
 // Define STORM_LOG_ASSERT which is only checked when NDEBUG is not set.
 #ifndef NDEBUG
 #define STORM_LOG_ASSERT(cond, message)                     \
 do {                                                        \
-if (!(cond)) {                                              \
-std::cout << "ASSERT FAILED (" << __SHORT_FORM_OF_FILE__ << ":" << __LINE__ << "): " <<  message << std::endl;     \
-assert(cond);                                               \
-}                                                           \
-} while (false)                                 
+    if (!(cond)) {                                          \
+        STORM_LOG_ERROR(message);                           \
+        assert(cond);                                       \
+    }                                                       \
+} while (false)
 
 #else
-#define STORM_LOG_ASSERT(cond, message)         
+#define STORM_LOG_ASSERT(cond, message)
 #endif
+
 // Define STORM_LOG_THROW to always throw the exception with the given message if the condition fails to hold.
 #define STORM_LOG_THROW(cond, exception, message)               \
 do {                                                            \
     if (!(cond)) {                                              \
-        std::cout << "ERROR (" << __SHORT_FORM_OF_FILE__ << ":" << __LINE__ << "): " <<  message << std::endl;       \
+        STORM_LOG_ERROR(message);                               \
         throw exception() << message;                           \
     }                                                           \
-} while (false)                                
-
-
-// Define STORM_LOG_WARN, STORM_LOG_ERROR and STORM_LOG_INFO to log the given message with the corresponding log levels.
-#define STORM_LOG_WARN(message)                                \
-do {                                                           \
-    if(storm_runtime_loglevel >= STORM_LOGLEVEL_WARN) {        \
-        std::stringstream __ss;                                \
-        __ss << message;                                       \
-        std::cout << "WARN  (" << __SHORT_FORM_OF_FILE__ << ":" << __LINE__ << "): " <<  __ss.str() << std::endl;      \
-    }                                                          \
-} while (false)                               
+} while (false)
 
 #define STORM_LOG_WARN_COND(cond, message)                      \
 do {                                                            \
     if (!(cond)) {                                              \
-        STORM_LOG_WARN(message);                                 \
-    }                                                           \
-} while (false)                                 
-
-#define STORM_LOG_INFO(message)                                 \
-do {                                                            \
-    if(storm_runtime_loglevel >= STORM_LOGLEVEL_INFO) {         \
-        std::stringstream __ss;                                 \
-        __ss << message;                                        \
-        std::cout << "INFO  (" << __SHORT_FORM_OF_FILE__ << ":" << __LINE__ << "): " << __ss.str() << std::endl;       \
+        STORM_LOG_WARN(message);                                \
     }                                                           \
-} while (false)                                 
+} while (false)
 
 #define STORM_LOG_INFO_COND(cond, message)                      \
 do {                                                            \
     if (!(cond)) {                                              \
         STORM_LOG_INFO(message);                                \
     }                                                           \
-} while (false)                                 
-
-#define STORM_LOG_ERROR(message)                                \
-do {                                                            \
-    if(storm_runtime_loglevel >= STORM_LOGLEVEL_ERROR) {        \
-        std::stringstream __ss;                                 \
-        __ss << message;                                        \
-        std::cout << "ERROR (" << __SHORT_FORM_OF_FILE__  << ":" << __LINE__ << "): " << __ss.str() << std::endl;       \
-    }                                                           \
-} while (false)                                                 \
+} while (false)
 
 #define STORM_LOG_ERROR_COND(cond, message)     \
 do {                                            \
@@ -131,37 +50,6 @@ do {                                            \
     }                                           \
 } while (false)                                 \
 
-#define STORM_GLOBAL_LOGLEVEL_ERROR()               \
-do {                                                \
-storm_runtime_loglevel = STORM_LOGLEVEL_ERROR;      \
-} while(false)
-
-#define STORM_GLOBAL_LOGLEVEL_INFO()                \
-do {                                                \
-storm_runtime_loglevel = STORM_LOGLEVEL_INFO;       \
-} while (false)
-
-#ifndef STORM_LOG_DISABLE_DEBUG
-#define STORM_GLOBAL_LOGLEVEL_DEBUG()               \
-do {                                                \
-storm_runtime_loglevel = STORM_LOGLEVEL_DEBUG;      \
-} while(false)
-#else 
-#define STORM_GLOBAL_LOGLEVEL_DEBUG()               \
-std::cout << "***** warning ***** loglevel debug is not compiled\n"
-#endif 
-
-#ifndef STORM_LOG_DISABLE_TRACE
-#define STORM_GLOBAL_LOGLEVEL_TRACE()               \
-do {                                                \
-storm_runtime_loglevel = STORM_LOGLEVEL_TRACE;      \
-} while(false)
-#else
-#define STORM_GLOBAL_LOGLEVEL_TRACE()               \
-std::cout << "***** warning ***** loglevel trace is not compiled\n"
-#endif
-
-
 /*!
  * Define the macros that print information and optionally also log it.
  */