diff --git a/CMakeLists.txt b/CMakeLists.txt
index a432f4e8d3cadf2899f90b13ff687018e4fecd0d..8ba5a8554aba4536d1567d0b64e2d26481768f19 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -25,6 +25,12 @@ if(WITH_ASSERTIONS)
     add_definitions("-DWITH_ASSERTIONS")
 endif()
 
+# enable traces?
+set(WITH_TRACE OFF CACHE BOOL "enable TRACE() macros in code")
+if(WITH_TRACE)
+    add_definitions("-DWITH_TRACE")
+endif()
+
 # TBB support
 set(WITH_TBB OFF CACHE BOOL "use TBB for on-node threading" )
 if(WITH_TBB)
diff --git a/src/util/debug.cpp b/src/util/debug.cpp
index 2dd83f562d3ea15477d7507026a370a87428a36b..029fae921d87e0e37ddde3fa33a60c08d2fb06ef 100644
--- a/src/util/debug.cpp
+++ b/src/util/debug.cpp
@@ -1,9 +1,22 @@
+#include <chrono>
 #include <cstdlib>
+#include <cstring>
+#include <iomanip>
 #include <iostream>
+#include <thread>
 
 #include "util/debug.hpp"
+#include "util/ioutil.hpp"
 
-bool nest::mc::util::failed_assertion(const char *assertion, const char *file,
+namespace nest {
+namespace mc {
+namespace util {
+
+#ifdef WITH_TBB
+std::mutex global_debug_cerr_mutex;
+#endif
+
+bool failed_assertion(const char *assertion, const char *file,
                                       int line, const char *func)
 {
     // Explicit flush, as we can't assume default buffering semantics on stderr/cerr,
@@ -14,3 +27,27 @@ bool nest::mc::util::failed_assertion(const char *assertion, const char *file,
     std::abort();
     return false;
 }
+
+std::ostream& debug_emit_trace_leader(std::ostream &out, const char* file, int line, const char* varlist) {
+    iosfmt_guard _(out);
+
+    const char* leaf = std::strrchr(file, '/');
+    out << (leaf?leaf+1:file) << ':' << line << " ";
+
+    using namespace std::chrono;
+    auto tstamp = system_clock::now().time_since_epoch();
+    auto tstamp_usec = duration_cast<microseconds>(tstamp).count();
+
+    out << std::right << '[';
+    out << std::setw(11) << std::setfill('0') << (tstamp_usec/1000000) << '.';
+    out << std::setw(6)  << std::setfill('0') << (tstamp_usec%1000000) << ']';
+
+    if (varlist && *varlist) {
+        out << ' ' << varlist << ": ";
+    }
+    return out;
+}
+
+} // namespace util
+} // namespace mc
+} // namespace nest
diff --git a/src/util/debug.hpp b/src/util/debug.hpp
index 148b3c44db9b03cd396c10db044e6924b99d7104..6739c4ff1e727b4e04a7cc734c3c30a92f840c98 100644
--- a/src/util/debug.hpp
+++ b/src/util/debug.hpp
@@ -1,15 +1,66 @@
 #pragma once
 
+#include <iostream>
+#include <sstream>
+#include <mutex>
+
 namespace nest {
 namespace mc {
 namespace util {
 
-bool failed_assertion(const char *assertion, const char *file, int line, const char *func);
+bool failed_assertion(const char* assertion, const char* file, int line, const char* func);
+std::ostream &debug_emit_trace_leader(std::ostream& out, const char* file, int line, const char* varlist);
+
+inline void debug_emit(std::ostream& out) {
+    out << "\n";
+}
 
-} 
+template <typename Head, typename... Tail>
+void debug_emit(std::ostream& out, const Head& head, const Tail&... tail) {
+    out << head;
+    if (sizeof...(tail)) {
+        out << ", ";
+    }
+    debug_emit(out, tail...);
 }
+
+#ifdef WITH_TBB
+extern std::mutex global_debug_cerr_mutex;
+#endif
+
+template <typename... Args>
+void debug_emit_trace(const char *file, int line, const char *varlist, const Args&... args) {
+#ifdef WITH_TBB
+    std::stringstream out;
+#else
+    auto &out = std::cerr;
+#endif
+
+    debug_emit_trace_leader(out, file, line, varlist);
+    debug_emit(out, args...);
+
+#ifdef WITH_TBB
+    std::lock_guard<std::mutex> _(global_debug_cerr_mutex);
+    std::cerr << out.rdbuf();
+#else
+    out.flush();
+#endif
 }
 
+} // namespace util
+} // namespace mc
+} // namespace nest
+
+#ifdef WITH_TRACE
+
+#define TRACE(vars...) nest::mc::util::debug_emit_trace(__FILE__, __LINE__, #vars, ##vars)
+
+#else
+
+#define TRACE(...)
+
+#endif
+
 
 #ifdef WITH_ASSERTIONS
 
diff --git a/src/util/ioutil.hpp b/src/util/ioutil.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..b6670072b4529258c52d59b023e71d5313905c9b
--- /dev/null
+++ b/src/util/ioutil.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <ios>
+
+namespace nest {
+namespace mc {
+namespace util {
+
+class iosfmt_guard {
+public:
+    explicit iosfmt_guard(std::ios &stream): save_(nullptr), stream_(stream) {
+        save_.copyfmt(stream_);
+    }
+
+    ~iosfmt_guard() {
+        stream_.copyfmt(save_);
+    }
+
+private:
+    std::ios save_;
+    std::ios& stream_;
+};
+
+
+} // namespace util
+} // namespace mc
+} // namespace nest
+