From 472e2a82224a39669d8c4e2ccdc6e0de84e77562 Mon Sep 17 00:00:00 2001 From: mbruin-NR <118208503+mbruin-NR@users.noreply.github.com> Date: Wed, 5 Feb 2025 09:47:35 -0500 Subject: [PATCH] Nr 350676 changing handled exceptions to send one per request (#338) * NR-350676 changing the handled exceptions to send one at a time * Fixing the unit tests * Made some recommended changes --- .../HandledException/NRMAHandledExceptions.mm | 5 +-- .../TestHexUploadPublisher.mm | 15 ++++---- .../Hex/include/Hex/HexPersistenceManager.hpp | 2 +- .../src/Hex/include/Hex/HexReportContext.hpp | 7 +++- libMobileAgent/src/Hex/src/HexController.cxx | 10 ++--- .../src/Hex/src/HexPersistenceManager.cxx | 37 +++++++++---------- .../src/Hex/src/HexReportContext.cxx | 25 ++++++++----- 7 files changed, 53 insertions(+), 48 deletions(-) diff --git a/Agent/HandledException/NRMAHandledExceptions.mm b/Agent/HandledException/NRMAHandledExceptions.mm index 92be8a1f..5300824d 100644 --- a/Agent/HandledException/NRMAHandledExceptions.mm +++ b/Agent/HandledException/NRMAHandledExceptions.mm @@ -334,10 +334,7 @@ - (void) recordHandledException:(NSException*)exception { - (void) processAndPublishPersistedReports { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ - auto context = _persistenceManager->retrieveStoreReports(); - if (context) { - _publisher->publish(context); - } + _persistenceManager->retrieveAndPublishReports(); }); } diff --git a/Tests/Unit-Tests/NewRelicAgentTests/Handled-Exception-Tests/TestHexUploadPublisher.mm b/Tests/Unit-Tests/NewRelicAgentTests/Handled-Exception-Tests/TestHexUploadPublisher.mm index 514c4ea3..c6d90a15 100644 --- a/Tests/Unit-Tests/NewRelicAgentTests/Handled-Exception-Tests/TestHexUploadPublisher.mm +++ b/Tests/Unit-Tests/NewRelicAgentTests/Handled-Exception-Tests/TestHexUploadPublisher.mm @@ -50,7 +50,8 @@ - (void)setUp { auto appLicense = std::make_shared("ABCDEF12345"); applicationInfo = std::make_shared(appLicense.get(),fbs::Platform_iOS); attributeValidator = new NewRelic::AttributeValidator([](const char*) {return true;},[](const char*) {return true;},[](const char*) {return true;}); - context = std::make_shared(applicationInfo,*attributeValidator); + auto uploadPublisher = new NewRelic::Hex::HexUploadPublisher(".","AppToken", "1.0", "staging-mobile-collector.staging.com"); + context = std::make_shared(applicationInfo,*attributeValidator,uploadPublisher); sessionId = std::string("ABSDFWERQWE"); e = std::make_shared(sessionId, 1, @@ -70,14 +71,14 @@ - (void)testHexUploaderCreation { auto appLicense = std::make_shared("ABCDEF12345"); std::shared_ptr applicationInfo = std::make_shared(appLicense.get(),fbs::Platform_iOS); NewRelic::AttributeValidator* attributeValidator = new NewRelic::AttributeValidator([](const char*) {return true;},[](const char*) {return true;},[](const char*) {return true;}); - std::shared_ptr context = std::make_shared(applicationInfo,*attributeValidator); + auto uploadPublisher = new NewRelic::Hex::HexUploadPublisher(".","AppToken", "1.0", "staging-mobile-collector.staging.com"); + std::shared_ptr context = std::make_shared(applicationInfo,*attributeValidator,uploadPublisher); std::shared_ptr exception = std::make_shared("sessionId", 1, "The tea is too hot.", "HotTeaException", std::vector>()); - auto uploadPublisher = new NewRelic::Hex::HexUploadPublisher(".","AppToken", "1.0", "staging-mobile-collector.staging.com"); XCTAssertTrue(uploadPublisher!=NULL); } @@ -88,15 +89,15 @@ - (void) testHexUploaderWrapper { auto appLicense = std::make_shared("ABCDEF12345"); std::shared_ptr applicationInfo = std::make_shared(appLicense.get(),fbs::Platform_iOS); NewRelic::AttributeValidator* attributeValidator = new NewRelic::AttributeValidator([](const char*) {return true;},[](const char*) {return true;},[](const char*) {return true;}); - std::shared_ptr context = std::make_shared(applicationInfo,*attributeValidator); + auto uploadPublisher = new NewRelic::Hex::TestHexUploadPublisher(".","AppToken", "1.0", "staging-mobile-collector.staging.com"); + auto uploader = uploadPublisher->getUploaderImpl(); + std::shared_ptr context = std::make_shared(applicationInfo,*attributeValidator,uploadPublisher); std::shared_ptr exception = std::make_shared("sessionId", 1, "The tea is too hot.", "HotTeaException", std::vector>()); - auto uploadPublisher = new NewRelic::Hex::TestHexUploadPublisher(".","AppToken", "1.0", "staging-mobile-collector.staging.com"); - auto uploader = uploadPublisher->getUploaderImpl(); id mockWrapper = [OCMockObject partialMockForObject:((UploaderImpl*)uploader)->wrapper]; @@ -106,7 +107,7 @@ - (void) testHexUploaderWrapper { context->finalize(); - uploadPublisher->publish(context); + // uploadPublisher->publish(context); XCTAssertNoThrow([mockWrapper verify]); } diff --git a/libMobileAgent/src/Hex/include/Hex/HexPersistenceManager.hpp b/libMobileAgent/src/Hex/include/Hex/HexPersistenceManager.hpp index f349a587..c0a5d725 100644 --- a/libMobileAgent/src/Hex/include/Hex/HexPersistenceManager.hpp +++ b/libMobileAgent/src/Hex/include/Hex/HexPersistenceManager.hpp @@ -19,7 +19,7 @@ namespace NewRelic { ~HexPersistenceManager() = default; - std::shared_ptr retrieveStoreReports(); + void retrieveAndPublishReports(); void publishContext(std::shared_ptrconst& context); diff --git a/libMobileAgent/src/Hex/include/Hex/HexReportContext.hpp b/libMobileAgent/src/Hex/include/Hex/HexReportContext.hpp index 4ff0e632..3b9c10f5 100644 --- a/libMobileAgent/src/Hex/include/Hex/HexReportContext.hpp +++ b/libMobileAgent/src/Hex/include/Hex/HexReportContext.hpp @@ -7,14 +7,16 @@ #define LIBMOBILEAGENT_HEXREPORTCONTEXT_HPP #include +#include namespace NewRelic { namespace Hex { - class HexReportContext : public HexContext { + class HexReportContext : public HexContext, public std::enable_shared_from_this { public: HexReportContext(const std::shared_ptr& applicationInfo, - const AttributeValidator& attributeValidator); + const AttributeValidator& attributeValidator, + HexPublisher* publisher); virtual void finalize(); @@ -29,6 +31,7 @@ namespace NewRelic { std::vector> reportList; const AttributeValidator& _attributeValidator; const std::shared_ptr& _applicationInfo; + HexPublisher* _publisher; }; } } diff --git a/libMobileAgent/src/Hex/src/HexController.cxx b/libMobileAgent/src/Hex/src/HexController.cxx index 0e32f681..defb160b 100644 --- a/libMobileAgent/src/Hex/src/HexController.cxx +++ b/libMobileAgent/src/Hex/src/HexController.cxx @@ -20,7 +20,7 @@ HexController::HexController(std::shared_ptr& analyti _publisher(publisher), _store(store), _sessionId(sessionId), - _keyContext(std::make_shared(_applicationInfo, _analytics->getAttributeValidator())) { + _keyContext(std::make_shared(_applicationInfo, _analytics->getAttributeValidator(), publisher)) { } HexController::HexController(std::shared_ptr&& analytics, @@ -33,7 +33,7 @@ HexController::HexController(std::shared_ptr&& analyt _publisher(publisher), _store(store), _sessionId(sessionId), - _keyContext(std::make_shared(_applicationInfo, _analytics->getAttributeValidator())) { + _keyContext(std::make_shared(_applicationInfo, _analytics->getAttributeValidator(), publisher)) { } // New Event System @@ -78,20 +78,20 @@ std::shared_ptr HexController::createReport(uint64_t epochMs, std::shared_ptr HexController::detachKeyContext() { std::unique_lock detachLock(_keyContextMutex); auto context = _keyContext; - _keyContext = std::make_shared(_applicationInfo, _analytics->getAttributeValidator()); + _keyContext = std::make_shared(_applicationInfo, _analytics->getAttributeValidator(), _publisher); return context; } void HexController::resetKeyContext() { std::unique_lock resetLock(_keyContextMutex); - _keyContext = std::make_shared(_applicationInfo, _analytics->getAttributeValidator()); + _keyContext = std::make_shared(_applicationInfo, _analytics->getAttributeValidator(), _publisher); } void HexController::publish() { auto context = detachKeyContext(); if (context->reports() > 0) { context->finalize(); - _publisher->publish(context); + // _publisher->publish(context); } } diff --git a/libMobileAgent/src/Hex/src/HexPersistenceManager.cxx b/libMobileAgent/src/Hex/src/HexPersistenceManager.cxx index 7cab8047..e1c1d7cb 100644 --- a/libMobileAgent/src/Hex/src/HexPersistenceManager.cxx +++ b/libMobileAgent/src/Hex/src/HexPersistenceManager.cxx @@ -7,6 +7,7 @@ #include "HexPersistenceManager.hpp" #include "hex-agent-data-bundle_generated.h" #include "jserror_generated.h" +#include using namespace NewRelic::Hex; using namespace com::newrelic::mobile; @@ -17,32 +18,28 @@ HexPersistenceManager::HexPersistenceManager(std::shared_ptr& store, } -std::shared_ptr NewRelic::Hex::HexPersistenceManager::retrieveStoreReports() { - auto context = std::make_shared(); - std::vector> agentDataVector; - - - auto future = _store->readAll([&agentDataVector, &context](uint8_t* buf, std::size_t size) { +void NewRelic::Hex::HexPersistenceManager::retrieveAndPublishReports() { + auto future = _store->readAll([this](uint8_t* buf, std::size_t size) { auto verifier = flatbuffers::Verifier(buf, size); - if(fbs::VerifyHexAgentDataBuffer(verifier)) { + if (fbs::VerifyHexAgentDataBuffer(verifier)) { auto agentDataObj = UnPackHexAgentData(buf, nullptr); - flatbuffers::Offset agentDataOffset = HexAgentData::Pack(*context->getBuilder(), agentDataObj.get(), - nullptr); - agentDataVector.push_back(agentDataOffset); - } - }); - future.get(); + // Create a new context for each piece of agent data + auto context = std::make_shared(); + flatbuffers::Offset agentDataOffset = HexAgentData::Pack(*context->getBuilder(), agentDataObj.get(), nullptr); - if (agentDataVector.empty()) { - return nullptr; - } - auto bundle = fbs::CreateHexAgentDataBundle(*context->getBuilder(), - context->getBuilder()->CreateVector(agentDataVector)); + Offset>> agentDataVector = context->getBuilder()->CreateVector(&agentDataOffset, 1); + auto bundle = fbs::CreateHexAgentDataBundle(*context->getBuilder(), agentDataVector); + FinishHexAgentDataBundleBuffer(*context->getBuilder(), bundle); - FinishHexAgentDataBundleBuffer(*context->getBuilder(), bundle); + // Publish the context for this agent data + if (context) { + _publisher->publish(context); + } + } + }); - return context; + future.get(); } void NewRelic::Hex::HexPersistenceManager::publishContext(std::shared_ptrconst& context) { diff --git a/libMobileAgent/src/Hex/src/HexReportContext.cxx b/libMobileAgent/src/Hex/src/HexReportContext.cxx index 8c3b2dca..5d49383f 100644 --- a/libMobileAgent/src/Hex/src/HexReportContext.cxx +++ b/libMobileAgent/src/Hex/src/HexReportContext.cxx @@ -12,28 +12,35 @@ using namespace NewRelic::Hex; using namespace com::newrelic::mobile; HexReportContext::HexReportContext(const std::shared_ptr& applicationInfo, - const AttributeValidator& attributeValidator) + const AttributeValidator& attributeValidator, + HexPublisher* publisher) : HexContext::HexContext(), _attributeValidator(attributeValidator), - _applicationInfo(applicationInfo) {} + _applicationInfo(applicationInfo), + _publisher(publisher){} void HexReportContext::finalize() { std::unique_lock finalizeLock(reportMutex); - std::vector> agentDataList; + for (auto& it : reportList) { try { - agentDataList.push_back(it->finalize(*getBuilder())); + auto agentDataOffset = it->finalize(*getBuilder()); + auto agentDataVector = getBuilder()->CreateVector(&agentDataOffset, 1); + + auto bundle = fbs::CreateHexAgentDataBundle(*getBuilder(), agentDataVector); + FinishHexAgentDataBundleBuffer(*getBuilder(), bundle); + auto sharedThis = std::static_pointer_cast(shared_from_this()); + + _publisher->publish(sharedThis); + + // Clear the builder for the next report + getBuilder()->Clear(); } catch (std::invalid_argument& e) { LLOG_AUDIT("Hex report not finalized: %s", e.what()); } catch (...) { LLOG_AUDIT("Hex report not finalized:"); } } - getBuilder()->CreateVector(agentDataList); - - auto bundle = fbs::CreateHexAgentDataBundle(*getBuilder(), getBuilder()->CreateVector(agentDataList)); - FinishHexAgentDataBundleBuffer(*getBuilder(), bundle); - } std::shared_ptr HexReportContext::createReport(std::shared_ptr exception) {