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
37class StateMachineLogger : public QObject
38{
39 Q_OBJECT
40
41public:
43 enum LogLevel {
44 Silent = 0,
45 Error = 1,
46 Normal = 2,
47 Verbose = 3,
48 Trace = 4
49 };
50 Q_ENUM(LogLevel)
51
52
72 Q_DECLARE_FLAGS(LogEvents, LogEvent)
73
74
75 struct LogEntry {
76 QDateTime timestamp;
77 qint64 elapsedMs = 0;
80 QString machine;
81 QString state;
83 QString message;
85 qint64 stateDurationMs = 0;
86 QJsonObject context;
87 int depth = 0;
88
89 QString toString(bool colored = false, bool showTiming = true, bool indent = true) const;
90 QJsonObject toJson() const;
91 };
92
93 using LogHandler = std::function<void(const LogEntry&)>;
94
95 explicit StateMachineLogger(QGCStateMachine* machine, QObject* parent = nullptr);
96 ~StateMachineLogger() override;
97
98 // -------------------------------------------------------------------------
99 // Enable/Disable
100 // -------------------------------------------------------------------------
101
102 void setEnabled(bool enabled);
103 bool isEnabled() const { return _enabled; }
104
105 // -------------------------------------------------------------------------
106 // Log Level
107 // -------------------------------------------------------------------------
108
109 void setLogLevel(LogLevel level) { _logLevel = level; }
110 LogLevel logLevel() const { return _logLevel; }
111
113 void setStateLogLevel(const QString& stateName, LogLevel level);
114 void clearStateLogLevel(const QString& stateName);
115
116 // -------------------------------------------------------------------------
117 // Event Filtering
118 // -------------------------------------------------------------------------
119
121 void setLogFilter(LogEvents events) { _logFilter = events; }
122 LogEvents logFilter() const { return _logFilter; }
123
125 void excludeState(const QString& stateName);
126 void includeState(const QString& stateName);
127 void clearExclusions() { _excludedStates.clear(); }
128
129 // -------------------------------------------------------------------------
130 // Output Options
131 // -------------------------------------------------------------------------
132
134 void setColoredOutput(bool enabled) { _coloredOutput = enabled; }
135 bool coloredOutput() const { return _coloredOutput; }
136
138 void setLogTimings(bool enabled) { _logTimings = enabled; }
139 bool logTimings() const { return _logTimings; }
140
142 void setLogIndent(bool enabled) { _logIndent = enabled; }
143 bool logIndent() const { return _logIndent; }
144
146 void setLogTransitionReasons(bool enabled) { _logTransitionReasons = enabled; }
147 bool logTransitionReasons() const { return _logTransitionReasons; }
148
149 // -------------------------------------------------------------------------
150 // Log Sinks
151 // -------------------------------------------------------------------------
152
154 bool setLogFile(const QString& filePath);
155 void closeLogFile();
156
158 void setLogHandler(LogHandler handler) { _customHandler = std::move(handler); }
159
161 void enableCrashLog(int maxEntries);
162 void disableCrashLog();
163 QString dumpCrashLog() const;
164 QList<LogEntry> crashLogEntries() const { return _crashLog; }
165
166 // -------------------------------------------------------------------------
167 // Manual Logging
168 // -------------------------------------------------------------------------
169
171 void log(LogLevel level, const QString& message, const QJsonObject& context = QJsonObject());
172
174 void logEvent(LogEvent event, const QString& message, const QJsonObject& context = QJsonObject());
175
176 // -------------------------------------------------------------------------
177 // Statistics
178 // -------------------------------------------------------------------------
179
181 QHash<LogEvent, int> eventCounts() const { return _eventCounts; }
182
184 void resetStats() { _eventCounts.clear(); }
185
186private slots:
187 void _onMachineStarted();
188 void _onMachineStopped();
189 void _onStateEntered();
190 void _onStateExited();
191
192private:
193 void _log(const LogEntry& entry);
194 void _connectToState(QAbstractState* state);
195 QString _colorize(const QString& text, const QString& colorCode) const;
196 QString _eventColor(LogEvent event) const;
197 LogLevel _effectiveLogLevel(const QString& stateName) const;
198 QString _determineTransitionReason() const;
199
200 QGCStateMachine* _machine = nullptr;
201 bool _enabled = false;
202 LogLevel _logLevel = Normal;
203 LogEvents _logFilter = EventAll;
204
205 bool _coloredOutput = false;
206 bool _logTimings = true;
207 bool _logIndent = true;
208 bool _logTransitionReasons = true;
209
210 QSet<QString> _excludedStates;
211 QHash<QString, LogLevel> _stateLogLevels;
212
213 QFile* _logFile = nullptr;
214 QTextStream* _logStream = nullptr;
215 LogHandler _customHandler;
216
217 QList<LogEntry> _crashLog;
218 int _crashLogMaxEntries = 0;
219
220 QElapsedTimer _machineTimer;
221 QHash<QString, qint64> _stateEntryTimes;
222 QString _previousState;
223 int _currentDepth = 0;
224
225 QHash<LogEvent, int> _eventCounts;
226 QList<QMetaObject::Connection> _connections;
227};
228
229Q_DECLARE_OPERATORS_FOR_FLAGS(StateMachineLogger::LogEvents)
QGroundControl specific state machine with enhanced error handling.
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