diff --git a/ci/summarizer.py b/ci/summarizer.py
index 15e48d03c61bffd4caeb8c43804393abbf00016e..5139df77ab8d09d9c8acf4d90b3cd3471023f3dd 100755
--- a/ci/summarizer.py
+++ b/ci/summarizer.py
@@ -58,7 +58,7 @@ class Summarizer(object):
                 with open(os.path.abspath(file_name)) as code_file:
                     code_lines = code_file.readlines()  # Read the source code file
                     line_of_interest = code_lines[int(violation[0]) - 1]  # Get the desired violation line
-                if line_of_interest.find("// Ignore-MISRA") >= 0:
+                if line_of_interest.find("// Ignore-MISRA") >= 0 or line_of_interest.find("/* Ignore-MISRA */") >= 0:
                     continue
 
                 if file_name not in self.violations_map.keys():
diff --git a/ci/vera.sh b/ci/vera.sh
index 4481cfb2b2b49d904725a211d4c58b51fe4c4048..2ece81da50bfefdefba08effef4bbadc3f7d415f 100755
--- a/ci/vera.sh
+++ b/ci/vera.sh
@@ -10,4 +10,5 @@
 echo -e "\033[0;34mRunning vera++...\033[0m"
 
 cd "$(dirname "$0")/.."
-vera++ --error --parameter max-line-length=120 --profile custom `find src inc test -type f -regextype posix-egrep -regex '.*\.(cpp|hpp|c|h)'`
+vera++ --error --parameter max-line-length=120 --profile custom \
+    `find src inc test -type f -regextype posix-egrep -regex '.*\.(cpp|hpp|c|h)' -not -wholename 'inc/Logger.hpp'`
diff --git a/inc/Logger.hpp b/inc/Logger.hpp
index 3f8a4335628c760241d0baa916b1d8b3f9f60484..894461eae37bee691170f052531e0be55a4956dc 100644
--- a/inc/Logger.hpp
+++ b/inc/Logger.hpp
@@ -7,53 +7,103 @@
 #include <ECSS_Definitions.hpp>
 
 #if defined LOGLEVEL_TRACE
-#define LOGLEVEL Logger::trace
+#define LOGLEVEL Logger::trace // Ignore-MISRA
 #elif defined LOGLEVEL_DEBUG
-#define LOGLEVEL Logger::debug
+#define LOGLEVEL Logger::debug // Ignore-MISRA
 #elif defined LOGLEVEL_INFO
-#define LOGLEVEL Logger::info
+#define LOGLEVEL Logger::info // Ignore-MISRA
 #elif defined LOGLEVEL_NOTICE
-#define LOGLEVEL Logger::notice
+#define LOGLEVEL Logger::notice // Ignore-MISRA
 #elif defined LOGLEVEL_WARNING
-#define LOGLEVEL Logger::warning
+#define LOGLEVEL Logger::warning // Ignore-MISRA
 #elif defined LOGLEVEL_ERROR
-#define LOGLEVEL Logger::error
+#define LOGLEVEL Logger::error // Ignore-MISRA
 #elif defined LOGLEVEL_EMERGENCY
-#define LOGLEVEL Logger::emergency
+#define LOGLEVEL Logger::emergency // Ignore-MISRA
 #else
-#define LOGLEVEL Logger::disabled
+#define LOGLEVEL Logger::disabled // Ignore-MISRA
 #endif
 
-#define _ac_LOGGER_ENABLED_LEVEL(level) (( (Logger::LogLevelType) LOGLEVEL) <= ( (Logger::LogLevelType) level))
+/**
+ * Internal define to check if logging is enabled for a level
+ * @param level A log level
+ * @return bool
+ */
+#define _ac_LOGGER_ENABLED_LEVEL(level) /* Ignore-MISRA */ \
+	(( (Logger::LogLevelType) LOGLEVEL) <= ( (Logger::LogLevelType) level))
 
