forked from qt-creator/qt-creator
CtfVisualizer: Do not crash on unexpected types again
And print a nicer error message.
Amends c05f9cacc6
Task-number: QTCREATORBUG-29659
Change-Id: I1db6bea0bedf1fae034fecbbbeae56bb2fee49ed
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
@@ -46,50 +46,56 @@ qint64 CtfTraceManager::traceEnd() const
|
|||||||
|
|
||||||
void CtfTraceManager::addEvent(const json &event)
|
void CtfTraceManager::addEvent(const json &event)
|
||||||
{
|
{
|
||||||
const double timestamp = event.value(CtfTracingClockTimestampKey, -1.0);
|
try {
|
||||||
if (timestamp < 0) {
|
const double timestamp = event.value(CtfTracingClockTimestampKey, -1.0);
|
||||||
// events without or with negative timestamp will be ignored
|
if (timestamp < 0) {
|
||||||
return;
|
// events without or with negative timestamp will be ignored
|
||||||
}
|
return;
|
||||||
if (m_timeOffset < 0) {
|
|
||||||
// the timestamp of the first event is used as the global offset
|
|
||||||
m_timeOffset = timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const auto getStringValue = [](const json &event, const char *key, const QString &def) {
|
|
||||||
if (!event.contains(key))
|
|
||||||
return def;
|
|
||||||
const json val = event[key];
|
|
||||||
if (val.is_string())
|
|
||||||
return QString::fromStdString(val);
|
|
||||||
if (val.is_number()) {
|
|
||||||
return QString::number(int(val));
|
|
||||||
}
|
}
|
||||||
return def;
|
if (m_timeOffset < 0) {
|
||||||
};
|
// the timestamp of the first event is used as the global offset
|
||||||
const QString processId = getStringValue(event, CtfProcessIdKey, "0");
|
m_timeOffset = timestamp;
|
||||||
const QString threadId = getStringValue(event, CtfThreadIdKey, processId);
|
|
||||||
if (!m_threadModels.contains(threadId)) {
|
|
||||||
addModelForThread(threadId, processId);
|
|
||||||
}
|
|
||||||
if (event.value(CtfEventPhaseKey, "") == CtfEventTypeMetadata) {
|
|
||||||
const std::string name = event[CtfEventNameKey];
|
|
||||||
if (name == "thread_name") {
|
|
||||||
m_threadNames[threadId] = QString::fromStdString(event["args"]["name"]);
|
|
||||||
} else if (name == "process_name") {
|
|
||||||
m_processNames[processId] = QString::fromStdString(event["args"]["name"]);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const QPair<bool, qint64> result = m_threadModels[threadId]->addEvent(event, m_timeOffset);
|
static const auto getStringValue =
|
||||||
const bool visibleOnTimeline = result.first;
|
[](const json &event, const char *key, const QString &def) {
|
||||||
if (visibleOnTimeline) {
|
if (!event.contains(key))
|
||||||
m_traceBegin = std::min(m_traceBegin, timestamp);
|
return def;
|
||||||
m_traceEnd = std::max(m_traceEnd, timestamp);
|
const json val = event[key];
|
||||||
} else if (m_timeOffset == timestamp) {
|
if (val.is_string())
|
||||||
// this timestamp was used as the time offset but it is not a visible element
|
return QString::fromStdString(val);
|
||||||
// -> reset the time offset again:
|
if (val.is_number()) {
|
||||||
m_timeOffset = -1.0;
|
return QString::number(int(val));
|
||||||
|
}
|
||||||
|
return def;
|
||||||
|
};
|
||||||
|
const QString processId = getStringValue(event, CtfProcessIdKey, "0");
|
||||||
|
const QString threadId = getStringValue(event, CtfThreadIdKey, processId);
|
||||||
|
if (!m_threadModels.contains(threadId)) {
|
||||||
|
addModelForThread(threadId, processId);
|
||||||
|
}
|
||||||
|
if (event.value(CtfEventPhaseKey, "") == CtfEventTypeMetadata) {
|
||||||
|
const std::string name = event[CtfEventNameKey];
|
||||||
|
if (name == "thread_name") {
|
||||||
|
m_threadNames[threadId] = QString::fromStdString(event["args"]["name"]);
|
||||||
|
} else if (name == "process_name") {
|
||||||
|
m_processNames[processId] = QString::fromStdString(event["args"]["name"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QPair<bool, qint64> result = m_threadModels[threadId]->addEvent(event, m_timeOffset);
|
||||||
|
const bool visibleOnTimeline = result.first;
|
||||||
|
if (visibleOnTimeline) {
|
||||||
|
m_traceBegin = std::min(m_traceBegin, timestamp);
|
||||||
|
m_traceEnd = std::max(m_traceEnd, timestamp);
|
||||||
|
} else if (m_timeOffset == timestamp) {
|
||||||
|
// this timestamp was used as the time offset but it is not a visible element
|
||||||
|
// -> reset the time offset again:
|
||||||
|
m_timeOffset = -1.0;
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
m_errorString = Tr::tr("Error while parsing CTF data: %1.")
|
||||||
|
.arg("<pre>" + QString::fromStdString(event.dump()) + "</pre>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,6 +222,7 @@ void CtfTraceManager::updateStatistics()
|
|||||||
|
|
||||||
void CtfTraceManager::clearAll()
|
void CtfTraceManager::clearAll()
|
||||||
{
|
{
|
||||||
|
m_errorString.clear();
|
||||||
m_modelAggregator->clear();
|
m_modelAggregator->clear();
|
||||||
for (CtfTimelineModel *model: std::as_const(m_threadModels)) {
|
for (CtfTimelineModel *model: std::as_const(m_threadModels)) {
|
||||||
model->deleteLater();
|
model->deleteLater();
|
||||||
@@ -226,6 +233,10 @@ void CtfTraceManager::clearAll()
|
|||||||
m_timeOffset = -1;
|
m_timeOffset = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString CtfTraceManager::errorString() const
|
||||||
|
{
|
||||||
|
return m_errorString;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace CtfVisualizer
|
} // namespace CtfVisualizer
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ public:
|
|||||||
void updateStatistics();
|
void updateStatistics();
|
||||||
void clearAll();
|
void clearAll();
|
||||||
|
|
||||||
|
QString errorString() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void detailsRequested(const QString &title);
|
void detailsRequested(const QString &title);
|
||||||
|
|
||||||
@@ -66,6 +68,7 @@ protected:
|
|||||||
double m_traceEnd = std::numeric_limits<double>::min();
|
double m_traceEnd = std::numeric_limits<double>::min();
|
||||||
double m_timeOffset = -1.0;
|
double m_timeOffset = -1.0;
|
||||||
|
|
||||||
|
QString m_errorString;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -231,6 +231,10 @@ void CtfVisualizerTool::loadJson(const QString &fileName)
|
|||||||
QMessageBox::warning(Core::ICore::dialogParent(),
|
QMessageBox::warning(Core::ICore::dialogParent(),
|
||||||
Tr::tr("CTF Visualizer"),
|
Tr::tr("CTF Visualizer"),
|
||||||
Tr::tr("The file does not contain any trace data."));
|
Tr::tr("The file does not contain any trace data."));
|
||||||
|
} else if (!m_traceManager->errorString().isEmpty()) {
|
||||||
|
QMessageBox::warning(Core::ICore::dialogParent(),
|
||||||
|
Tr::tr("CTF Visualizer"),
|
||||||
|
m_traceManager->errorString());
|
||||||
} else {
|
} else {
|
||||||
m_traceManager->finalize();
|
m_traceManager->finalize();
|
||||||
m_perspective.select();
|
m_perspective.select();
|
||||||
|
|||||||
Reference in New Issue
Block a user