diff --git a/src/Lib/Log.cc b/src/Lib/Log.cc
index 35d84b25e3453026386a144b5237b52bf7f8129b..5c97d0c8432145aaacc46531a399acf944f35095 100644
--- a/src/Lib/Log.cc
+++ b/src/Lib/Log.cc
@@ -5,8 +5,8 @@ namespace Vivy
 {
 LogSinkDispatcher::~LogSinkDispatcher() noexcept {}
 
-StderrLogSinkDispatcher::StderrLogSinkDispatcher(LogSink *const sink) noexcept
-    : LogSinkDispatcher(sink, std::string_view{ "stderr" })
+StderrLogSinkDispatcher::StderrLogSinkDispatcher() noexcept
+    : LogSinkDispatcher(std::string_view{ "stderr" })
 {
 }
 
@@ -14,14 +14,15 @@ void
 StderrLogSinkDispatcher::handleLogMessage(const std::string_view category,
                                           const LogMessage &msg) noexcept
 {
-    std::cerr << '[' << category << ']' << msg.getTextBuffer() << '\n';
+    std::cerr << '[' << category << "] " << msg.getTextBuffer() << '\n';
 }
 }
 
 // Vivy::LogSink implementation
 namespace Vivy
 {
-LogSink::~LogSink() noexcept {}
+// Flush all messages before exiting
+LogSink::~LogSink() noexcept { flush(); }
 
 // Get the log message from the logger and add it to the sink's queue.
 void
@@ -53,11 +54,11 @@ LogSink::newSink() noexcept
     return std::make_shared<makeSharedEnabler>();
 }
 
-// void
-// LogSink::registerLogDispatcher(std::shared_ptr<LogSinkDispatcher> dispatcher) noexcept
-// {
-//     logDispatchers.push_back(dispatcher);
-// }
+void
+LogSink::registerLogDispatcher(std::shared_ptr<LogSinkDispatcher> dispatcher) noexcept
+{
+    logDispatchers.push_back(dispatcher);
+}
 }
 
 // Vivy::Logger implementation
@@ -78,8 +79,6 @@ Logger::logEvent(const char *fileName, const char *functionName, const int lineN
                                                 .severity         = logSeverity,
                                                 .lineNumberInFile = lineNumber });
 }
-
-Logger::~Logger() noexcept {}
 }
 
 // Vivy::LogMessage implementation
diff --git a/src/Lib/Log.hh b/src/Lib/Log.hh
index 5d507dafa7a3677caa18a74dacb3b6376c0fce62..dcb33f6bc2b9922c96cbb6afa5d84e623bb11b2f 100644
--- a/src/Lib/Log.hh
+++ b/src/Lib/Log.hh
@@ -2,7 +2,6 @@
 
 #include "Utils.hh"
 
-#define VIVY_NEW_LOG_SINK()             LogSink::newSink()
 #define VIVY_GET_LOGGER(sink, cat)      std::make_shared<Logger>(sink.get(), cat)
 #define VIVY_LOG_WITH_LEVEL(log, level) log->logEvent(__FILE__, __func__, __LINE__, level)
 #define VIVY_LOG_WARN(log)              VIVY_LOG_WITH_LEVEL(log, LogLevel::Warning)
@@ -11,7 +10,9 @@
 #define VIVY_LOG_ERR(log)               VIVY_LOG_WITH_LEVEL(log, LogLevel::Error)
 #define VIVY_LOG_FATAL(log)             VIVY_LOG_WITH_LEVEL(log, LogLevel::Critical)
 
-#define VIVY_DCL_LOG_SINK(sink) std::shared_ptr<LogSink> sink{ VIVY_NEW_LOG_SINK() };
+#define VIVY_DCL_LOG_SINK(sink) std::shared_ptr<LogSink> sink{ LogSink::newSink() };
+#define VIVY_DCL_LOG_DISPATCH(sink, name, dispatch) \
+    std::shared_ptr<dispatch> name{ sink->newDispatcher<dispatch>() };
 
 #define VIVY_LOGGABLE_OBJECT(sink, name, logger)                             \
     std::shared_ptr<Logger> logger{ VIVY_GET_LOGGER(sink, name) };           \
@@ -41,6 +42,35 @@ enum class LogLevel : int {
     None     = std::numeric_limits<int>::min() // In option setup to disable logs
 };
 
+// A LogSinkDispatcher will excavate LogMessages from the Sink and do something
+// with them (save to a file, display in stderr/Vivy console, etc).
+class LogSinkDispatcher {
+    VIVY_UNMOVABLE_OBJECT(LogSinkDispatcher)
+
+    const std::string dispatcherName;
+
+protected:
+    explicit LogSinkDispatcher(const std::string_view name) noexcept
+        : dispatcherName(name)
+    {
+    }
+
+public:
+    const std::string_view getDispatcherName() const noexcept { return dispatcherName; }
+    virtual ~LogSinkDispatcher() noexcept;
+
+    virtual void handleLogMessage(const std::string_view, const LogMessage &) noexcept = 0;
+};
+
+// The stderr dispatcher for logs
+class StderrLogSinkDispatcher : public LogSinkDispatcher {
+    VIVY_UNMOVABLE_OBJECT(StderrLogSinkDispatcher)
+
+public:
+    explicit StderrLogSinkDispatcher() noexcept;
+    void handleLogMessage(const std::string_view, const LogMessage &) noexcept override;
+};
+
 // LogSink is the parent logger. It will recieve messages and display them to a
 // console or to std::cerr or to a file, etc. The save to over file, etc will
 // be donne by the LogSinkDispatcher.