-#define LOG(level) \
+/**
+ * Create a stream to log a Message
+ *
+ * This functions appends one line to the Logs (which could be printed to screen, transferred via UART or stored for
+ * later use.)
+ *
+ * Examples of usage: \n
+ * `LOG(Logger::debug) << "Reached point of no return";` \n
+ * `LOG(Logger::error) << "More than " << 50 << " dogs found!";`
+ *
+ * You can also use one of the \ref LOG_TRACE, \ref LOG_DEBUG, \ref LOG_INFO, \ref LOG_NOTICE, \ref LOG_WARNING,
+ * \ref LOG_ERROR or \ref LOG_EMERGENCY defines, which avoid the need of explicitly passing the log level: \n
+ * `LOG_DEBUG << "Reached point of no return";` \n
+ * `LOG_ERROR << "More than " << 50 << " dogs found!";`
+ *
+ * See \ref Logger::LogLevel for an explanation of the different log levels.
+ *
+ * @par Implementation details
+ * This macro uses a trick to pass an object where the `<<` operator can be used, and which is logged when the statement
+ * is complete. It uses an `if` statement, initializing a variable within its condition. According to the C++98
+ * standard (1998), Clause 3.3.2.4, "Names declared in the [..] condition of the if statement are local to the if [...]
+ * statement (including the controlled statement) [...]". This result in the \ref Logger::LogEntry::~LogEntry()
+ * to be called as soon as the statement is complete. The bottom `if` statement serves this purpose, and is always
+ * evaluated to true to ensure execution.
+ *
+ * @par
+ * Additionally, the top `if` checks the sufficiency of the log level. It should be optimized away at compile-time on
+ * invisible log entries, meaning that there is no performance overhead for unused calls to LOG.
+ *
+ * @section GlobalLogLevels Global log levels
+ * The **global log level** defines the minimum severity of events to be displayed. Log entries with a severity equal
+ * to or higher than the global log level will be shown. Log entries with a severity smaller than the global log level
+ * will not be shown.
+ *
+ * The global log level can be set by defining one of the following constants:
+ * - `LOGLEVEL_TRACE`
+ * - `LOGLEVEL_DEBUG`
+ * - `LOGLEVEL_INFO`
+ * - `LOGLEVEL_NOTICE`
+ * - `LOGLEVEL_WARNING`
+ * - `LOGLEVEL_ERROR`
+ * - `LOGLEVEL_EMERGENCY`
+ *
+ * @relates Logger
+ * @param level The log level. A value of \ref Logger::LogEntry
+ */
+#define LOG(level)  /* Ignore-MISRA */ \
     if (_ac_LOGGER_ENABLED_LEVEL(level)) \
         if (Logger::LogEntry entry(level); true) \
             entry
 
-#define LOG_TRACE     LOG(Logger::trace)
-#define LOG_DEBUG     LOG(Logger::debug)
-#define LOG_INFO      LOG(Logger::info)
-#define LOG_NOTICE    LOG(Logger::notice)
-#define LOG_WARNING   LOG(Logger::warning)
-#define LOG_ERROR     LOG(Logger::error)
-#define LOG_EMERGENCY LOG(Logger::emergency)
+#define LOG_TRACE     LOG(Logger::trace)     ///< @see LOG @relates Logger
+#define LOG_DEBUG     LOG(Logger::debug)     ///< @see LOG @relates Logger
+#define LOG_INFO      LOG(Logger::info)      ///< @see LOG @relates Logger
+#define LOG_NOTICE    LOG(Logger::notice)    ///< @see LOG @relates Logger
+#define LOG_WARNING   LOG(Logger::warning)   ///< @see LOG @relates Logger
+#define LOG_ERROR     LOG(Logger::error)     ///< @see LOG @relates Logger
+#define LOG_EMERGENCY LOG(Logger::emergency) ///< @see LOG @relates Logger
 
 /**
  * A logging class for ECSS Services that supports ETL's String and is lightweight enough to be used in embedded
  * development.
+ *
+ * @note Always use the \ref LOG macro and its associated utility macros to log. Do not directly use the Logger class.
  */
 class Logger {
-private:
-
-protected:
-
+public:
 	/**
-	 * Default protected constructor for this Logger
+	 * No need to instantiate a Logger object for now.
 	 */
-	Logger() = default;
+	Logger() = delete;
 
-public:
 	/**
 	 * The underlying type to be used for values of Logger::LogLevel.
 	 */
@@ -82,9 +132,9 @@ public:
 	 * Instead of using this class, prefer one of the above macros
 	 */
 	struct LogEntry {
-		String<LOGGER_MAX_MESSAGE_SIZE> message = ""; ///< The current log message itself
+		String<LOGGER_MAX_MESSAGE_SIZE> message = ""; ///< The current log message itself, starting from a blank slate
 		etl::format_spec format; ///< ETL's string format specification
-		LogLevel level;
+		LogLevel level; ///< The log level of this message
 
 		explicit LogEntry(LogLevel level); ///< Create a new LogEntry
 
@@ -97,41 +147,21 @@ public:
 		LogEntry(LogEntry const&) = delete; ///< Unimplemented copy constructor
 	};
 
-	/**
-	 * @brief Unimplemented copy constructor
-	 *
-	 * Does not allow Loggers to be copied. There should be only one instance for each Logger.
-	 */
-	Logger(Logger const&) = delete;
-
-	/**
-	 * Unimplemented assignment operation
-	 *
-	 * Does not allow changing the instances of Loggers, as Loggers are singletons.
-	 */
-	void operator=(Logger const&) = delete;
-
-	/**
-	 * Default destructor
-	 */
-	~Logger() = default;
-
-	/**
-	 * Default move constructor
-	 */
-	Logger(Logger&& service) noexcept = default;
-
-	/**
-	 * Default move assignment operator
-	 */
-	Logger& operator=(Logger&& service) noexcept = default;
-
 	/**
 	 * Store a new log message
 	 */
 	static void log(LogLevel level, String<LOGGER_MAX_MESSAGE_SIZE>& message);
 };
 
