diff --git a/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.cpp b/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.cpp
index 6c2f80af613f3749adc1b6247bc306f8bb9c9cab..c50e415dcb08afad89a77dc531d9439bc7835623 100644
--- a/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.cpp
+++ b/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.cpp
@@ -24,18 +24,18 @@
 #include <QDebug>
 #include <QTableWidgetItem>
 
-OutgoingMessagesViewerModule::OutgoingMessagesViewerModule(QWidget* parent)
-    : DefaultModule(parent)
+OutgoingMessagesViewerModule::OutgoingMessagesViewerModule()
+    : Module(ModuleId::OUTGOING_MESSAGES_VIEWER)
 {
     setupUi();
-    defaultContextMenuSetup();
+    customContextMenuActionSetup();
 
     // Subscribe to commands, ACKs and NACKs
-    getCore()->getMessageBroker()->subscribe(
+    MessageBroker::getInstance().subscribe(
         Filter::fromString(SkywardHubStrings::logCommandsTopic), this,
         [this](const Message& message, const Filter& filter)
         { handleMsg(message); });
-    getCore()->getMessageBroker()->subscribe(
+    MessageBroker::getInstance().subscribe(
         Filter::fromString(SkywardHubStrings::mavlink_received_msg_ACK_topic),
         this, [this](const Message& message, const Filter& filter)
         { handleAck(message); });
@@ -47,18 +47,35 @@ OutgoingMessagesViewerModule::OutgoingMessagesViewerModule(QWidget* parent)
         Filter::fromString(SkywardHubStrings::mavlink_received_msg_WACK_topic),
         this, [this](const Message& message, const Filter& filter)
         { handleWack(message); });
-}
 
-QWidget* OutgoingMessagesViewerModule::toWidget() { return this; }
+    timer = new QTimer(this);
+    connect(timer, &QTimer::timeout, this,
+            &OutgoingMessagesViewerModule::updateElapsedTime);
+}
 
 XmlObject OutgoingMessagesViewerModule::toXmlObject()
 {
-    return XmlObject(getName(ModuleId::OUTCOMINGMESSAGEVIEWER));
+    XmlObject obj = Module::toXmlObject();
+
+    obj.addAttribute("timestamp", timestamp->isChecked());
+    obj.addAttribute("elapsed_time", elapsedTime->isChecked());
+
+    return obj;
 }
 
-void OutgoingMessagesViewerModule::fromXmlObject(const XmlObject& xmlObject)
+void OutgoingMessagesViewerModule::fromXmlObject(const XmlObject& obj)
 {
-    Q_UNUSED(xmlObject);
+    int timestampAtt;
+    if (obj.getAttribute("timestamp", timestampAtt))
+    {
+        timestamp->setChecked(timestampAtt != 0);
+    }
+
+    int elapsedTimeAtt;
+    if (obj.getAttribute("elapsed_time", elapsedTimeAtt))
+    {
+        elapsedTime->setChecked(elapsedTimeAtt != 0);
+    }
 }
 
 void OutgoingMessagesViewerModule::setupUi()
@@ -68,18 +85,62 @@ void OutgoingMessagesViewerModule::setupUi()
 
     table = new QTableWidget;
     outerLayout->addWidget(table);
-    table->setColumnCount(2);
+    table->setColumnCount(3);
+
+    // Hide elapsed time column
+    table->setColumnHidden(1, true);
+
+    // Hide headers
     table->verticalHeader()->setVisible(false);
     table->horizontalHeader()->setVisible(false);
+
+    // Timestamp and elapse time columns resize to fit content while message
+    // takes all the remaining space
     table->horizontalHeader()->setSectionResizeMode(
         0, QHeaderView::ResizeToContents);
-    table->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
+    table->horizontalHeader()->setSectionResizeMode(
+        1, QHeaderView::ResizeToContents);
+    table->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch);
+
+    // Hide vertical scrollbar
     table->verticalScrollBar()->setVisible(false);
+
+    // Disable items selection
     table->setSelectionMode(QAbstractItemView::NoSelection);
 
     setLayout(outerLayout);
 }
 