@@ -53,9 +83,18 @@ public:
     static std::shared_ptr<LogSink> newSink() noexcept;
     ~LogSink() noexcept;
 
+    void registerLogDispatcher(std::shared_ptr<LogSinkDispatcher>) noexcept;
     void recieveLogMessage(const Logger *const, LogMessage &&) noexcept;
     void flush() noexcept;
 
+    template <Derived<LogSinkDispatcher> DispatcherType>
+    std::shared_ptr<DispatcherType> newDispatcher() noexcept
+    {
+        std::shared_ptr<DispatcherType> dispatch = std::make_shared<DispatcherType>();
+        registerLogDispatcher(dispatch);
+        return dispatch;
+    }
+
 private:
     std::mutex messageQueueLock{};
     std::vector<std::tuple<const std::string_view, LogMessage>> messageQueue;
@@ -106,28 +145,6 @@ public:
     LogMessage &operator<<(const long) noexcept;
 };
 
-// A LogSinkDispatcher will excavate LogMessages from the Sink and do something
-// with them (save to a file, display in stderr/Vivy console, etc).
-class LogSinkDispatcher : public std::enable_shared_from_this<LogSinkDispatcher> {
-    VIVY_UNMOVABLE_OBJECT(LogSinkDispatcher)
-
-    const std::string dispatcherName;
-
-protected:
-    explicit LogSinkDispatcher(LogSink *const, const std::string_view name) noexcept
-        : dispatcherName(name)
-    {
-        std::shared_ptr<LogSinkDispatcher> self = shared_from_this();
-        // sink->registerLogDispatcher(self);
-    }
-
-public:
-    const std::string_view getDispatcherName() const noexcept { return dispatcherName; }
-    virtual ~LogSinkDispatcher() noexcept;
-
-    virtual void handleLogMessage(const std::string_view, const LogMessage &) noexcept = 0;
-};
-
 // A logger class, a client to LogSink. Will generate and send instances of
 // LogMessage.
 class Logger final : public std::enable_shared_from_this<Logger> {
@@ -136,44 +153,19 @@ class Logger final : public std::enable_shared_from_this<Logger> {
     LogSink *const parentLogSink;
     const std::string logCategory;
 
-    static std::string anyStringToStdString(StringType auto const &str) noexcept
-    {
-        std::string ret;
-        std::size_t i;
-        const std::size_t size = str.size();
-        ret.resize(size);
-        for (i = 0; i < size && str[i]; ++i)
-            ret[i] = str[i];
-        ret.resize(i);
-        return ret;
-    }
-
 public:
     // Templated constructor, construct from anything that can be considered as
     // a string.
     explicit Logger(LogSink *const sink, const StringType auto category) noexcept
         : parentLogSink(sink)
-        , logCategory(anyStringToStdString(category))
+        , logCategory(Utils::anyStringToStdString(category))
     {
     }
 
-    ~Logger() noexcept;
-
-    const std::string_view getCategoryView() const noexcept
-    {
-        return std::string_view{ logCategory };
-    }
+    const std::string_view getCategoryView() const noexcept { return logCategory; }
 
     void sendLogMessage(LogMessage &&) const noexcept;
     LogMessage logEvent(const char *fileName, const char *functionName, const int lineNumber,
                         const LogLevel) noexcept;
 };
-
-class StderrLogSinkDispatcher : public LogSinkDispatcher {
-    VIVY_UNMOVABLE_OBJECT(StderrLogSinkDispatcher)
-
-public:
-    explicit StderrLogSinkDispatcher(LogSink *const sink) noexcept;
-    void handleLogMessage(const std::string_view, const LogMessage &) noexcept override;
-};
 }
diff --git a/src/Lib/Utils.hh b/src/Lib/Utils.hh
index ff65ad6d5c475aa4ad1572db9cfea1aea21a2dd6..6346183b710e520aac0cf0eb43aae8bdfcd07450 100644
--- a/src/Lib/Utils.hh
+++ b/src/Lib/Utils.hh
@@ -123,7 +123,7 @@ uniqAndSort(std::vector<T> &vec) noexcept
 }
 
 // WARN: The V1 and V2 vectors need to be sorted before calling this function.
-template <typename T> inline std::vector<T>
+template <typename T> static inline std::vector<T>
 sortedSetDifference(const std::vector<T> &v1, const std::vector<T> &v2)
 {
     std::vector<T> res{};
@@ -136,6 +136,19 @@ sortedSetDifference(const std::vector<T> &v1, const std::vector<T> &v2)
     return res;
 }
 
+static inline std::string
+anyStringToStdString(StringType auto const &str) noexcept
+{
+    std::string ret;
+    std::size_t i;
+    const std::size_t size = str.size();
+    ret.resize(size);
+    for (i = 0; i < size && str[i]; ++i)
+        ret[i] = str[i];
+    ret.resize(i);
+    return ret;
+}
+
 enum class DocumentType : quint64 {
     /* Basic types */
     Vivy = (1 << 1),
diff --git a/src/VivyApplication.hh b/src/VivyApplication.hh
index 493ab004d60b2f3d9bdc5c6935516e5975f5ad06..ca1254ed08e9fccfc2d3357fa94c22e448b22677 100644
--- a/src/VivyApplication.hh
+++ b/src/VivyApplication.hh
@@ -42,6 +42,7 @@ class MainWindow;
 class VivyApplication : public QApplication {
     Q_OBJECT
     VIVY_DCL_LOG_SINK(logSink)
+    VIVY_DCL_LOG_DISPATCH(logSink, stderrLogDispathcer, StderrLogSinkDispatcher)
     VIVY_LOGGABLE_OBJECT(logSink, std::string_view("APPLICATION"), logger)
 
 public: