QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
StateMachineLogger.h
Go to the documentation of this file.
1#pragma once
2
3#include <QtCore/QDateTime>
4#include <QtCore/QElapsedTimer>
5#include <QtCore/QFile>
6#include <QtCore/QHash>
7#include <QtCore/QJsonObject>
8#include <QtCore/QList>
9#include <QtCore/QObject>
10#include <QtCore/QSet>
11#include <QtCore/QString>
12#include <QtCore/QTextStream>
13
14#include <functional>
15
16class QAbstractState;
17class QAbstractTransition;
18class QGCStateMachine;
19
38class StateMachineLogger : public QObject
39{
40 Q_OBJECT
41
42public:
44 enum LogLevel {
45 Silent = 0,
46 Error = 1,
47 Normal = 2,
48 Verbose = 3,
49 Trace = 4
50 };
51 Q_ENUM(LogLevel)
52
53
73 Q_DECLARE_FLAGS(LogEvents, LogEvent)
74
75
76 struct LogEntry {
77 QDateTime timestamp;
78 qint64 elapsedMs = 0;
81 QString machine;
82 QString state;
84 QString message;
86 qint64 stateDurationMs = 0;
87 QJsonObject context;
88 int depth = 0;
89
90 QString toString(bool colored = false, bool showTiming = true, bool indent = true) const;
91 QJsonObject toJson() const;
92 };
93
94 using LogHandler = std::function<void(const LogEntry&)>;
95
96 explicit StateMachineLogger(QGCStateMachine* machine, QObject* parent = nullptr);
97 ~StateMachineLogger() override;
98
99 // -------------------------------------------------------------------------
100 // Enable/Disable
101 // -------------------------------------------------------------------------
102
103 void setEnabled(bool enabled);
104 bool isEnabled() const { return _enabled; }
105
106 // -------------------------------------------------------------------------
107 // Log Level
108 // -------------------------------------------------------------------------
109
110 void setLogLevel(LogLevel level) { _logLevel = level; }
111 LogLevel logLevel() const { return _logLevel; }
112
114 void setStateLogLevel(const QString& stateName, LogLevel level);
115 void clearStateLogLevel(const QString& stateName);
116
117 // -------------------------------------------------------------------------
118 // Event Filtering
119 // -------------------------------------------------------------------------
120
122 void setLogFilter(LogEvents events) { _logFilter = events; }
123 LogEvents logFilter() const { return _logFilter; }
124
126 void excludeState(const QString& stateName);
127 void includeState(const QString& stateName);
128 void clearExclusions() { _excludedStates.clear(); }
129
130 // -------------------------------------------------------------------------
131 // Output Options
132 // -------------------------------------------------------------------------
133
135 void setColoredOutput(bool enabled) { _coloredOutput = enabled; }
136 bool coloredOutput() const { return _coloredOutput; }
137
139 void setLogTimings(bool enabled) { _logTimings = enabled; }
140 bool logTimings() const { return _logTimings; }
141
143 void setLogIndent(bool enabled) { _logIndent = enabled; }
144 bool logIndent() const { return _logIndent; }
145
147 void setLogTransitionReasons(bool enabled) { _logTransitionReasons = enabled; }
148 bool logTransitionReasons() const { return _logTransitionReasons; }
149
150 // -------------------------------------------------------------------------
151 // Log Sinks
152 // -------------------------------------------------------------------------
153
155 bool setLogFile(const QString& filePath);
156 void closeLogFile();
157
159 void setLogHandler(LogHandler handler) { _customHandler = std::move(handler); }
160
162 void enableCrashLog(int maxEntries);
163 void disableCrashLog();
164 QString dumpCrashLog() const;
165 QList<LogEntry> crashLogEntries() const { return _crashLog; }
166
167 // -------------------------------------------------------------------------
168 // Manual Logging
169 // -------------------------------------------------------------------------
170
172 void log(LogLevel level, const QString& message, const QJsonObject& context = QJsonObject());
173
175 void logEvent(LogEvent event, const QString& message, const QJsonObject& context = QJsonObject());
176
177 // -------------------------------------------------------------------------
178 // Statistics
179 // -------------------------------------------------------------------------
180
182 QHash<LogEvent, int> eventCounts() const { return _eventCounts; }
183
185 void resetStats() { _eventCounts.clear(); }
186
187private slots:
188 void _onMachineStarted();
189 void _onMachineStopped();
190 void _onStateEntered();
191 void _onStateExited();
192
193private:
194 void _log(const LogEntry& entry);
195 void _connectToState(QAbstractState* state);
196 QString _colorize(const QString& text, const QString& colorCode) const;
197 QString _eventColor(LogEvent event) const;
198 LogLevel _effectiveLogLevel(const QString& stateName) const;
199 QString _determineTransitionReason() const;
200
201 QGCStateMachine* _machine = nullptr;
202 bool _enabled = false;
203 LogLevel _logLevel = Normal;
204 LogEvents _logFilter = EventAll;
205
206 bool _coloredOutput = false;
207 bool _logTimings = true;
208 bool _logIndent = true;
209 bool _logTransitionReasons = true;
210
211 QSet<QString> _excludedStates;
212 QHash<QString, LogLevel> _stateLogLevels;
213
214 QFile* _logFile = nullptr;
215 QTextStream* _logStream = nullptr;
216 LogHandler _customHandler;
217
218 QList<LogEntry> _crashLog;
219 int _crashLogMaxEntries = 0;
220
221 QElapsedTimer _machineTimer;
222 QHash<QString, qint64> _stateEntryTimes;
223 QString _previousState;
224 int _currentDepth = 0;
225
226 QHash<LogEvent, int> _eventCounts;
227 QList<QMetaObject::Connection> _connections;
228};
229
230Q_DECLARE_OPERATORS_FOR_FLAGS(StateMachineLogger::LogEvents)
QGroundControl specific state machine with enhanced error handling.
Extended logging for state machines.
void setEnabled(bool enabled)
void excludeState(const QString &stateName)
Exclude specific states from logging.
std::function< void(const LogEntry &)> LogHandler
void setLogLevel(LogLevel level)
void enableCrashLog(int maxEntries)
Enable crash log buffer (circular buffer for post-mortem analysis)
LogEvents logFilter() const
void setStateLogLevel(const QString &stateName, LogLevel level)
Set log level override for a specific state.
void setLogTimings(bool enabled)
Enable timing annotations.
void log(LogLevel level, const QString &message, const QJsonObject &context=QJsonObject())
Log a custom message.
void setLogIndent(bool enabled)
Enable hierarchy indentation.
void setLogHandler(LogHandler handler)
Set a custom log handler.
void includeState(const QString &stateName)
void setLogFilter(LogEvents events)
Set which events to log (default: all)
LogLevel logLevel() const
bool logTransitionReasons() const
void setLogTransitionReasons(bool enabled)
Log transition reasons (signal name, timeout, etc.)
void logEvent(LogEvent event, const QString &message, const QJsonObject &context=QJsonObject())
Log with specific event type.
LogLevel
Log verbosity levels.
@ Normal
Errors + state changes.
@ Trace
Everything including internal details.
@ Verbose
Normal + signals/transitions.
QString dumpCrashLog() const
void clearStateLogLevel(const QString &stateName)
void resetStats()
Reset statistics.
LogEvent
Types of log events.
void setColoredOutput(bool enabled)
Enable colored console output.
bool setLogFile(const QString &filePath)
Log to a file (in addition to console)
QHash< LogEvent, int > eventCounts() const
Get count of entries by event type.
QList< LogEntry > crashLogEntries() const