mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 18:06:57 +02:00
Many improvements:
* Get crash settings in assignment clients * Allow custom crash reporting URL and token * Fix setting system -- the client's one doesn't belong in the server * Lots more documentation Commit just before moving things around.
This commit is contained in:
parent
f218e54eac
commit
25755f9c88
23 changed files with 361 additions and 63 deletions
|
@ -371,6 +371,8 @@ void AssetServer::completeSetup() {
|
||||||
auto& domainHandler = nodeList->getDomainHandler();
|
auto& domainHandler = nodeList->getDomainHandler();
|
||||||
const QJsonObject& settingsObject = domainHandler.getSettingsObject();
|
const QJsonObject& settingsObject = domainHandler.getSettingsObject();
|
||||||
|
|
||||||
|
commonParseSettingsObject(settingsObject);
|
||||||
|
|
||||||
static const QString ASSET_SERVER_SETTINGS_KEY = "asset_server";
|
static const QString ASSET_SERVER_SETTINGS_KEY = "asset_server";
|
||||||
|
|
||||||
if (!settingsObject.contains(ASSET_SERVER_SETTINGS_KEY)) {
|
if (!settingsObject.contains(ASSET_SERVER_SETTINGS_KEY)) {
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "AudioMixerClientData.h"
|
#include "AudioMixerClientData.h"
|
||||||
#include "AvatarAudioStream.h"
|
#include "AvatarAudioStream.h"
|
||||||
#include "InjectedAudioStream.h"
|
#include "InjectedAudioStream.h"
|
||||||
|
#include "crash-handler/CrashHandler.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@ static const QString AUDIO_ENV_GROUP_KEY = "audio_env";
|
||||||
static const QString AUDIO_BUFFER_GROUP_KEY = "audio_buffer";
|
static const QString AUDIO_BUFFER_GROUP_KEY = "audio_buffer";
|
||||||
static const QString AUDIO_THREADING_GROUP_KEY = "audio_threading";
|
static const QString AUDIO_THREADING_GROUP_KEY = "audio_threading";
|
||||||
|
|
||||||
|
|
||||||
int AudioMixer::_numStaticJitterFrames{ DISABLE_STATIC_JITTER_FRAMES };
|
int AudioMixer::_numStaticJitterFrames{ DISABLE_STATIC_JITTER_FRAMES };
|
||||||
float AudioMixer::_noiseMutingThreshold{ DEFAULT_NOISE_MUTING_THRESHOLD };
|
float AudioMixer::_noiseMutingThreshold{ DEFAULT_NOISE_MUTING_THRESHOLD };
|
||||||
float AudioMixer::_attenuationPerDoublingInDistance{ DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE };
|
float AudioMixer::_attenuationPerDoublingInDistance{ DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE };
|
||||||
|
@ -560,6 +562,8 @@ void AudioMixer::clearDomainSettings() {
|
||||||
void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) {
|
void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) {
|
||||||
qCDebug(audio) << "AVX2 Support:" << (cpuSupportsAVX2() ? "enabled" : "disabled");
|
qCDebug(audio) << "AVX2 Support:" << (cpuSupportsAVX2() ? "enabled" : "disabled");
|
||||||
|
|
||||||
|
commonParseSettingsObject(settingsObject);
|
||||||
|
|
||||||
if (settingsObject.contains(AUDIO_THREADING_GROUP_KEY)) {
|
if (settingsObject.contains(AUDIO_THREADING_GROUP_KEY)) {
|
||||||
QJsonObject audioThreadingGroupObject = settingsObject[AUDIO_THREADING_GROUP_KEY].toObject();
|
QJsonObject audioThreadingGroupObject = settingsObject[AUDIO_THREADING_GROUP_KEY].toObject();
|
||||||
const QString AUTO_THREADS = "auto_threads";
|
const QString AUTO_THREADS = "auto_threads";
|
||||||
|
|
|
@ -988,6 +988,8 @@ void AvatarMixer::handlePacketVersionMismatch(PacketType type, const SockAddr& s
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) {
|
void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) {
|
||||||
|
commonParseSettingsObject(domainSettings);
|
||||||
|
|
||||||
const QString AVATAR_MIXER_SETTINGS_KEY = "avatar_mixer";
|
const QString AVATAR_MIXER_SETTINGS_KEY = "avatar_mixer";
|
||||||
QJsonObject avatarMixerGroupObject = domainSettings[AVATAR_MIXER_SETTINGS_KEY].toObject();
|
QJsonObject avatarMixerGroupObject = domainSettings[AVATAR_MIXER_SETTINGS_KEY].toObject();
|
||||||
|
|
||||||
|
|
|
@ -272,7 +272,7 @@ int EntityServer::sendSpecialPackets(const SharedNodePointer& node, OctreeQueryN
|
||||||
|
|
||||||
#ifdef EXTRA_ERASE_DEBUGGING
|
#ifdef EXTRA_ERASE_DEBUGGING
|
||||||
if (packetsSent > 0) {
|
if (packetsSent > 0) {
|
||||||
qDebug() << "EntityServer::sendSpecialPackets() sent " << packetsSent << "special packets of "
|
qDebug() << "EntityServer::sendSpecialPackets() sent " << packetsSent << "special packets of "
|
||||||
<< totalBytes << " total bytes to node:" << node->getUUID();
|
<< totalBytes << " total bytes to node:" << node->getUUID();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -326,14 +326,14 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio
|
||||||
} else {
|
} else {
|
||||||
tree->setEntityScriptSourceWhitelist("");
|
tree->setEntityScriptSourceWhitelist("");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto entityEditFilters = DependencyManager::get<EntityEditFilters>();
|
auto entityEditFilters = DependencyManager::get<EntityEditFilters>();
|
||||||
|
|
||||||
QString filterURL;
|
QString filterURL;
|
||||||
if (readOptionString("entityEditFilter", settingsSectionObject, filterURL) && !filterURL.isEmpty()) {
|
if (readOptionString("entityEditFilter", settingsSectionObject, filterURL) && !filterURL.isEmpty()) {
|
||||||
// connect the filterAdded signal, and block edits until you hear back
|
// connect the filterAdded signal, and block edits until you hear back
|
||||||
connect(entityEditFilters.data(), &EntityEditFilters::filterAdded, this, &EntityServer::entityFilterAdded);
|
connect(entityEditFilters.data(), &EntityEditFilters::filterAdded, this, &EntityServer::entityFilterAdded);
|
||||||
|
|
||||||
entityEditFilters->addFilter(EntityItemID(), filterURL);
|
entityEditFilters->addFilter(EntityItemID(), filterURL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -367,7 +367,7 @@ void EntityServer::nodeKilled(SharedNodePointer node) {
|
||||||
|
|
||||||
// FIXME - this stats tracking is somewhat temporary to debug the Whiteboard issues. It's not a bad
|
// FIXME - this stats tracking is somewhat temporary to debug the Whiteboard issues. It's not a bad
|
||||||
// set of stats to have, but we'd probably want a different data structure if we keep it very long.
|
// set of stats to have, but we'd probably want a different data structure if we keep it very long.
|
||||||
// Since this version uses a single shared QMap for all senders, there could be some lock contention
|
// Since this version uses a single shared QMap for all senders, there could be some lock contention
|
||||||
// on this QWriteLocker
|
// on this QWriteLocker
|
||||||
void EntityServer::trackSend(const QUuid& dataID, quint64 dataLastEdited, const QUuid& sessionID) {
|
void EntityServer::trackSend(const QUuid& dataID, quint64 dataLastEdited, const QUuid& sessionID) {
|
||||||
QWriteLocker locker(&_viewerSendingStatsLock);
|
QWriteLocker locker(&_viewerSendingStatsLock);
|
||||||
|
|
|
@ -19,13 +19,8 @@
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
setupHifiApplication(BuildInfo::ASSIGNMENT_CLIENT_NAME);
|
setupHifiApplication(BuildInfo::ASSIGNMENT_CLIENT_NAME);
|
||||||
|
|
||||||
auto &ch = CrashHandler::getInstance();
|
|
||||||
ch.start(argv[0]);
|
|
||||||
ch.setAnnotation("program", "assignment-client");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AssignmentClientApp app(argc, argv);
|
AssignmentClientApp app(argc, argv);
|
||||||
|
auto &ch = CrashHandler::getInstance();
|
||||||
ch.startMonitor(&app);
|
ch.startMonitor(&app);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,8 @@ void MessagesMixer::domainSettingsRequestComplete() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessagesMixer::parseDomainServerSettings(const QJsonObject& domainSettings) {
|
void MessagesMixer::parseDomainServerSettings(const QJsonObject& domainSettings) {
|
||||||
|
commonParseSettingsObject(domainSettings);
|
||||||
|
|
||||||
const QString MESSAGES_MIXER_SETTINGS_KEY = "messages_mixer";
|
const QString MESSAGES_MIXER_SETTINGS_KEY = "messages_mixer";
|
||||||
QJsonObject messagesMixerGroupObject = domainSettings[MESSAGES_MIXER_SETTINGS_KEY].toObject();
|
QJsonObject messagesMixerGroupObject = domainSettings[MESSAGES_MIXER_SETTINGS_KEY].toObject();
|
||||||
|
|
||||||
|
|
|
@ -1023,6 +1023,8 @@ void OctreeServer::readConfiguration() {
|
||||||
|
|
||||||
const QJsonObject& settingsObject = DependencyManager::get<NodeList>()->getDomainHandler().getSettingsObject();
|
const QJsonObject& settingsObject = DependencyManager::get<NodeList>()->getDomainHandler().getSettingsObject();
|
||||||
|
|
||||||
|
commonParseSettingsObject(settingsObject);
|
||||||
|
|
||||||
QString settingsKey = getMyDomainSettingsKey();
|
QString settingsKey = getMyDomainSettingsKey();
|
||||||
QJsonObject settingsSectionObject = settingsObject[settingsKey].toObject();
|
QJsonObject settingsSectionObject = settingsObject[settingsKey].toObject();
|
||||||
_settings = settingsSectionObject; // keep this for later
|
_settings = settingsSectionObject; // keep this for later
|
||||||
|
|
|
@ -149,11 +149,14 @@ void EntityScriptServer::handleEntityScriptGetStatusPacket(QSharedPointer<Receiv
|
||||||
|
|
||||||
void EntityScriptServer::handleSettings() {
|
void EntityScriptServer::handleSettings() {
|
||||||
|
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
|
||||||
auto& domainHandler = nodeList->getDomainHandler();
|
auto& domainHandler = nodeList->getDomainHandler();
|
||||||
const QJsonObject& settingsObject = domainHandler.getSettingsObject();
|
const QJsonObject& settingsObject = domainHandler.getSettingsObject();
|
||||||
|
|
||||||
|
commonParseSettingsObject(settingsObject);
|
||||||
|
|
||||||
static const QString ENTITY_SCRIPT_SERVER_SETTINGS_KEY = "entity_script_server";
|
static const QString ENTITY_SCRIPT_SERVER_SETTINGS_KEY = "entity_script_server";
|
||||||
|
|
||||||
if (!settingsObject.contains(ENTITY_SCRIPT_SERVER_SETTINGS_KEY)) {
|
if (!settingsObject.contains(ENTITY_SCRIPT_SERVER_SETTINGS_KEY)) {
|
||||||
|
@ -292,7 +295,7 @@ void EntityScriptServer::run() {
|
||||||
entityScriptingInterface->init();
|
entityScriptingInterface->init();
|
||||||
|
|
||||||
_entityViewer.init();
|
_entityViewer.init();
|
||||||
|
|
||||||
// setup the JSON filter that asks for entities with a non-default serverScripts property
|
// setup the JSON filter that asks for entities with a non-default serverScripts property
|
||||||
QJsonObject queryJSONParameters;
|
QJsonObject queryJSONParameters;
|
||||||
queryJSONParameters[EntityJSONQueryProperties::SERVER_SCRIPTS_PROPERTY] = EntityQueryFilterSymbol::NonDefault;
|
queryJSONParameters[EntityJSONQueryProperties::SERVER_SCRIPTS_PROPERTY] = EntityQueryFilterSymbol::NonDefault;
|
||||||
|
@ -303,7 +306,7 @@ void EntityScriptServer::run() {
|
||||||
queryFlags[EntityJSONQueryProperties::INCLUDE_DESCENDANTS_PROPERTY] = true;
|
queryFlags[EntityJSONQueryProperties::INCLUDE_DESCENDANTS_PROPERTY] = true;
|
||||||
|
|
||||||
queryJSONParameters[EntityJSONQueryProperties::FLAGS_PROPERTY] = queryFlags;
|
queryJSONParameters[EntityJSONQueryProperties::FLAGS_PROPERTY] = queryFlags;
|
||||||
|
|
||||||
// setup the JSON parameters so that OctreeQuery does not use a frustum and uses our JSON filter
|
// setup the JSON parameters so that OctreeQuery does not use a frustum and uses our JSON filter
|
||||||
_entityViewer.getOctreeQuery().setJSONParameters(queryJSONParameters);
|
_entityViewer.getOctreeQuery().setJSONParameters(queryJSONParameters);
|
||||||
|
|
||||||
|
@ -380,7 +383,7 @@ void EntityScriptServer::nodeKilled(SharedNodePointer killedNode) {
|
||||||
if (!hasAnotherEntityServer) {
|
if (!hasAnotherEntityServer) {
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeType::Agent: {
|
case NodeType::Agent: {
|
||||||
|
@ -584,7 +587,7 @@ void EntityScriptServer::sendStatsPacket() {
|
||||||
}
|
}
|
||||||
scriptEngineStats["number_running_scripts"] = numberRunningScripts;
|
scriptEngineStats["number_running_scripts"] = numberRunningScripts;
|
||||||
statsObject["script_engine_stats"] = scriptEngineStats;
|
statsObject["script_engine_stats"] = scriptEngineStats;
|
||||||
|
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
QJsonObject nodesObject;
|
QJsonObject nodesObject;
|
||||||
|
|
|
@ -76,7 +76,8 @@
|
||||||
{
|
{
|
||||||
"label": "Networking / Crash Reporting",
|
"label": "Networking / Crash Reporting",
|
||||||
"name": "crash_reporting",
|
"name": "crash_reporting",
|
||||||
"restart": false,
|
"restart": true,
|
||||||
|
"assignment-types": [ 0, 1, 3, 4, 5, 6 ],
|
||||||
"settings": [
|
"settings": [
|
||||||
{
|
{
|
||||||
"name": "enable_crash_reporter",
|
"name": "enable_crash_reporter",
|
||||||
|
@ -85,6 +86,22 @@
|
||||||
"default": false,
|
"default": false,
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
"advanced": true
|
"advanced": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "custom_crash_url",
|
||||||
|
"label": "Custom crash URL",
|
||||||
|
"help": "If this is set, it overrides the internal crash reporting URL. This can be used for instance to direct crash reports to Sentry.",
|
||||||
|
"default": "",
|
||||||
|
"type": "string",
|
||||||
|
"advanced": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "custom_crash_token",
|
||||||
|
"label": "Custom crash token",
|
||||||
|
"help": "This is a token that identifies the thing sending a crash report, such as a product name and version number. If not set, the compile time default will be used.",
|
||||||
|
"default": "",
|
||||||
|
"type": "string",
|
||||||
|
"advanced": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -63,7 +63,9 @@ const QString SETTINGS_VIEWPOINT_KEY = "viewpoint";
|
||||||
|
|
||||||
DomainServerSettingsManager::DomainServerSettingsManager() {
|
DomainServerSettingsManager::DomainServerSettingsManager() {
|
||||||
// load the description object from the settings description
|
// load the description object from the settings description
|
||||||
QFile descriptionFile(QCoreApplication::applicationDirPath() + SETTINGS_DESCRIPTION_RELATIVE_PATH);
|
qDebug() << "Application dir: " << QCoreApplication::applicationDirPath();
|
||||||
|
QString descriptionFilePath = QCoreApplication::applicationDirPath() + SETTINGS_DESCRIPTION_RELATIVE_PATH;
|
||||||
|
QFile descriptionFile(descriptionFilePath);
|
||||||
descriptionFile.open(QIODevice::ReadOnly);
|
descriptionFile.open(QIODevice::ReadOnly);
|
||||||
|
|
||||||
QJsonParseError parseError;
|
QJsonParseError parseError;
|
||||||
|
@ -89,7 +91,7 @@ DomainServerSettingsManager::DomainServerSettingsManager() {
|
||||||
|
|
||||||
static const QString MISSING_SETTINGS_DESC_MSG =
|
static const QString MISSING_SETTINGS_DESC_MSG =
|
||||||
QString("Did not find settings description in JSON at %1 - Unable to continue. domain-server will quit.\n%2 at %3")
|
QString("Did not find settings description in JSON at %1 - Unable to continue. domain-server will quit.\n%2 at %3")
|
||||||
.arg(SETTINGS_DESCRIPTION_RELATIVE_PATH).arg(parseError.errorString()).arg(parseError.offset);
|
.arg(descriptionFilePath).arg(parseError.errorString()).arg(parseError.offset);
|
||||||
static const int MISSING_SETTINGS_DESC_ERROR_CODE = 6;
|
static const int MISSING_SETTINGS_DESC_ERROR_CODE = 6;
|
||||||
|
|
||||||
QMetaObject::invokeMethod(QCoreApplication::instance(), "queuedQuit", Qt::QueuedConnection,
|
QMetaObject::invokeMethod(QCoreApplication::instance(), "queuedQuit", Qt::QueuedConnection,
|
||||||
|
|
|
@ -50,12 +50,42 @@ enum SettingsType {
|
||||||
ContentSettings
|
ContentSettings
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Manages the domain-wide settings
|
||||||
|
*
|
||||||
|
* The domain server doesn't use the interface's QSettings based system, but this one.
|
||||||
|
* The domain holds all the settings and distributes it to the connected assignment clients.
|
||||||
|
*
|
||||||
|
* Assignment clients request their settings by making a DomainSettingsRequest. The request
|
||||||
|
* is specific to the client's type.
|
||||||
|
*
|
||||||
|
* The response is generated in settingsResponseObjectForType and filtered according to what
|
||||||
|
* the client is allowed to see.
|
||||||
|
*
|
||||||
|
* To add a new setting, add it in resources/describe-settings.json
|
||||||
|
*
|
||||||
|
* To make a setting be sent to assignment clients, set the assignment-types value to an array
|
||||||
|
* of the desired assignment clients. The type is defined numerically.
|
||||||
|
*
|
||||||
|
* The canonical list of assignment types is in the Assignment::Type enum.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
class DomainServerSettingsManager : public QObject {
|
class DomainServerSettingsManager : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
DomainServerSettingsManager();
|
DomainServerSettingsManager();
|
||||||
bool handleAuthenticatedHTTPRequest(HTTPConnection* connection, const QUrl& url);
|
bool handleAuthenticatedHTTPRequest(HTTPConnection* connection, const QUrl& url);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Loads the configuration from the specified file
|
||||||
|
*
|
||||||
|
* Performs version upgrades when we're loading an older version of the config.
|
||||||
|
*
|
||||||
|
* @param userConfigFilename
|
||||||
|
*/
|
||||||
void setupConfigMap(const QString& userConfigFilename);
|
void setupConfigMap(const QString& userConfigFilename);
|
||||||
|
|
||||||
// each of the three methods in this group takes a read lock of _settingsLock
|
// each of the three methods in this group takes a read lock of _settingsLock
|
||||||
|
@ -126,7 +156,21 @@ public:
|
||||||
enum DefaultSettingsInclusion { NoDefaultSettings, IncludeDefaultSettings };
|
enum DefaultSettingsInclusion { NoDefaultSettings, IncludeDefaultSettings };
|
||||||
enum SettingsBackupFlag { NotForBackup, ForBackup };
|
enum SettingsBackupFlag { NotForBackup, ForBackup };
|
||||||
|
|
||||||
/// thread safe method to retrieve a JSON representation of settings
|
/**
|
||||||
|
* @brief Generates a JSON representation of settings
|
||||||
|
*
|
||||||
|
* This is what answers an assignment client's request for domain settings.
|
||||||
|
*
|
||||||
|
* @note thread safe
|
||||||
|
*
|
||||||
|
* @param typeValue Type of assignment client
|
||||||
|
* @param authentication
|
||||||
|
* @param domainSettingsInclusion
|
||||||
|
* @param contentSettingsInclusion
|
||||||
|
* @param defaultSettingsInclusion
|
||||||
|
* @param settingsBackupFlag
|
||||||
|
* @return QJsonObject
|
||||||
|
*/
|
||||||
QJsonObject settingsResponseObjectForType(const QString& typeValue,
|
QJsonObject settingsResponseObjectForType(const QString& typeValue,
|
||||||
SettingsRequestAuthentication authentication = NotAuthenticated,
|
SettingsRequestAuthentication authentication = NotAuthenticated,
|
||||||
DomainSettingsInclusion domainSettingsInclusion = IncludeDomainSettings,
|
DomainSettingsInclusion domainSettingsInclusion = IncludeDomainSettings,
|
||||||
|
@ -211,7 +255,7 @@ private:
|
||||||
// keep track of answers to api queries about which users are in which groups
|
// keep track of answers to api queries about which users are in which groups
|
||||||
QHash<QString, QHash<QUuid, QUuid>> _groupMembership; // QHash<user-name, QHash<group-id, rank-id>>
|
QHash<QString, QHash<QUuid, QUuid>> _groupMembership; // QHash<user-name, QHash<group-id, rank-id>>
|
||||||
|
|
||||||
/// guard read/write access from multiple threads to settings
|
/// guard read/write access from multiple threads to settings
|
||||||
QReadWriteLock _settingsLock { QReadWriteLock::Recursive };
|
QReadWriteLock _settingsLock { QReadWriteLock::Recursive };
|
||||||
|
|
||||||
friend class DomainServer;
|
friend class DomainServer;
|
||||||
|
|
|
@ -35,7 +35,7 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
// use a do-while to handle domain-server restart
|
// use a do-while to handle domain-server restart
|
||||||
auto &ch = CrashHandler::getInstance();
|
auto &ch = CrashHandler::getInstance();
|
||||||
ch.start(argv[0]);
|
ch.setPath(argv[0]);
|
||||||
|
|
||||||
if ( DomainServer::forceCrashReporting() ) {
|
if ( DomainServer::forceCrashReporting() ) {
|
||||||
ch.setEnabled(true);
|
ch.setEnabled(true);
|
||||||
|
|
|
@ -323,6 +323,13 @@ int main(int argc, const char* argv[]) {
|
||||||
auto& ual = UserActivityLogger::getInstance();
|
auto& ual = UserActivityLogger::getInstance();
|
||||||
auto& ch = CrashHandler::getInstance();
|
auto& ch = CrashHandler::getInstance();
|
||||||
|
|
||||||
|
QObject::connect(&ch, &CrashHandler::enabledChanged, [](bool enabled) {
|
||||||
|
Settings s;
|
||||||
|
s.beginGroup("Crash");
|
||||||
|
s.setValue("ReportingEnabled", enabled);
|
||||||
|
s.endGroup();
|
||||||
|
});
|
||||||
|
|
||||||
// once the settings have been loaded, check if we need to flip the default for UserActivityLogger
|
// once the settings have been loaded, check if we need to flip the default for UserActivityLogger
|
||||||
if (!ual.isDisabledSettingSet()) {
|
if (!ual.isDisabledSettingSet()) {
|
||||||
// the user activity logger is opt-out for Interface
|
// the user activity logger is opt-out for Interface
|
||||||
|
@ -337,13 +344,6 @@ int main(int argc, const char* argv[]) {
|
||||||
ch.setEnabled(true);
|
ch.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto crashHandlerStarted = ch.start(argv[0]);
|
|
||||||
if (crashHandlerStarted) {
|
|
||||||
qDebug() << "Crash handler started";
|
|
||||||
} else {
|
|
||||||
qWarning() << "Crash handler failed to start";
|
|
||||||
}
|
|
||||||
|
|
||||||
ch.setAnnotation("program", "interface");
|
ch.setAnnotation("program", "interface");
|
||||||
|
|
||||||
const QString& applicationName = getInterfaceSharedMemoryName();
|
const QString& applicationName = getInterfaceSharedMemoryName();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
set(TARGET_NAME monitoring)
|
set(TARGET_NAME monitoring)
|
||||||
setup_hifi_library()
|
setup_hifi_library()
|
||||||
link_hifi_libraries(shared networking)
|
link_hifi_libraries(shared)
|
||||||
|
|
||||||
add_crashpad()
|
add_crashpad()
|
||||||
target_breakpad()
|
target_breakpad()
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include "CrashHandler.h"
|
#include "CrashHandler.h"
|
||||||
#include "CrashHandlerBackend.h"
|
#include "CrashHandlerBackend.h"
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
|
||||||
CrashHandler& CrashHandler::getInstance() {
|
CrashHandler& CrashHandler::getInstance() {
|
||||||
|
@ -18,13 +20,32 @@ CrashHandler& CrashHandler::getInstance() {
|
||||||
return sharedInstance;
|
return sharedInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CrashHandler::start(const QString &path) {
|
CrashHandler::CrashHandler(QObject *parent) : QObject(parent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CrashHandler::setPath(const QString &path) {
|
||||||
|
QFileInfo fi(path);
|
||||||
|
|
||||||
if (isStarted()) {
|
if (isStarted()) {
|
||||||
qCWarning(crash_handler) << "Crash handler already started";
|
qCWarning(crash_handler) << "Crash handler already started, too late to set the path.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fi.isFile()) {
|
||||||
|
_path = fi.absolutePath();
|
||||||
|
} else {
|
||||||
|
_path = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CrashHandler::start() {
|
||||||
|
if (isStarted()) {
|
||||||
|
//qCWarning(crash_handler) << "Crash handler already started";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto started = startCrashHandler(path.toStdString());
|
auto started = startCrashHandler(_path.toStdString(), _crashUrl.toStdString(), _crashToken.toStdString());
|
||||||
setStarted(started);
|
setStarted(started);
|
||||||
|
|
||||||
if ( started ) {
|
if ( started ) {
|
||||||
|
@ -41,21 +62,50 @@ void CrashHandler::startMonitor(QCoreApplication *app) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrashHandler::setEnabled(bool enabled) {
|
void CrashHandler::setEnabled(bool enabled) {
|
||||||
if (enabled != _crashReportingEnabled.get()) {
|
start();
|
||||||
_crashReportingEnabled.set(enabled);
|
|
||||||
|
|
||||||
|
if (enabled != _crashReportingEnabled) {
|
||||||
|
_crashReportingEnabled = enabled;
|
||||||
setCrashReportingEnabled(enabled);
|
setCrashReportingEnabled(enabled);
|
||||||
|
|
||||||
|
emit enabledChanged(enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CrashHandler::setUrl(const QString &url) {
|
||||||
|
// This can be called both from the settings system in an assignment client
|
||||||
|
// and from the commandline parser. We only emit a warning if the commandline
|
||||||
|
// argument causes the domain setting to be ignored.
|
||||||
|
|
||||||
|
if (isStarted() && url != _crashUrl) {
|
||||||
|
qCWarning(crash_handler) << "Setting crash reporting URL to " << url << "after the crash handler is already running has no effect";
|
||||||
|
} else {
|
||||||
|
_crashUrl = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CrashHandler::setToken(const QString &token) {
|
||||||
|
if (isStarted() && token != _crashToken) {
|
||||||
|
qCWarning(crash_handler) << "Setting crash reporting token to " << token << "after the crash handler is already running has no effect";
|
||||||
|
} else {
|
||||||
|
_crashToken = token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrashHandler::setAnnotation(const std::string &key, const char *value) {
|
void CrashHandler::setAnnotation(const std::string &key, const char *value) {
|
||||||
|
setAnnotation(key, std::string(value));
|
||||||
setCrashAnnotation(key, std::string(value));
|
setCrashAnnotation(key, std::string(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrashHandler::setAnnotation(const std::string &key, const QString &value) {
|
void CrashHandler::setAnnotation(const std::string &key, const QString &value) {
|
||||||
setCrashAnnotation(key, value.toStdString());
|
setAnnotation(key, value.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrashHandler::setAnnotation(const std::string &key, const std::string &value) {
|
void CrashHandler::setAnnotation(const std::string &key, const std::string &value) {
|
||||||
|
if (!isStarted()) {
|
||||||
|
qCWarning(crash_handler) << "Can't set annotation" << QString::fromStdString(key) << "to" << QString::fromStdString(value) << "crash handler not yet started";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setCrashAnnotation(key, value);
|
setCrashAnnotation(key, value);
|
||||||
}
|
}
|
|
@ -21,7 +21,31 @@
|
||||||
/**
|
/**
|
||||||
* @brief The global object in charge of setting up and controlling crash reporting.
|
* @brief The global object in charge of setting up and controlling crash reporting.
|
||||||
*
|
*
|
||||||
* This object initializes and talks to crash reporting backends.
|
* This object initializes and talks to crash reporting backends. For those, see
|
||||||
|
* CrashHandlerBackend.h and the .cpp files that implement that interface.
|
||||||
|
*
|
||||||
|
* The crash URL and token can only be passed to the underlying system on start, so
|
||||||
|
* things should be set up in such a way that startup is only done after those are set.
|
||||||
|
*
|
||||||
|
* start() will be automatically called when setEnabled() is called with true.
|
||||||
|
* setAnnotation() can only be called after start.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* To use, follow this general pattern in an application:
|
||||||
|
*
|
||||||
|
* @code {.cpp}
|
||||||
|
* auto &ch = CrashHandler::getInstance();
|
||||||
|
* ch.setPath(...);
|
||||||
|
* ch.setUrl("https://server.com/crash-reports");
|
||||||
|
* ch.setToken("1.2beta");
|
||||||
|
* ch.setEnabled(true);
|
||||||
|
* ch.setAnnotation("version", "1.3"); // Needs a started handler to work
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* For an assignment client, there are two potential ways to start, through the command-line
|
||||||
|
* and through the settings system. Since the path, URL and token only apply on startup, the
|
||||||
|
* code must be written such that if command arguments are not given, setEnabled() or start()
|
||||||
|
* are not called until receiving the settings from the domain.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class CrashHandler : public QObject {
|
class CrashHandler : public QObject {
|
||||||
|
@ -30,18 +54,42 @@ class CrashHandler : public QObject {
|
||||||
public:
|
public:
|
||||||
static CrashHandler& getInstance();
|
static CrashHandler& getInstance();
|
||||||
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the directory for the crash reports
|
||||||
|
*
|
||||||
|
* This sets the path for writing crash reports. This should be done on application startup.
|
||||||
|
*
|
||||||
|
* @param path Directory where to store crash reports. It's allowed to set this to argv[0],
|
||||||
|
* if the path is a filename, then the base directory will be automatically used.
|
||||||
|
*/
|
||||||
|
void setPath(const QString &path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Start the crash handler
|
* @brief Start the crash handler
|
||||||
*
|
*
|
||||||
* @param path Database path
|
* This is called automatically if it wasn't started yet when setEnabled() is called.
|
||||||
|
*
|
||||||
|
* @param path Path where to store the crash database
|
||||||
* @return true Started successfully
|
* @return true Started successfully
|
||||||
* @return false Failed to start
|
* @return false Failed to start
|
||||||
*/
|
*/
|
||||||
bool start(const QString &path);
|
bool start();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Starts the unhandled exception monitor.
|
||||||
|
*
|
||||||
|
* On Windows, it's possible for the unhandled exception handler to be reset. This starts a timer
|
||||||
|
* to periodically set it back.
|
||||||
|
*
|
||||||
|
* On non-Windows systems this has no effect.
|
||||||
|
*
|
||||||
|
* @param app Main application
|
||||||
|
*/
|
||||||
void startMonitor(QCoreApplication *app);
|
void startMonitor(QCoreApplication *app);
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,7 +118,7 @@ public slots:
|
||||||
* @return true Crashes will be reported to CMAKE_BACKTRACE_URL
|
* @return true Crashes will be reported to CMAKE_BACKTRACE_URL
|
||||||
* @return false Crashes will not be reported
|
* @return false Crashes will not be reported
|
||||||
*/
|
*/
|
||||||
bool isEnabled() const { return _crashReportingEnabled.get(); }
|
bool isEnabled() const { return _crashReportingEnabled; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set whether we want to submit crash reports to the report server
|
* @brief Set whether we want to submit crash reports to the report server
|
||||||
|
@ -78,17 +126,84 @@ public slots:
|
||||||
* The report server is configured with CMAKE_BACKTRACE_URL.
|
* The report server is configured with CMAKE_BACKTRACE_URL.
|
||||||
* Emits crashReportingEnabledChanged signal.
|
* Emits crashReportingEnabledChanged signal.
|
||||||
*
|
*
|
||||||
|
* @note This automatically calls start(), so it should be called after setPath(), setUrl() and setToken()
|
||||||
* @param enabled Whether it's enabled.
|
* @param enabled Whether it's enabled.
|
||||||
*/
|
*/
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the URL where to send crash reports to
|
||||||
|
*
|
||||||
|
* If not set, a predefined URL specified at compile time via CMAKE_BACKTRACE_URL
|
||||||
|
* will be used.
|
||||||
|
*
|
||||||
|
* @param url URL
|
||||||
|
*/
|
||||||
|
void setUrl(const QString &url);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the token for the crash reporter
|
||||||
|
*
|
||||||
|
* This is an identifier in the crash collection service, such as Sentry, and may contain
|
||||||
|
* a branch name or a version number.
|
||||||
|
*
|
||||||
|
* If not set, a predefined token specified at compile time via CMAKE_BACKTRACE_TOKEN
|
||||||
|
* will be used.
|
||||||
|
*
|
||||||
|
* @param token Token
|
||||||
|
*/
|
||||||
|
void setToken(const QString &token);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set an annotation to be added to a crash
|
||||||
|
*
|
||||||
|
* Annotations add extra information, such as the application's version number,
|
||||||
|
* the current user, or any other information of interest.
|
||||||
|
*
|
||||||
|
* @param key Key
|
||||||
|
* @param value Value
|
||||||
|
*/
|
||||||
void setAnnotation(const std::string &key, const char *value);
|
void setAnnotation(const std::string &key, const char *value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set an annotation to be added to a crash
|
||||||
|
*
|
||||||
|
* Annotations add extra information, such as the application's version number,
|
||||||
|
* the current user, or any other information of interest.
|
||||||
|
*
|
||||||
|
* @param key Key
|
||||||
|
* @param value Value
|
||||||
|
*/
|
||||||
void setAnnotation(const std::string &key, const QString &value);
|
void setAnnotation(const std::string &key, const QString &value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set an annotation to be added to a crash
|
||||||
|
*
|
||||||
|
* Annotations add extra information, such as the application's version number,
|
||||||
|
* the current user, or any other information of interest.
|
||||||
|
*
|
||||||
|
* @param key Key
|
||||||
|
* @param value Value
|
||||||
|
*/
|
||||||
void setAnnotation(const std::string &key, const std::string &value);
|
void setAnnotation(const std::string &key, const std::string &value);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Emitted when the enabled/disabled state of the crash handler changes
|
||||||
|
*
|
||||||
|
* This can be used to store it as a setting.
|
||||||
|
*
|
||||||
|
* @param enabled Whether the crash handler is now enabled
|
||||||
|
*/
|
||||||
|
void enabledChanged(bool enabled);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CrashHandler(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Marks the crash monitor as started
|
* @brief Marks the crash monitor as started
|
||||||
*
|
*
|
||||||
|
@ -99,9 +214,12 @@ private:
|
||||||
void setStarted(bool started) { _crashMonitorStarted = started; }
|
void setStarted(bool started) { _crashMonitorStarted = started; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Setting::Handle<bool> _crashReportingEnabled { "CrashReportingEnabled", false };
|
|
||||||
bool _crashMonitorStarted {false};
|
bool _crashMonitorStarted {false};
|
||||||
|
bool _crashReportingEnabled {false};
|
||||||
|
|
||||||
|
QString _path;
|
||||||
|
QString _crashUrl;
|
||||||
|
QString _crashToken;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(crash_handler)
|
Q_DECLARE_LOGGING_CATEGORY(crash_handler)
|
||||||
|
|
||||||
bool startCrashHandler(std::string appPath);
|
bool startCrashHandler(std::string appPath, std::string url="", std::string token="");
|
||||||
void setCrashAnnotation(std::string name, std::string value);
|
void setCrashAnnotation(std::string name, std::string value);
|
||||||
void startCrashHookMonitor(QCoreApplication* app);
|
void startCrashHookMonitor(QCoreApplication* app);
|
||||||
void setCrashReportingEnabled(bool value);
|
void setCrashReportingEnabled(bool value);
|
||||||
|
|
|
@ -57,7 +57,7 @@ void flushAnnotations() {
|
||||||
settings.sync();
|
settings.sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool startCrashHandler(std::string appPath) {
|
bool startCrashHandler(std::string appPath, std::string crashURL, std::string crashToken) {
|
||||||
annotations["version"] = BuildInfo::VERSION;
|
annotations["version"] = BuildInfo::VERSION;
|
||||||
annotations["build_number"] = BuildInfo::BUILD_NUMBER;
|
annotations["build_number"] = BuildInfo::BUILD_NUMBER;
|
||||||
annotations["build_type"] = BuildInfo::BUILD_TYPE_STRING;
|
annotations["build_type"] = BuildInfo::BUILD_TYPE_STRING;
|
||||||
|
|
|
@ -49,6 +49,10 @@ Q_LOGGING_CATEGORY(crash_handler, "overte.crash_handler")
|
||||||
static const std::string BACKTRACE_URL{ CMAKE_BACKTRACE_URL };
|
static const std::string BACKTRACE_URL{ CMAKE_BACKTRACE_URL };
|
||||||
static const std::string BACKTRACE_TOKEN{ CMAKE_BACKTRACE_TOKEN };
|
static const std::string BACKTRACE_TOKEN{ CMAKE_BACKTRACE_TOKEN };
|
||||||
|
|
||||||
|
std::string custom_backtrace_url;
|
||||||
|
std::string custom_backtrace_token;
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// SpinLock - a lock that can timeout attempting to lock a block of code, and is in a busy-wait cycle while trying to acquire
|
// SpinLock - a lock that can timeout attempting to lock a block of code, and is in a busy-wait cycle while trying to acquire
|
||||||
// note that this code will malfunction if you attempt to grab a lock while already holding it
|
// note that this code will malfunction if you attempt to grab a lock while already holding it
|
||||||
|
@ -351,8 +355,16 @@ static QString findBinaryDir() {
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool startCrashHandler(std::string appPath) {
|
bool startCrashHandler(std::string appPath, std::string crashURL, std::string crashToken) {
|
||||||
if (BACKTRACE_URL.empty() || BACKTRACE_TOKEN.empty()) {
|
if (crashURL.empty()) {
|
||||||
|
crashURL = BACKTRACE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crashToken.empty()) {
|
||||||
|
crashToken = BACKTRACE_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crashURL.empty() || crashToken.empty()) {
|
||||||
qCCritical(crash_handler) << "Backtrace URL or token not set, crash handler disabled.";
|
qCCritical(crash_handler) << "Backtrace URL or token not set, crash handler disabled.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -362,7 +374,7 @@ bool startCrashHandler(std::string appPath) {
|
||||||
std::vector<std::string> arguments;
|
std::vector<std::string> arguments;
|
||||||
|
|
||||||
std::map<std::string, std::string> annotations;
|
std::map<std::string, std::string> annotations;
|
||||||
annotations["sentry[release]"] = BACKTRACE_TOKEN;
|
annotations["sentry[release]"] = crashToken;
|
||||||
annotations["sentry[contexts][app][app_version]"] = BuildInfo::VERSION.toStdString();
|
annotations["sentry[contexts][app][app_version]"] = BuildInfo::VERSION.toStdString();
|
||||||
annotations["sentry[contexts][app][app_build]"] = BuildInfo::BUILD_NUMBER.toStdString();
|
annotations["sentry[contexts][app][app_build]"] = BuildInfo::BUILD_NUMBER.toStdString();
|
||||||
annotations["build_type"] = BuildInfo::BUILD_TYPE_STRING.toStdString();
|
annotations["build_type"] = BuildInfo::BUILD_TYPE_STRING.toStdString();
|
||||||
|
@ -389,10 +401,10 @@ bool startCrashHandler(std::string appPath) {
|
||||||
qCDebug(crash_handler) << "Locating own directory by platform-specific method";
|
qCDebug(crash_handler) << "Locating own directory by platform-specific method";
|
||||||
interfaceDir.setPath(binaryDir);
|
interfaceDir.setPath(binaryDir);
|
||||||
} else {
|
} else {
|
||||||
|
// Getting the base dir from argv[0] is already handled by CrashHandler, so we use
|
||||||
|
// the path as-is here.
|
||||||
qCDebug(crash_handler) << "Locating own directory by argv[0]";
|
qCDebug(crash_handler) << "Locating own directory by argv[0]";
|
||||||
interfaceDir.setPath(QString::fromStdString(appPath));
|
interfaceDir.setPath(QString::fromStdString(appPath));
|
||||||
// argv[0] gets us the path including the binary file
|
|
||||||
interfaceDir.cdUp();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!interfaceDir.exists(CRASHPAD_HANDLER_NAME)) {
|
if (!interfaceDir.exists(CRASHPAD_HANDLER_NAME)) {
|
||||||
|
@ -429,7 +441,7 @@ bool startCrashHandler(std::string appPath) {
|
||||||
crashpadDatabase->GetSettings()->SetUploadsEnabled(CrashHandler::getInstance().isEnabled());
|
crashpadDatabase->GetSettings()->SetUploadsEnabled(CrashHandler::getInstance().isEnabled());
|
||||||
|
|
||||||
|
|
||||||
if (!client->StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true)) {
|
if (!client->StartHandler(handler, db, db, crashURL, annotations, arguments, true, true)) {
|
||||||
qCCritical(crash_handler) << "Failed to start crashpad handler";
|
qCCritical(crash_handler) << "Failed to start crashpad handler";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(crash_handler, "overte.crash_handler")
|
Q_LOGGING_CATEGORY(crash_handler, "overte.crash_handler")
|
||||||
|
|
||||||
bool startCrashHandler(std::string appPath) {
|
bool startCrashHandler(std::string appPath, std::string crashURL, std::string crashToken) {
|
||||||
qCWarning(crash_handler) << "No crash handler available.";
|
qCWarning(crash_handler) << "No crash handler available.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
set(TARGET_NAME networking)
|
set(TARGET_NAME networking)
|
||||||
setup_hifi_library(Network WebSockets)
|
setup_hifi_library(Network WebSockets)
|
||||||
link_hifi_libraries(shared platform)
|
link_hifi_libraries(shared platform monitoring)
|
||||||
|
|
||||||
target_openssl()
|
target_openssl()
|
||||||
target_tbb()
|
target_tbb()
|
||||||
|
|
|
@ -16,11 +16,17 @@
|
||||||
#include <BuildInfo.h>
|
#include <BuildInfo.h>
|
||||||
#include <QtCore/QStandardPaths>
|
#include <QtCore/QStandardPaths>
|
||||||
#include <QtCore/QDir>
|
#include <QtCore/QDir>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <crash-handler/CrashHandler.h>
|
||||||
|
|
||||||
|
|
||||||
#include "udt/PacketHeaders.h"
|
#include "udt/PacketHeaders.h"
|
||||||
#include "SharedUtil.h"
|
#include "SharedUtil.h"
|
||||||
#include "UUID.h"
|
#include "UUID.h"
|
||||||
|
|
||||||
|
static const QString CRASH_REPORTING_GROUP_KEY = "crash_reporting";
|
||||||
|
|
||||||
|
|
||||||
Assignment::Type Assignment::typeForNodeType(NodeType_t nodeType) {
|
Assignment::Type Assignment::typeForNodeType(NodeType_t nodeType) {
|
||||||
switch (nodeType) {
|
switch (nodeType) {
|
||||||
case NodeType::AudioMixer:
|
case NodeType::AudioMixer:
|
||||||
|
@ -51,7 +57,7 @@ Assignment::Assignment() :
|
||||||
_payload(),
|
_payload(),
|
||||||
_isStatic(false)
|
_isStatic(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Assignment::Assignment(Assignment::Command command, Assignment::Type type, const QString& pool, Assignment::Location location, QString dataDirectory) :
|
Assignment::Assignment(Assignment::Command command, Assignment::Type type, const QString& pool, Assignment::Location location, QString dataDirectory) :
|
||||||
|
@ -84,9 +90,9 @@ Assignment::Assignment(ReceivedMessage& message) :
|
||||||
} else if (message.getType() == PacketType::CreateAssignment) {
|
} else if (message.getType() == PacketType::CreateAssignment) {
|
||||||
_command = Assignment::CreateCommand;
|
_command = Assignment::CreateCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream packetStream(message.getMessage());
|
QDataStream packetStream(message.getMessage());
|
||||||
|
|
||||||
packetStream >> *this;
|
packetStream >> *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +119,7 @@ Assignment& Assignment::operator=(const Assignment& rhsAssignment) {
|
||||||
|
|
||||||
void Assignment::swap(Assignment& otherAssignment) {
|
void Assignment::swap(Assignment& otherAssignment) {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
|
|
||||||
swap(_uuid, otherAssignment._uuid);
|
swap(_uuid, otherAssignment._uuid);
|
||||||
swap(_command, otherAssignment._command);
|
swap(_command, otherAssignment._command);
|
||||||
swap(_type, otherAssignment._type);
|
swap(_type, otherAssignment._type);
|
||||||
|
@ -148,10 +154,36 @@ const char* Assignment::typeToString(Assignment::Type type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Assignment::commonParseSettingsObject(const QJsonObject &settingsObject) {
|
||||||
|
|
||||||
|
if (settingsObject.contains(CRASH_REPORTING_GROUP_KEY)) {
|
||||||
|
|
||||||
|
auto &ch = CrashHandler::getInstance();
|
||||||
|
QJsonObject crashGroupObject = settingsObject[CRASH_REPORTING_GROUP_KEY].toObject();
|
||||||
|
|
||||||
|
const QString CRASH_REPORTING_ENABLED = "enable_crash_reporter";
|
||||||
|
const QString CRASH_REPORTING_CUSTOM_URL = "custom_crash_url";
|
||||||
|
const QString CRASH_REPORTING_CUSTOM_TOKEN = "custom_crash_token";
|
||||||
|
|
||||||
|
bool enabled = crashGroupObject[CRASH_REPORTING_ENABLED].toBool();
|
||||||
|
QString url = crashGroupObject[CRASH_REPORTING_CUSTOM_URL].toString();
|
||||||
|
QString token = crashGroupObject[CRASH_REPORTING_CUSTOM_TOKEN].toString();
|
||||||
|
|
||||||
|
ch.setUrl(url);
|
||||||
|
ch.setToken(token);
|
||||||
|
ch.setEnabled(enabled);
|
||||||
|
|
||||||
|
ch.setAnnotation("program", "assignment-client");
|
||||||
|
ch.setAnnotation("assignment-client", "audio-mixer");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, const Assignment &assignment) {
|
QDebug operator<<(QDebug debug, const Assignment &assignment) {
|
||||||
debug.nospace() << "UUID: " << qPrintable(assignment.getUUID().toString()) <<
|
debug.nospace() << "UUID: " << qPrintable(assignment.getUUID().toString()) <<
|
||||||
", Type: " << assignment.getTypeName() << " (" << assignment.getType() << ")";
|
", Type: " << assignment.getTypeName() << " (" << assignment.getType() << ")";
|
||||||
|
|
||||||
if (!assignment.getPool().isEmpty()) {
|
if (!assignment.getPool().isEmpty()) {
|
||||||
debug << ", Pool: " << assignment.getPool();
|
debug << ", Pool: " << assignment.getPool();
|
||||||
}
|
}
|
||||||
|
@ -161,11 +193,11 @@ QDebug operator<<(QDebug debug, const Assignment &assignment) {
|
||||||
|
|
||||||
QDataStream& operator<<(QDataStream &out, const Assignment& assignment) {
|
QDataStream& operator<<(QDataStream &out, const Assignment& assignment) {
|
||||||
out << (quint8) assignment._type << assignment._uuid << assignment._pool << assignment._payload;
|
out << (quint8) assignment._type << assignment._uuid << assignment._pool << assignment._payload;
|
||||||
|
|
||||||
if (assignment._command == Assignment::RequestCommand) {
|
if (assignment._command == Assignment::RequestCommand) {
|
||||||
out << assignment._nodeVersion;
|
out << assignment._nodeVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,11 +205,11 @@ QDataStream& operator>>(QDataStream &in, Assignment& assignment) {
|
||||||
quint8 packedType;
|
quint8 packedType;
|
||||||
in >> packedType >> assignment._uuid >> assignment._pool >> assignment._payload;
|
in >> packedType >> assignment._uuid >> assignment._pool >> assignment._payload;
|
||||||
assignment._type = (Assignment::Type) packedType;
|
assignment._type = (Assignment::Type) packedType;
|
||||||
|
|
||||||
if (assignment._command == Assignment::RequestCommand) {
|
if (assignment._command == Assignment::RequestCommand) {
|
||||||
in >> assignment._nodeVersion;
|
in >> assignment._nodeVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,3 +219,4 @@ uint qHash(const Assignment::Type& key, uint seed) {
|
||||||
// strongly typed enum for PacketType
|
// strongly typed enum for PacketType
|
||||||
return qHash((uint8_t) key, seed);
|
return qHash((uint8_t) key, seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,12 @@
|
||||||
|
|
||||||
#include <QtCore/QUuid>
|
#include <QtCore/QUuid>
|
||||||
|
|
||||||
|
|
||||||
#include "ReceivedMessage.h"
|
#include "ReceivedMessage.h"
|
||||||
|
|
||||||
#include "NodeList.h"
|
#include "NodeList.h"
|
||||||
|
|
||||||
|
|
||||||
const int MAX_PAYLOAD_BYTES = 1024;
|
const int MAX_PAYLOAD_BYTES = 1024;
|
||||||
|
|
||||||
const QString emptyPool = QString();
|
const QString emptyPool = QString();
|
||||||
|
@ -80,12 +82,12 @@ public:
|
||||||
|
|
||||||
void setPool(const QString& pool) { _pool = pool; };
|
void setPool(const QString& pool) { _pool = pool; };
|
||||||
const QString& getPool() const { return _pool; }
|
const QString& getPool() const { return _pool; }
|
||||||
|
|
||||||
void setIsStatic(bool isStatic) { _isStatic = isStatic; }
|
void setIsStatic(bool isStatic) { _isStatic = isStatic; }
|
||||||
bool isStatic() const { return _isStatic; }
|
bool isStatic() const { return _isStatic; }
|
||||||
|
|
||||||
const QString& getNodeVersion() const { return _nodeVersion; }
|
const QString& getNodeVersion() const { return _nodeVersion; }
|
||||||
|
|
||||||
const char* getTypeName() const;
|
const char* getTypeName() const;
|
||||||
static const char* typeToString(Assignment::Type type);
|
static const char* typeToString(Assignment::Type type);
|
||||||
|
|
||||||
|
@ -94,6 +96,16 @@ public:
|
||||||
friend QDataStream& operator>>(QDataStream &in, Assignment& assignment);
|
friend QDataStream& operator>>(QDataStream &in, Assignment& assignment);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/**
|
||||||
|
* @brief Parse the part of the settings object common to all assignment clients
|
||||||
|
*
|
||||||
|
* Currently this is the crash reporting settings.
|
||||||
|
*
|
||||||
|
* @param settingsObject
|
||||||
|
*/
|
||||||
|
void commonParseSettingsObject(const QJsonObject &settingsObject);
|
||||||
|
|
||||||
|
|
||||||
QUuid _uuid; /// the 16 byte UUID for this assignment
|
QUuid _uuid; /// the 16 byte UUID for this assignment
|
||||||
Assignment::Command _command; /// the command for this assignment (Create, Deploy, Request)
|
Assignment::Command _command; /// the command for this assignment (Create, Deploy, Request)
|
||||||
Assignment::Type _type; /// the type of the assignment, defines what the assignee will do
|
Assignment::Type _type; /// the type of the assignment, defines what the assignee will do
|
||||||
|
|
Loading…
Reference in a new issue