+/**
+ * Stream operator to append new values to a log record
+ *
+ * @relates Logger
+ * @tparam T The type of value to append
+ * @param entry The already existing Logger::LogEntry
+ * @param value The new value to add
+ * @return The new Logger::LogEntry where the value has been appended
+ */
 template <class T>
 Logger::LogEntry& operator<<(Logger::LogEntry& entry, const T value) {
 	etl::to_string(value, entry.message, entry.format, true);
diff --git a/src/Logger.cpp b/src/Logger.cpp
index aba0f7a002c5771f9dd4476d0e22b1b1077b96d5..990c49df940068955576993dfcd6ff4bde0c1f79 100644
--- a/src/Logger.cpp
+++ b/src/Logger.cpp
@@ -1,5 +1,6 @@
 #include <Logger.hpp>
 
+// Reimplementation of the function for C strings
 template <>
 Logger::LogEntry& operator<<(Logger::LogEntry& entry, const char* value) {
 	entry.message.append(value);
@@ -8,9 +9,10 @@ Logger::LogEntry& operator<<(Logger::LogEntry& entry, const char* value) {
 }
 
 Logger::LogEntry::LogEntry(LogLevel level) : level(level) {
-	format.precision(3);
+	format.precision(3); // Set precision to 3 decimal digits
 }
 
 Logger::LogEntry::~LogEntry() {
+	// When the destructor is called, the log message is fully "designed". Now we can finally "display" it to the user.
 	Logger::log(level, message);
-}
\ No newline at end of file
+}
diff --git a/src/Platform/x86/Logger.cpp b/src/Platform/x86/Logger.cpp
index 554cd3f7535e72f08789c8514bb76e2aaf004c45..9ee1b8b0fe236cab3d72400f323df9930b4bdcef 100644
--- a/src/Platform/x86/Logger.cpp
+++ b/src/Platform/x86/Logger.cpp
@@ -44,16 +44,16 @@ void Logger::log(Logger::LogLevel level, String<LOGGER_MAX_MESSAGE_SIZE> & messa
 	}
 
 	std::ostringstream ss; // A string stream to create the log message
-	ss << "\033[0;90m" << std::put_time(&tm, "%FT%T%z") << "\033[0m "; // The date
-	ss << "[\033[1;" << colour << "m" << std::setfill(' ') << std::setw(7) << std::right
-		<< name << std::setw(0) << "\033[0m] "; // The log level
+	ss << "\033" "[0;90m" << std::put_time(&tm, "%FT%T%z") << "\033" "[0m "; // The date
+	ss << "[\033" "[1;" << colour << "m" << std::setfill(' ') << std::setw(7) << std::right
+		<< name << std::setw(0) << "\033" "[0m] "; // The log level
 
 	if (keepColour) {
-		ss << "\033[0;" << colour << "m";
+		ss << "\033" "[0;" << colour << "m";
 	}
 	ss << message.c_str(); // The message itself
 	if (keepColour) {
-		ss << "\033[0m";
+		ss << "\033" "[0m";
 	}
 
 	ss << "\n";
diff --git a/src/Platform/x86/main.cpp b/src/Platform/x86/main.cpp
index 251b7ae5a8d70a19833477d41252c5125fb424a1..f53c4ae357477df24e0d3a3eb343f5e98c16a87e 100644
--- a/src/Platform/x86/main.cpp
+++ b/src/Platform/x86/main.cpp
@@ -1,3 +1,5 @@
+#define LOGLEVEL_TRACE
+
 #include <iostream>
 #include <ServicePool.hpp>
 #include <Logger.hpp>
@@ -21,7 +23,7 @@
 #include "etl/String.hpp"
 
 int main() {
-	LOG_NOTICE("ECSS Services test application");
+	LOG_NOTICE << "ECSS Services test application";
 
 	Message packet = Message(0, 0, Message::TC, 1);
 
@@ -338,5 +340,6 @@ int main() {
 	receivedMsg = Message(11, 12, Message::TC, 1);
 	timeBasedSchedulingService.summaryReportActivitiesByID(receivedMsg);
 
+	LOG_NOTICE << "ECSS Services test complete";
 	return 0;
 }
diff --git a/test/TestPlatform.cpp b/test/TestPlatform.cpp
index a4cbee4d07452934aec010d06061b4479cb2d775..1e50ae0f48833268b8bbb336d9589a9ff41b97d9 100644
--- a/test/TestPlatform.cpp
+++ b/test/TestPlatform.cpp
@@ -3,6 +3,7 @@
 #include <catch2/catch.hpp>
 #include <Message.hpp>
 #include <Service.hpp>
+#include <Logger.hpp>
 #include "Services/ServiceTests.hpp"
 
 // Explicit template specializations for the logError() function
@@ -34,6 +35,10 @@ void ErrorHandler::logError(ErrorType errorType) {
 	ServiceTests::addError(ErrorHandler::findErrorSource(errorType), errorType);
 }
 
+void Logger::log(Logger::LogLevel level, String<LOGGER_MAX_MESSAGE_SIZE> & message) {
+	// Logs while testing are completely ignored
+}
+
 struct ServiceTestsListener : Catch::TestEventListenerBase {
 	using TestEventListenerBase::TestEventListenerBase; // inherit constructor