diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx index 9b394920a..961642266 100644 --- a/src/AIModel/AIManager.cxx +++ b/src/AIModel/AIManager.cxx @@ -21,12 +21,13 @@ #include #include -#include +#include #include #include -#include -#include +#include #include +#include +#include #include #include @@ -74,9 +75,15 @@ public: if (!loadScript.empty()) { FGNasalSys* nasalSys = globals->get_subsystem(); std::string moduleName = "scenario_" + _internalName; - nasalSys->createModule(moduleName.c_str(), moduleName.c_str(), - loadScript.c_str(), loadScript.size(), - nullptr); + bool ok = nasalSys->createModule(moduleName.c_str(), moduleName.c_str(), + loadScript.c_str(), loadScript.size(), + nullptr); + + if (!ok) { + // TODO: get the Nasal errors logged properly + simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::ScenarioLoad, + "Failed to parse scenario Nasal"); + } } } @@ -213,8 +220,10 @@ SGPropertyNode_ptr FGAIManager::registerScenarioFile(SGPropertyNode_ptr root, co auto scenariosNode = root->getNode("/sim/ai/scenarios", true); SGPropertyNode_ptr sNode; + simgear::ErrorReportContext ectx("scenario", xmlPath.utf8Str()); + // don't report XML errors while loading scenarios, to Sentry - flightgear::sentryThreadReportXMLErrors(false); + flightgear::SentryXMLErrorSupression xml; try { SGPropertyNode_ptr scenarioProps(new SGPropertyNode); @@ -246,12 +255,14 @@ SGPropertyNode_ptr FGAIManager::registerScenarioFile(SGPropertyNode_ptr root, co FGAICarrier::extractCarriersFromScenario(xs, sNode); } // of scenarios in the XML file - } catch (std::exception&) { + } catch (sg_exception& e) { SG_LOG(SG_AI, SG_WARN, "Skipping malformed scenario file:" << xmlPath); + simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::ScenarioLoad, + string{"The scenario couldn't be loaded:"} + e.getFormattedMessage(), + e.getLocation()); sNode.reset(); } - flightgear::sentryThreadReportXMLErrors(true); return sNode; } @@ -590,6 +601,7 @@ FGAIBasePtr FGAIManager::getObjectFromProperty(const SGPropertyNode* aProp) cons bool FGAIManager::loadScenario( const string &id ) { + simgear::ErrorReportContext("scenario", id); SGPropertyNode_ptr file = loadScenarioFile(id); if (!file) { return false; @@ -646,7 +658,10 @@ FGAIManager::loadScenarioFile(const std::string& scenarioName) { auto s = fgGetNode("/sim/ai/scenarios"); if (!s) return {}; - + + // don't report XML errors while loading scenarios, to Sentry + flightgear::SentryXMLErrorSupression xml; + for (auto n : s->getChildren("scenario")) { if (n->getStringValue("id") == scenarioName) { SGPath path{n->getStringValue("path")}; @@ -657,6 +672,9 @@ FGAIManager::loadScenarioFile(const std::string& scenarioName) } catch (const sg_exception &t) { SG_LOG(SG_AI, SG_ALERT, "Failed to load scenario '" << path << "': " << t.getFormattedMessage()); + simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::ScenarioLoad, + "Failed to laod scenario XML:" + t.getFormattedMessage(), + t.getLocation()); } } } diff --git a/src/Autopilot/autopilotgroup.cxx b/src/Autopilot/autopilotgroup.cxx index 49465ed19..58d68ee3f 100644 --- a/src/Autopilot/autopilotgroup.cxx +++ b/src/Autopilot/autopilotgroup.cxx @@ -31,10 +31,13 @@ #include #include +#include #include -#include #include +#include + #include
+#include
using std::vector; using simgear::PropertyList; @@ -189,13 +192,13 @@ void FGXMLAutopilotGroup::addAutopilotFromFile( const std::string& name, SGPath config = globals->resolve_maybe_aircraft_path(path); if( config.isNull() ) { - SG_LOG - ( - SG_AUTOPILOT, - SG_ALERT, - "Cannot find property-rule configuration file '" << path << "'." - ); - return; + simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::AircraftSystems, + string{"Autopilot XML not found:"} + path, sg_location{path}); + SG_LOG( + SG_AUTOPILOT, + SG_ALERT, + "Cannot find property-rule configuration file '" << path << "'."); + return; } SG_LOG ( @@ -206,11 +209,13 @@ void FGXMLAutopilotGroup::addAutopilotFromFile( const std::string& name, try { - SGPropertyNode_ptr configNode = new SGPropertyNode(); - readProperties( config, configNode ); + flightgear::SentryXMLErrorSupression xmlc; - SG_LOG(SG_AUTOPILOT, SG_INFO, "adding property-rule subsystem " << name); - addAutopilot(name, apNode, configNode); + SGPropertyNode_ptr configNode = new SGPropertyNode(); + readProperties(config, configNode); + + SG_LOG(SG_AUTOPILOT, SG_INFO, "adding property-rule subsystem " << name); + addAutopilot(name, apNode, configNode); } catch (const sg_exception& e) { @@ -221,6 +226,8 @@ void FGXMLAutopilotGroup::addAutopilotFromFile( const std::string& name, "Failed to load property-rule configuration: " << config << ": " << e.getMessage() ); + simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::AircraftSystems, + string{"Autopilot XML faield to load:"} + e.getFormattedMessage(), e.getLocation()); return; } } diff --git a/src/GUI/new_gui.cxx b/src/GUI/new_gui.cxx index 487f2ed7e..219c2bd21 100644 --- a/src/GUI/new_gui.cxx +++ b/src/GUI/new_gui.cxx @@ -12,12 +12,14 @@ #include #include -#include -#include +#include #include +#include +#include #include #include
+#include
#if defined(SG_UNIX) && !defined(SG_MAC) #include "GL/glx.h" @@ -207,9 +209,13 @@ NewGUI::showDialog (const string &name) // check we know about the dialog by name if (_dialog_names.find(name) == _dialog_names.end()) { + simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::GUIDialog, "Dialog not found:" + name); SG_LOG(SG_GENERAL, SG_ALERT, "Dialog " << name << " not defined"); return false; } + + flightgear::addSentryBreadcrumb("showing GUI dialog:" + name, "info"); + _active_dialogs[name] = new FGPUIDialog(getDialogProperties(name)); fgSetString("/sim/gui/dialogs/current-dialog", name); @@ -261,6 +267,8 @@ bool NewGUI::closeDialog (const string& name) { if(_active_dialogs.find(name) != _active_dialogs.end()) { + flightgear::addSentryBreadcrumb("closing GUI dialog:" + name, "info"); + if(_active_dialog == _active_dialogs[name]) _active_dialog = 0; delete _active_dialogs[name]; diff --git a/src/Input/FGDeviceConfigurationMap.cxx b/src/Input/FGDeviceConfigurationMap.cxx index 4e0d3323e..9f618fcc0 100644 --- a/src/Input/FGDeviceConfigurationMap.cxx +++ b/src/Input/FGDeviceConfigurationMap.cxx @@ -28,11 +28,13 @@ #include "FGDeviceConfigurationMap.hxx" +#include #include #include #include #include
+#include
#include using simgear::PropertyList; @@ -158,15 +160,21 @@ void FGDeviceConfigurationMap::readCachedData(const SGPath& path) void FGDeviceConfigurationMap::refreshCacheForFile(const SGPath& path) { - SG_LOG(SG_INPUT, SG_DEBUG, "Reading device file " << path); - SGPropertyNode_ptr n(new SGPropertyNode); - try { - readProperties(path, n); - } catch (sg_exception&) { - SG_LOG(SG_INPUT, SG_ALERT, "parse failure reading:" << path); - return; - } - + simgear::ErrorReportContext ectx("input-device", path.utf8Str()); + + SG_LOG(SG_INPUT, SG_DEBUG, "Reading device file " << path); + SGPropertyNode_ptr n(new SGPropertyNode); + flightgear::SentryXMLErrorSupression dontReportXmlErrors; + try { + readProperties(path, n); + } catch (sg_exception& e) { + SG_LOG(SG_INPUT, SG_ALERT, "parse failure reading:" << path); + simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::InputDeviceConfig, + "Failed to load input device configuration:" + e.getFormattedMessage(), + path); + return; + } + std::string suffix = computeSuffix(n); string_list names; for (auto nameProp : n->getChildren("name")) { diff --git a/src/Input/FGJoystickInput.cxx b/src/Input/FGJoystickInput.cxx index 5712172ca..2524dbaa3 100644 --- a/src/Input/FGJoystickInput.cxx +++ b/src/Input/FGJoystickInput.cxx @@ -32,7 +32,9 @@ #include +#include #include + #include "FGDeviceConfigurationMap.hxx" #include
#include @@ -202,6 +204,9 @@ void FGJoystickInput::postinit() if (!js_node || js->notWorking()) continue; + // FIXME : need to get input device path to disambiguate + simgear::ErrorReportContext errCtx("input-device", ""); + #ifdef WIN32 JOYCAPS jsCaps ; joyGetDevCaps( i, &jsCaps, sizeof(jsCaps) ); @@ -244,7 +249,12 @@ void FGJoystickInput::postinit() unsigned int j; for (j = 0; j < nasal.size(); j++) { nasal[j]->setStringValue("module", module.c_str()); - nasalsys->handleCommand(nasal[j],nullptr); + bool ok = nasalsys->handleCommand(nasal[j], nullptr); + if (!ok) { + // TODO: get the Nasal errors logged properly + simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::InputDeviceConfig, + "Failed to parse input device Nasal"); + } } // diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx index 31a77dca6..e63952bec 100644 --- a/src/Main/fg_commands.cxx +++ b/src/Main/fg_commands.cxx @@ -11,16 +11,18 @@ #include #include -#include +#include #include -#include #include -#include -#include +#include #include #include +#include +#include #include +#include #include + #include #include @@ -817,6 +819,8 @@ do_load_xml_to_proptree(const SGPropertyNode * arg, SGPropertyNode * root) { if (!quiet) { SG_LOG(SG_IO, SG_ALERT, "loadxml: Cannot find XML property file '" << file << "'."); + simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::XMLLoadCommand, + "loadxml: no such file:" + file.utf8Str(), file); } return false; } @@ -825,6 +829,8 @@ do_load_xml_to_proptree(const SGPropertyNode * arg, SGPropertyNode * root) if (!XMLLoader::findAirportData(icao, file.utf8Str(), file)) { if (!quiet) { SG_LOG(SG_IO, SG_INFO, "loadxml: failed to find airport data for " << file << " at ICAO:" << icao); + simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::XMLLoadCommand, + "loadxml: no airprot data file for:" + icao, file); } return false; } @@ -852,15 +858,17 @@ do_load_xml_to_proptree(const SGPropertyNode * arg, SGPropertyNode * root) // don't report Sentry errors for Nasal-loaded XML, since it makes // for very noisy reports - flightgear::sentryThreadReportXMLErrors(false); + flightgear::SentryXMLErrorSupression xmls; try { readProperties(validated_path, targetnode, true); } catch (const sg_exception &e) { + if (!quiet) { + simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::XMLLoadCommand, + "loadxml exception:" + e.getFormattedMessage(), e.getLocation()); + } SG_LOG(SG_IO, quiet ? SG_DEV_WARN : SG_WARN, "loadxml exception: " << e.getFormattedMessage()); - flightgear::sentryThreadReportXMLErrors(true); return false; } - flightgear::sentryThreadReportXMLErrors(true); return true; } diff --git a/src/Model/acmodel.cxx b/src/Model/acmodel.cxx index 83ef19bac..7e75dbe7a 100644 --- a/src/Model/acmodel.cxx +++ b/src/Model/acmodel.cxx @@ -10,7 +10,9 @@ #include // for strcmp() #include +#include #include + #include #include #include @@ -74,13 +76,20 @@ FGAircraftModel::init () return; } + simgear::ErrorReportContext ec("primary-aircraft", "yes"); + SGPropertyNode_ptr sim = fgGetNode("/sim", true); for (auto model : sim->getChildren("model")) { std::string path = model->getStringValue("path", "Models/Geometry/glider.ac"); std::string usage = model->getStringValue("usage", "external"); + simgear::ErrorReportContext ec("aircraft-model", path); + SGPath resolvedPath = globals->resolve_aircraft_path(path); if (resolvedPath.isNull()) { + simgear::reportFailure(simgear::LoadFailure::NotFound, + simgear::ErrorCode::XMLModelLoad, + "Failed to find aircraft model", SGPath::fromUtf8(path)); SG_LOG(SG_AIRCRAFT, SG_ALERT, "Failed to find aircraft model: " << path); continue; } @@ -89,6 +98,10 @@ FGAircraftModel::init () try { node = fgLoad3DModelPanel( resolvedPath, globals->get_props()); } catch (const sg_exception &ex) { + simgear::reportFailure(simgear::LoadFailure::BadData, + simgear::ErrorCode::XMLModelLoad, + "Failed to load aircraft model:" + ex.getFormattedMessage(), + ex.getLocation()); SG_LOG(SG_AIRCRAFT, SG_ALERT, "Failed to load aircraft from " << path << ':'); SG_LOG(SG_AIRCRAFT, SG_ALERT, " " << ex.getFormattedMessage()); } diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx index e75bde0f1..08668f619 100644 --- a/src/Scripting/NasalSys.cxx +++ b/src/Scripting/NasalSys.cxx @@ -33,19 +33,20 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include diff --git a/src/Sound/fg_fx.cxx b/src/Sound/fg_fx.cxx index f07003f1a..3578ef2c1 100644 --- a/src/Sound/fg_fx.cxx +++ b/src/Sound/fg_fx.cxx @@ -31,14 +31,16 @@ #include "fg_fx.hxx" -#include #include
#include
+#include
#include +#include +#include +#include #include #include -#include #include FGFX::FGFX ( const std::string &refname, SGPropertyNode *props ) : @@ -120,6 +122,8 @@ FGFX::init() SGPath path = globals->resolve_aircraft_path(path_str); if (path.isNull()) { + simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::AudioFX, + "Failed to find FX XML file:" + path_str, sg_location{path_str}); SG_LOG(SG_SOUND, SG_ALERT, "File not found: '" << path_str); return; @@ -129,8 +133,11 @@ FGFX::init() SGPropertyNode root; try { + flightgear::SentryXMLErrorSupression xmls; readProperties(path, &root); - } catch (const sg_exception &) { + } catch (const sg_exception& e) { + simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::AudioFX, + "Failure loading FX XML:" + e.getFormattedMessage(), e.getLocation()); SG_LOG(SG_SOUND, SG_ALERT, "Error reading file '" << path << '\''); return; @@ -150,6 +157,8 @@ FGFX::init() } } catch ( sg_exception &e ) { SG_LOG(SG_SOUND, SG_ALERT, e.getFormattedMessage()); + simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::AudioFX, + "Failure creating Audio FX:" + e.getFormattedMessage(), path); } } }