+void OutgoingMessagesViewerModule::customContextMenuActionSetup()
+{
+    timestamp = new QAction("Timestamp");
+    timestamp->setCheckable(true);
+    timestamp->setChecked(true);
+    connect(timestamp, &QAction::toggled, this,
+            [this]() { table->setColumnHidden(0, !timestamp->isChecked()); });
+    customContextMenuActions.append(timestamp);
+
+    elapsedTime = new QAction("Elapsed time");
+    elapsedTime->setCheckable(true);
+    connect(elapsedTime, &QAction::toggled, this,
+            [this]()
+            {
+                table->setColumnHidden(1, !elapsedTime->isChecked());
+
+                if (elapsedTime->isChecked() && !timer->isActive())
+                {
+                    timer->start(timerPeriod);
+                }
+                else
+                {
+                    timer->stop();
+                }
+            });
+    customContextMenuActions.append(elapsedTime);
+
+    qDebug() << "Set context menu for outgoing messages viewer";
+}
+
 void OutgoingMessagesViewerModule::resizeEvent(QResizeEvent* event)
 {
     if (table->rowCount() == 0)
@@ -193,7 +254,8 @@ void OutgoingMessagesViewerModule::addMessageToTable(
     const QPair<QDateTime, Message>& msg, int row)
 {
     // Prepare the row items
-    auto dateTxt = new QTableWidgetItem(msg.first.toString("hh.mm.ss"));
+    auto timestampTxt   = new QTableWidgetItem(msg.first.toString("hh.mm.ss"));
+    auto elapsedTimeTxt = new QTableWidgetItem("-00.00.00");
     auto msgName = new QTableWidgetItem(msg.second.getField("name").toString());
     msgName->setBackground(QBrush(QColor(80, 80, 80)));
     msgName->setForeground(QBrush(QColor(0, 0, 0)));
@@ -202,6 +264,28 @@ void OutgoingMessagesViewerModule::addMessageToTable(
     table->insertRow(row);
 
     // Fill the row with data
-    table->setItem(row, 0, dateTxt);
-    table->setItem(row, 1, msgName);
+    table->setItem(row, 0, timestampTxt);
+    table->setItem(row, 1, elapsedTimeTxt);
+    table->setItem(row, 2, msgName);
+}
+
+void OutgoingMessagesViewerModule::updateElapsedTime()
+{
+    auto currentTime = QDateTime::currentDateTime();
+
+    for (int i = 0; i < std::min(table->rowCount(), messages.count()); i++)
+    {
+        auto date = messages[i].first;
+
+        auto elapsedSeconds = date.secsTo(currentTime) % 60;
+        auto elapsedMinutes = (date.secsTo(currentTime) / 60) % 60;
+        auto elapsedHours   = date.secsTo(currentTime) / 3600;
+
+        auto elapsedTimeTxt = QString("-%1:%2:%3")
+                                  .arg(elapsedHours, 2, 'f', 0, '0')
+                                  .arg(elapsedMinutes, 2, 'f', 0, '0')
+                                  .arg(elapsedSeconds, 2, 'f', 0, '0');
+
+        table->item(i, 1)->setText(elapsedTimeTxt);
+    }
 }
diff --git a/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.h b/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.h
index d8c5816070475c4607248f36f46a9e4c312e53c4..2a92998e7223ba29884b0ac39d04a5247be8c0c3 100644
--- a/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.h
+++ b/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.h
@@ -24,22 +24,22 @@
 #include <QDateTime>
 #include <QList>
 #include <QPair>
+#include <QTimer>
 #include <QWidget>
 
-class OutgoingMessagesViewerModule : public DefaultModule
+class OutgoingMessagesViewerModule : public Module
 {
     Q_OBJECT
 
 public:
-    explicit OutgoingMessagesViewerModule(QWidget* parent = nullptr);
-
-    QWidget* toWidget() override;
+    OutgoingMessagesViewerModule();
 
     XmlObject toXmlObject() override;
     void fromXmlObject(const XmlObject& xmlObject) override;
 
 private:
     void setupUi();
+    void customContextMenuActionSetup();
 
     void resizeEvent(QResizeEvent* event = nullptr) override;
 
@@ -50,8 +50,15 @@ private:
 
     void addMessageToTable(const QPair<QDateTime, Message>& msg, int row = 0);
 
+    void updateElapsedTime();
+
     QTableWidget* table;
+    QTimer* timer;
+    QAction* timestamp;
+    QAction* elapsedTime;
 
     QList<QPair<QDateTime, Message>> messages;
-    size_t maxListSize = 20;
+
+    int maxListSize = 20;
+    int timerPeriod = 1000;  // [ms]
 };