blob: 1a97d9eaa6e1512397bcf59a9efe5f0af35c3301 [file] [log] [blame]
/* SPDX-License-Identifier: LGPL-2.1 */
/*
* Copyright (C) 2017 VMware Inc, Yordan Karadzhov <ykaradzhov@vmware.com>
*/
/**
* @file KsUtils.hpp
* @brief KernelShark Utils.
*/
#ifndef _KS_UTILS_H
#define _KS_UTILS_H
// C++ 11
#include <chrono>
// Qt
#include <QtWidgets>
// KernelShark
#include "libkshark.h"
#include "libkshark-model.h"
#include "KsCmakeDef.hpp"
#include "KsPlotTools.hpp"
/** Macro providing the height of the screen in pixels. */
#define SCREEN_HEIGHT QGuiApplication::screens()[0]->geometry().height()
/** Macro providing the width of the screen in pixels. */
#define SCREEN_WIDTH QGuiApplication::screens()[0]->geometry().width()
//! @cond Doxygen_Suppress
static auto fontHeight = []()
{
QFont font;
QFontMetrics fm(font);
return fm.height();
};
static auto stringWidth = [](QString s)
{
QFont font;
QFontMetrics fm(font);
#ifdef QT_VERSION_LESS_5_11
return fm.width(s);
#else
return fm.horizontalAdvance(s);
#endif // QT_VERSION_LESS_5_11
};
//! @endcond
/** Macro providing the height of the font in pixels. */
#define FONT_HEIGHT fontHeight()
/** Macro providing the width of the font in pixels. */
#define FONT_WIDTH (stringWidth("KernelShark") / 11)
/** Macro providing the width of a string in pixels. */
#define STRING_WIDTH(s) stringWidth(s)
/** Macro providing the height of the KernelShark graphs in pixels. */
#define KS_GRAPH_HEIGHT (FONT_HEIGHT * 2)
//! @cond Doxygen_Suppress
#define KS_JSON_CAST(doc) \
reinterpret_cast<json_object *>(doc)
#define KS_C_STR_CAST(doc) \
reinterpret_cast<const char *>(doc)
typedef std::chrono::high_resolution_clock::time_point hd_time;
#define GET_TIME std::chrono::high_resolution_clock::now()
#define GET_DURATION(t0) \
std::chrono::duration_cast<std::chrono::duration<double>>( \
std::chrono::high_resolution_clock::now() - t0).count()
#ifdef QT_VERSION_LESS_5_15
#define KS_SPLIT_SkipEmptyParts QString::SkipEmptyParts
#else
#define KS_SPLIT_SkipEmptyParts Qt::SkipEmptyParts
#endif // QT_VERSION_LESS_5_15
//! @endcond
namespace KsUtils {
QVector<int> getCPUList(int sd);
QVector<int> getPidList(int sd);
QVector<int> getEventIdList(int sd);
int getEventId(int sd, const QString &eventName);
QString getEventName(int sd, int eventId);
QStringList getEventFieldsList(int sd, int eventId);
kshark_event_field_format getEventFieldType(int sd, int eventId,
const QString &fieldName);
QVector<int> getStreamIdList(kshark_context *kshark_ctx);
QVector<int> getFilterIds(kshark_hash_id *filter);
/** @brief Geat the list of plugins provided by the package. */
inline QStringList getPluginList() {return QString(KS_BUILTIN_PLUGINS).split(";");}
void listFilterSync(bool state);
void graphFilterSync(bool state);
QCheckBox *addCheckBoxToMenu(QMenu *menu, QString name);
/** @brief Convert the timestamp of the trace record into a string showing
* the time in seconds.
*
* @param ts: Input location for the timestamp.
* @param prec: the number of digits after the decimal point in the return
* string.
*
* @returns String showing the time in seconds.
*/
inline QString Ts2String(int64_t ts, int prec)
{
return QString::number(ts * 1e-9, 'f', prec);
}
bool matchCPUVisible(kshark_context *kshark_ctx,
kshark_entry *e, int sd, int *cpu);
bool isInstalled();
QString getFile(QWidget *parent,
const QString &windowName,
const QString &filter,
QString &lastFilePath);
QStringList getFiles(QWidget *parent,
const QString &windowName,
const QString &filter,
QString &lastFilePath);
QString getSaveFile(QWidget *parent,
const QString &windowName,
const QString &filter,
const QString &extension,
QString &lastFilePath);
void setElidedText(QLabel* label, QString text,
enum Qt::TextElideMode mode,
int labelWidth);
QStringList splitArguments(QString cmd);
QVector<int> parseIdList(QString v_str);
QMap<int, QVector<int>> parseTaskList(QString v_str);
QStringList getTepEvtName(int sd, int eventId);
/** Get a string to be used as a standard name of a CPU graph. */
inline QString cpuPlotName(int cpu) {return QString("CPU %1").arg(cpu);}
QString taskPlotName(int sd, int pid);
/** Get the total number of Data streams. */
inline int getNStreams()
{
kshark_context *kshark_ctx(nullptr);
if (!kshark_instance(&kshark_ctx))
return -1;
return kshark_ctx->n_streams;
}
QString streamDescription(kshark_data_stream *stream);
}; // KsUtils
/** Identifier of the Dual Marker active state. */
enum class DualMarkerState {
A,
B
};
/**
* The KsDataStore class provides the access to trace data for all KernelShark
* widgets.
*/
class KsDataStore : public QObject
{
Q_OBJECT
public:
explicit KsDataStore(QWidget *parent = nullptr);
~KsDataStore();
int loadDataFile(const QString &file,
QVector<kshark_dpi *> plugins);
int appendDataFile(const QString &file, int64_t shift);
void clear();
/** Get the trace data array. */
kshark_entry **rows() const {return _rows;}
/** Get a reference of the trace data array. */
kshark_entry ***rows_r() {return &_rows;}
/** Get the size of the data array. */
ssize_t size() const {return _dataSize;}
/** Set the size of the data (number of entries). */
void setSize(ssize_t s) {_dataSize = s;}
void reload();
void update();
void registerCPUCollections();
void unregisterCPUCollections();
void applyPosTaskFilter(int sd, QVector<int> vec);
void applyNegTaskFilter(int sd, QVector<int> vec);
void applyPosEventFilter(int sd, QVector<int> vec);
void applyNegEventFilter(int sd, QVector<int> vec);
void applyPosCPUFilter(int sd, QVector<int> vec);
void applyNegCPUFilter(int sd, QVector<int> vec);
void clearAllFilters();
void setClockOffset(int sd, int64_t offset);
signals:
/**
* This signal is emitted when the data has changed and the View
* widgets have to update.
*/
void updateWidgets(KsDataStore *);
private:
/** Trace data array. */
kshark_entry **_rows;
/** The size of the data array. */
ssize_t _dataSize;
int _openDataFile(kshark_context *kshark_ctx, const QString &file);
void _freeData();
void _applyIdFilter(int filterId, QVector<int> vec, int sd);
void _addPluginsToStream(kshark_context *kshark_ctx, int sd,
QVector<kshark_dpi *> plugins);
};
/** A Plugin Manager class. */
class KsPluginManager : public QObject
{
Q_OBJECT
public:
explicit KsPluginManager(QWidget *parent = nullptr);
QStringList getStreamPluginList(int sd) const;
QVector<int> getActivePlugins(int sd) const;
QVector<int> getPluginsByStatus(int sd, int status) const;
/** Get a list of all plugins added by the user. */
const QVector<kshark_plugin_list *>
getUserPlugins() const {return _userPlugins;}
void registerPluginMenues();
void updatePlugins(int sd, QVector<int> pluginStates);
void addPlugins(const QStringList &fileNames, QVector<int> streams);
void registerPlugins(const QString &pluginNames);
void unregisterPlugins(const QString &pluginNames);
void registerPluginToStream(const QString &pluginName,
QVector<int> streamId);
void unregisterPluginFromStream(const QString &pluginName,
QVector<int> streamId);
void deletePluginDialogs();
/** Append to the list of User plugin. */
void addUserPluginToList(kshark_plugin_list *p) {_userPlugins.append(p);}
signals:
/** This signal is emitted when a plugin is loaded or unloaded. */
void dataReload();
private:
QVector<kshark_plugin_list *> _userPlugins;
/** Plugin dialogs. */
QVector<QWidget *> _pluginDialogs;
QVector<kshark_plugin_list *>
_loadPluginList(const QStringList &plugins);
std::string _pluginLibFromName(const QString &plugin);
std::string _pluginNameFromLib(const QString &plugin);
void _pluginToStream(const QString &pluginName,
QVector<int> streamId,
bool reg);
};
KsPlot::Color& operator <<(KsPlot::Color &thisColor, const QColor &c);
QColor& operator <<(QColor &thisColor, const KsPlot::Color &c);
#endif