5#include <QtCore/QJsonArray>
6#include <QtStateMachine/QAbstractState>
12 connect(_machine, &QStateMachine::started,
this, &StateMachineProfiler::_onMachineStarted);
13 connect(_machine, &QStateMachine::stopped,
this, &StateMachineProfiler::_onMachineStopped);
18 if (_enabled == enabled) {
26 const auto states = _machine->findChildren<QAbstractState*>();
27 for (QAbstractState* state : states) {
28 auto enterConn = connect(state, &QAbstractState::entered,
this, &StateMachineProfiler::_onStateEntered);
29 auto exitConn = connect(state, &QAbstractState::exited,
this, &StateMachineProfiler::_onStateExited);
30 _stateConnections.append(enterConn);
31 _stateConnections.append(exitConn);
35 for (
const auto& conn : _stateConnections) {
38 _stateConnections.clear();
47 _currentStateName.clear();
52 return _profiles.value(stateName);
58 lines << QStringLiteral(
"=== State Machine Profile: %1 ===").arg(_machine->objectName());
59 lines << QStringLiteral(
"Total runtime: %1 ms").arg(_totalRuntimeMs);
60 lines << QStringLiteral(
"Transitions: %1").arg(_transitionCount);
64 QList<StateProfile> sortedProfiles = _profiles.values();
65 std::sort(sortedProfiles.begin(), sortedProfiles.end(),
67 return a.totalTimeMs > b.totalTimeMs;
70 lines << QStringLiteral(
"%1 %2 %3 %4 %5 %6")
77 lines << QString(80,
'-');
79 for (
const auto& p : sortedProfiles) {
80 lines << QStringLiteral(
"%1 %2 %3 %4 %5 %6")
81 .arg(p.name.left(30), -30)
83 .arg(p.totalTimeMs, 10)
84 .arg(p.averageTimeMs(), 10,
'f', 1)
85 .arg(p.minTimeMs == std::numeric_limits<qint64>::max() ? 0 : p.minTimeMs, 10)
86 .arg(p.maxTimeMs, 10);
89 return lines.join(
'\n');
95 root[
"machineName"] = _machine->objectName();
96 root[
"totalRuntimeMs"] = _totalRuntimeMs;
97 root[
"transitionCount"] = _transitionCount;
99 QJsonArray statesArray;
100 for (
auto it = _profiles.constBegin(); it != _profiles.constEnd(); ++it) {
101 QJsonObject stateObj;
102 stateObj[
"name"] = it.value().name;
103 stateObj[
"entryCount"] = it.value().entryCount;
104 stateObj[
"totalTimeMs"] = it.value().totalTimeMs;
105 stateObj[
"averageTimeMs"] = it.value().averageTimeMs();
106 stateObj[
"minTimeMs"] = it.value().minTimeMs == std::numeric_limits<qint64>::max()
107 ? 0 : it.value().minTimeMs;
108 stateObj[
"maxTimeMs"] = it.value().maxTimeMs;
109 statesArray.append(stateObj);
111 root[
"states"] = statesArray;
118 qCDebug(QGCStateMachineLog).noquote() <<
summary();
121void StateMachineProfiler::_onMachineStarted()
123 if (!_enabled)
return;
125 _machineTimer.start();
126 qCDebug(QGCStateMachineLog) <<
"Profiler: Machine started -" << _machine->objectName();
129void StateMachineProfiler::_onMachineStopped()
131 if (!_enabled)
return;
133 _totalRuntimeMs = _machineTimer.elapsed();
134 qCDebug(QGCStateMachineLog) <<
"Profiler: Machine stopped -" << _machine->objectName()
135 <<
"total runtime:" << _totalRuntimeMs <<
"ms";
138void StateMachineProfiler::_onStateEntered()
140 if (!_enabled)
return;
142 auto* state = qobject_cast<QAbstractState*>(sender());
145 _currentStateName = state->objectName();
148 StateProfile&
profile = _profiles[_currentStateName];
156void StateMachineProfiler::_onStateExited()
158 if (!_enabled)
return;
160 auto* state = qobject_cast<QAbstractState*>(sender());
163 QString stateName = state->objectName();
164 qint64 elapsed = _stateTimer.elapsed();
166 StateProfile&
profile = _profiles[stateName];
QGroundControl specific state machine with enhanced error handling.
QString summary() const
Get a human-readable summary.
void logProfile() const
Log the profile to debug output.
QJsonObject toJson() const
Export profile data as JSON.
StateMachineProfiler(QGCStateMachine *machine)
void reset()
Reset all profiling data.
StateProfile profile(const QString &stateName) const
Get profile data for a specific state.
void setEnabled(bool enabled)
Enable or disable profiling.