From 6269aa08484dedb6e25d257eb17330a55eb4b0e0 Mon Sep 17 00:00:00 2001 From: Alex Hemsath Date: Thu, 21 Sep 2023 15:47:13 -0700 Subject: [PATCH 1/7] Don't bail if log file can't be created --- .../NewRelic/Profiler/Profiler/CorProfilerCallbackImpl.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Agent/NewRelic/Profiler/Profiler/CorProfilerCallbackImpl.h b/src/Agent/NewRelic/Profiler/Profiler/CorProfilerCallbackImpl.h index c6e679c3e..1ca4b5c51 100644 --- a/src/Agent/NewRelic/Profiler/Profiler/CorProfilerCallbackImpl.h +++ b/src/Agent/NewRelic/Profiler/Profiler/CorProfilerCallbackImpl.h @@ -1074,9 +1074,11 @@ namespace NewRelic { namespace Profiler { nrlog::StdLog.get_dest().exceptions(std::wostream::failbit | std::wostream::badbit); LogInfo("Logger initialized."); } catch (...) { - printf("Unable to initialize the New Relic .NET Agent log file. Please make sure the logs directory is writeable.\n"); + printf("Unable to initialize the New Relic .NET Agent log file, but YOLO.\n"); // we can't log errors if the logger failed to initialize - return CORPROF_E_PROFILER_CANCEL_ACTIVATION; + //return CORPROF_E_PROFILER_CANCEL_ACTIVATION; + //nrlog::StdLog. set to console? + return S_OK; } return S_OK; } From 591e3685a00aa58de77d7a12bedccbcd7b8b392a Mon Sep 17 00:00:00 2001 From: Chris Hynes <111462425+chynesNR@users.noreply.github.com> Date: Fri, 3 Nov 2023 10:07:51 -0700 Subject: [PATCH 2/7] Support logging to stdout in the Profiler (#2025) --- .../Profiler/Configuration/Configuration.h | 27 ++++++ .../ConfigurationTest/ConfigOverrideTest.cpp | 83 +++++++++++++++++++ .../ConfigurationTest.vcxproj | 2 + .../ConfigurationTest/MockSystemCalls.h | 46 ++++++++++ src/Agent/NewRelic/Profiler/Logging/Logger.h | 45 +++++++++- .../Profiler/LoggingTest/LoggerTest.cpp | 62 +++++++++++++- .../Profiler/MethodRewriter/ISystemCalls.h | 54 +++++++++--- .../FunctionManipulatorTest.cpp | 1 - .../MethodRewriterTest/MethodRewriterTest.cpp | 1 - .../MethodRewriterTest.vcxproj | 1 - .../MethodRewriterTest/MockSystemCalls.h | 33 -------- .../Profiler/CorProfilerCallbackImpl.h | 72 +++++++++++----- 12 files changed, 350 insertions(+), 77 deletions(-) create mode 100644 src/Agent/NewRelic/Profiler/ConfigurationTest/ConfigOverrideTest.cpp create mode 100644 src/Agent/NewRelic/Profiler/ConfigurationTest/MockSystemCalls.h delete mode 100644 src/Agent/NewRelic/Profiler/MethodRewriterTest/MockSystemCalls.h diff --git a/src/Agent/NewRelic/Profiler/Configuration/Configuration.h b/src/Agent/NewRelic/Profiler/Configuration/Configuration.h index c79b60689..ac84abd74 100644 --- a/src/Agent/NewRelic/Profiler/Configuration/Configuration.h +++ b/src/Agent/NewRelic/Profiler/Configuration/Configuration.h @@ -32,6 +32,8 @@ namespace NewRelic { namespace Profiler { namespace Configuration { : _agentEnabled(true) , _agentEnabledInLocalConfig(false) , _logLevel(Logger::Level::LEVEL_INFO) + , _consoleLogging(false) + , _loggingEnabled(true) , _processes(new Processes()) , _applicationPoolsWhiteList(new ApplicationPools()) , _applicationPoolsBlackList(new ApplicationPools()) @@ -118,6 +120,8 @@ namespace NewRelic { namespace Profiler { namespace Configuration { : _agentEnabled(agentEnabled) , _agentEnabledInLocalConfig(false) , _logLevel(logLevel) + , _consoleLogging(false) + , _loggingEnabled(true) , _processes(processes) , _applicationPoolsWhiteList(whiteList) , _applicationPoolsBlackList(blackList) @@ -188,10 +192,21 @@ namespace NewRelic { namespace Profiler { namespace Configuration { return _logLevel; } + bool GetConsoleLogging() + { + return _consoleLogging; + } + bool GetLoggingEnabled() + { + return _loggingEnabled; + } + private: bool _agentEnabled; bool _agentEnabledInLocalConfig; Logger::Level _logLevel; + bool _consoleLogging; + bool _loggingEnabled; ProcessesPtr _processes; ApplicationPoolsPtr _applicationPoolsWhiteList; ApplicationPoolsPtr _applicationPoolsBlackList; @@ -250,6 +265,18 @@ namespace NewRelic { namespace Profiler { namespace Configuration { if (logNode == nullptr) return; + auto consoleAttribute = logNode->first_attribute(_X("console"), 0, false); + if (consoleAttribute != nullptr) + { + _consoleLogging = Strings::AreEqualCaseInsensitive(consoleAttribute->value(), _X("true")); + } + + auto enabledAttribute = logNode->first_attribute(_X("enabled"), 0, false); + if (enabledAttribute != nullptr) + { + _loggingEnabled = Strings::AreEqualCaseInsensitive(enabledAttribute->value(), _X("true")); + } + auto logLevelAttribute = logNode->first_attribute(_X("level"), 0, false); if (logLevelAttribute == nullptr) return; diff --git a/src/Agent/NewRelic/Profiler/ConfigurationTest/ConfigOverrideTest.cpp b/src/Agent/NewRelic/Profiler/ConfigurationTest/ConfigOverrideTest.cpp new file mode 100644 index 000000000..df03afbff --- /dev/null +++ b/src/Agent/NewRelic/Profiler/ConfigurationTest/ConfigOverrideTest.cpp @@ -0,0 +1,83 @@ +// Copyright 2020 New Relic, Inc. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include "../Common/xplat.h" +#include "../Common/Strings.h" +#include "../Logging/DefaultFileLogLocation.h" +#include "MockSystemCalls.h" + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace NewRelic { namespace Profiler { namespace Configuration { namespace Test +{ + TEST_CLASS(ConfigurationOverrideTest) + { + public: + TEST_METHOD(test_logging_enabled) + { + // Environment variable takes priority + _systemCalls.ResetEnvironmentVariables(); + _systemCalls.SetEnvironmentVariableW(_X("NEW_RELIC_LOG_ENABLED"), _X("1")); + Assert::IsTrue(_systemCalls.GetLoggingEnabled(false)); + Assert::IsTrue(_systemCalls.GetLoggingEnabled(true)); + + _systemCalls.SetEnvironmentVariableW(_X("NEW_RELIC_LOG_ENABLED"), _X("true")); + Assert::IsTrue(_systemCalls.GetLoggingEnabled(false)); + Assert::IsTrue(_systemCalls.GetLoggingEnabled(true)); + + _systemCalls.SetEnvironmentVariableW(_X("NEW_RELIC_LOG_ENABLED"), _X("0")); + Assert::IsFalse(_systemCalls.GetLoggingEnabled(false)); + Assert::IsFalse(_systemCalls.GetLoggingEnabled(true)); + + _systemCalls.SetEnvironmentVariableW(_X("NEW_RELIC_LOG_ENABLED"), _X("false")); + Assert::IsFalse(_systemCalls.GetLoggingEnabled(false)); + Assert::IsFalse(_systemCalls.GetLoggingEnabled(true)); + + // Use fallback (the config file value in actual usage) + _systemCalls.ResetEnvironmentVariables(); + + Assert::IsFalse(_systemCalls.GetLoggingEnabled(false)); + Assert::IsTrue(_systemCalls.GetLoggingEnabled(true)); + + _systemCalls.SetEnvironmentVariableW(_X("NEW_RELIC_LOG_ENABLED"), _X("*invalid*")); + Assert::IsFalse(_systemCalls.GetLoggingEnabled(false)); + Assert::IsTrue(_systemCalls.GetLoggingEnabled(true)); + } + TEST_METHOD(test_console_logging_enabled) + { + // Environment variable takes priority + _systemCalls.ResetEnvironmentVariables(); + _systemCalls.SetEnvironmentVariableW(_X("NEW_RELIC_LOG_CONSOLE"), _X("1")); + Assert::IsTrue(_systemCalls.GetConsoleLoggingEnabled(false)); + Assert::IsTrue(_systemCalls.GetConsoleLoggingEnabled(true)); + + _systemCalls.SetEnvironmentVariableW(_X("NEW_RELIC_LOG_CONSOLE"), _X("true")); + Assert::IsTrue(_systemCalls.GetConsoleLoggingEnabled(false)); + Assert::IsTrue(_systemCalls.GetConsoleLoggingEnabled(true)); + + _systemCalls.SetEnvironmentVariableW(_X("NEW_RELIC_LOG_CONSOLE"), _X("0")); + Assert::IsFalse(_systemCalls.GetConsoleLoggingEnabled(false)); + Assert::IsFalse(_systemCalls.GetConsoleLoggingEnabled(true)); + + _systemCalls.SetEnvironmentVariableW(_X("NEW_RELIC_LOG_CONSOLE"), _X("false")); + Assert::IsFalse(_systemCalls.GetConsoleLoggingEnabled(false)); + Assert::IsFalse(_systemCalls.GetConsoleLoggingEnabled(true)); + + // Use fallback (the config file value in actual usage) + _systemCalls.ResetEnvironmentVariables(); + + Assert::IsFalse(_systemCalls.GetConsoleLoggingEnabled(false)); + Assert::IsTrue(_systemCalls.GetConsoleLoggingEnabled(true)); + + _systemCalls.SetEnvironmentVariableW(_X("NEW_RELIC_LOG_CONSOLE"), _X("*invalid*")); + Assert::IsFalse(_systemCalls.GetConsoleLoggingEnabled(false)); + Assert::IsTrue(_systemCalls.GetConsoleLoggingEnabled(true)); + } + + private: + MockSystemCalls _systemCalls; + }; +}}}} diff --git a/src/Agent/NewRelic/Profiler/ConfigurationTest/ConfigurationTest.vcxproj b/src/Agent/NewRelic/Profiler/ConfigurationTest/ConfigurationTest.vcxproj index c2cd62f2f..734aec067 100644 --- a/src/Agent/NewRelic/Profiler/ConfigurationTest/ConfigurationTest.vcxproj +++ b/src/Agent/NewRelic/Profiler/ConfigurationTest/ConfigurationTest.vcxproj @@ -176,12 +176,14 @@ + + diff --git a/src/Agent/NewRelic/Profiler/ConfigurationTest/MockSystemCalls.h b/src/Agent/NewRelic/Profiler/ConfigurationTest/MockSystemCalls.h new file mode 100644 index 000000000..f8d39e039 --- /dev/null +++ b/src/Agent/NewRelic/Profiler/ConfigurationTest/MockSystemCalls.h @@ -0,0 +1,46 @@ +// Copyright 2020 New Relic, Inc. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#include +#include +#include +#include +#ifdef PAL_STDCPP_COMPAT +#include "../Profiler/UnixSystemCalls.h" +#else +#include "../Profiler/SystemCalls.h" +#endif + +namespace NewRelic { namespace Profiler { namespace Configuration { namespace Test +{ + struct MockSystemCalls : NewRelic::Profiler::SystemCalls + { + std::unordered_map environmentVariables; + + MockSystemCalls() + { + + } + + virtual std::unique_ptr TryGetEnvironmentVariable(const xstring_t& variableName) override + { + return std::make_unique(environmentVariables[variableName]); + } + + virtual bool FileExists(const xstring_t&) override + { + return true; + } + + void SetEnvironmentVariable(xstring_t name, xstring_t value) + { + environmentVariables[name] = value; + } + + void ResetEnvironmentVariables() + { + environmentVariables.clear(); + } + }; +}}}} diff --git a/src/Agent/NewRelic/Profiler/Logging/Logger.h b/src/Agent/NewRelic/Profiler/Logging/Logger.h index 2bbf50a1b..ef78c12b2 100644 --- a/src/Agent/NewRelic/Profiler/Logging/Logger.h +++ b/src/Agent/NewRelic/Profiler/Logging/Logger.h @@ -6,6 +6,8 @@ #include #include #include //wofstream +#include +#include #include #include #include "../Common/xplat.h" @@ -44,7 +46,7 @@ namespace NewRelic { using _Mystreamtype = std::basic_ostream; using _Mymut = std::mutex; using _Mylockgrd = std::lock_guard<_Mymut>; - Logger(_Ostr&& myostr, Level level) : _level(level), _destination(std::move(myostr)) + Logger(_Ostr&& myostr, Level level) : _level(level), _destination(std::move(myostr)), _console(false), _enabled(true), _initialized(false) { logging_available = true; } @@ -83,7 +85,39 @@ namespace NewRelic { Level GetLevel() const noexcept { - return _level; + if (!_console) + { + return _level; + } + // Console logging at debug or trace level incurs a very large + // performance hit. Clamp the log level to INFO in that case. + return (_level < Level::LEVEL_INFO) ? Level::LEVEL_INFO : _level; + } + + void SetConsoleLogging(bool enabled) + { + _console = enabled; + } + + bool GetConsoleLogging() + { + return _console; + } + void SetEnabled(bool enabled) + { + _enabled = enabled; + } + bool GetEnabled() + { + return _enabled; + } + void SetInitalized() + { + _initialized = true; + } + bool GetInitialized() + { + return _initialized; } _Mymut& mutex() const noexcept @@ -94,6 +128,9 @@ namespace NewRelic { _Ostr _destination; Level _level; mutable _Mymut _mutex; + bool _console; + bool _enabled; + bool _initialized; }; using FileLogger = Logger; @@ -127,7 +164,7 @@ namespace NewRelic { } using stream_char_t = typename _Log::char_type; - if (level >= log.GetLevel()) + if (log.GetInitialized() && log.GetEnabled() && (level >= log.GetLevel())) { //each thread will have these on the stack... std::tm tstruct; @@ -135,7 +172,7 @@ namespace NewRelic { (void)time(&now); (void)gmtime_s(&tstruct, &now); auto levelstr = nrlog::GetLevelString(level); - auto& strm = log.ostr(); + std::wostream& strm = log.GetConsoleLogging() ? std::wcout : log.ostr(); try { diff --git a/src/Agent/NewRelic/Profiler/LoggingTest/LoggerTest.cpp b/src/Agent/NewRelic/Profiler/LoggingTest/LoggerTest.cpp index cf1966d99..d12aa5130 100644 --- a/src/Agent/NewRelic/Profiler/LoggingTest/LoggerTest.cpp +++ b/src/Agent/NewRelic/Profiler/LoggingTest/LoggerTest.cpp @@ -45,6 +45,9 @@ namespace NewRelic { TEST_METHOD_INITIALIZE(MethodSetup) { StdLog.SetLevel(Level::LEVEL_INFO); + StdLog.SetConsoleLogging(false); + StdLog.SetEnabled(true); + StdLog.SetInitalized(); } TEST_METHOD(logger_verify_string_representation_of_levels) @@ -182,7 +185,7 @@ namespace NewRelic { LogError(L"Data too large to compress. ", std::hex, std::showbase, dataToCompress, std::resetiosflags(std::ios_base::basefield | std::ios_base::showbase)); AssertRegex(ERROR_PREFIX_REGEX L"Data too large to compress\\. 0xdeadbeef\n"); } - { + { //wchar_t NBTS LogTrace(L"This is a small message."); AssertRegex(TRACE_PREFIX_REGEX L"This is a small message\\.\n"); @@ -260,8 +263,8 @@ namespace NewRelic { } { - wchar_t *source = L""; - const rapidxml::parse_error exception("what string", source+9); + wchar_t* source = L""; + const rapidxml::parse_error exception("what string", source + 9); LogError(L"Exception thrown while attempting to parse configuration file. ", exception.what(), L" at ", exception.where()); AssertRegex(ERROR_PREFIX_REGEX L"Exception thrown while attempting to parse configuration file\\. what string at :=foo>\n"); } @@ -317,7 +320,58 @@ namespace NewRelic { auto str = StdLog.get_dest().str(); AssertRegex(ERROR_PREFIX_REGEX LR"X(Encountered unsupported instruction while attempting to generate byte code. Instruction: whipit.good)X" L"\n"); } - } + } + TEST_METHOD(logger_test_console) + { + StdLog.SetLevel(Level::LEVEL_TRACE); + StdLog.SetConsoleLogging(true); + ResetStdLog(); + + LogInfo("blah blah blah"); + LogWarn("A warning"); + LogError("An error"); + + AssertMessageCount(0); + } + + TEST_METHOD(logger_test_console_restrictions) + { + ResetStdLog(); + StdLog.SetLevel(Level::LEVEL_TRACE); + StdLog.SetConsoleLogging(true); + Assert::AreEqual(StdLog.GetLevel(), Level::LEVEL_INFO); + + ResetStdLog(); + StdLog.SetConsoleLogging(false); + StdLog.SetLevel(Level::LEVEL_TRACE); + Assert::AreEqual(StdLog.GetLevel(), Level::LEVEL_TRACE); + + ResetStdLog(); + StdLog.SetLevel(Level::LEVEL_WARN); + StdLog.SetConsoleLogging(true); + Assert::AreEqual(StdLog.GetLevel(), Level::LEVEL_WARN); + + // Disabling console logging should revert to the original log level + StdLog.SetConsoleLogging(true); + StdLog.SetLevel(Level::LEVEL_DEBUG); + Assert::AreEqual(StdLog.GetLevel(), Level::LEVEL_INFO); + StdLog.SetConsoleLogging(false); + Assert::AreEqual(StdLog.GetLevel(), Level::LEVEL_DEBUG); + } + + TEST_METHOD(logger_test_disabled) + { + StdLog.SetLevel(Level::LEVEL_TRACE); + StdLog.SetEnabled(false); + ResetStdLog(); + + LogInfo("blah blah blah"); + LogWarn("A warning"); + LogError("An error"); + + AssertMessageCount(0); + } + //------------------------------------------------------------ diff --git a/src/Agent/NewRelic/Profiler/MethodRewriter/ISystemCalls.h b/src/Agent/NewRelic/Profiler/MethodRewriter/ISystemCalls.h index df5e795ba..bf29a7c4b 100644 --- a/src/Agent/NewRelic/Profiler/MethodRewriter/ISystemCalls.h +++ b/src/Agent/NewRelic/Profiler/MethodRewriter/ISystemCalls.h @@ -49,19 +49,7 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter { virtual bool GetIsAppDomainCachingDisabled() { - auto value = TryGetEnvironmentVariable(_X("NEW_RELIC_DISABLE_APPDOMAIN_CACHING")); - - if (value == nullptr) - { - return false; - } - - if(Strings::AreEqualCaseInsensitive(*value, _X("true")) || Strings::AreEqualCaseInsensitive(*value, _X("1"))) - { - return true; - } - - return false; + return GetEnvironmentBool(_X("NEW_RELIC_DISABLE_APPDOMAIN_CACHING"), false); } virtual std::unique_ptr GetProfilerDelay() @@ -89,8 +77,48 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter { return TryGetEnvironmentVariable(_X("APP_POOL_ID")); } + virtual bool GetLoggingEnabled(bool fallback) + { + return GetEnvironmentBool(_X("NEW_RELIC_LOG_ENABLED"), fallback); + } + + virtual bool GetConsoleLoggingEnabled(bool fallback) + { + return GetEnvironmentBool(_X("NEW_RELIC_LOG_CONSOLE"), fallback); + } + + + private: bool _isCoreClr = false; + /// + /// Gets an environment variable that should be a boolean + /// + /// Name of the environment variable to fetch + /// If the environment variable doesn't + /// exist, or the value isn't 0/1/true/false, return the given fallback value + /// The value of the environment variable, or the fallback + bool GetEnvironmentBool(const xstring_t& variableName, bool fallback) + { + auto value = TryGetEnvironmentVariable(variableName); + + if (value == nullptr) + { + return fallback; + } + + if (Strings::AreEqualCaseInsensitive(*value, _X("true")) || Strings::AreEqualCaseInsensitive(*value, _X("1"))) + { + return true; + } + + if (Strings::AreEqualCaseInsensitive(*value, _X("false")) || Strings::AreEqualCaseInsensitive(*value, _X("0"))) + { + return false; + } + + return fallback; + } }; typedef std::shared_ptr ISystemCallsPtr; typedef std::set FilePaths; diff --git a/src/Agent/NewRelic/Profiler/MethodRewriterTest/FunctionManipulatorTest.cpp b/src/Agent/NewRelic/Profiler/MethodRewriterTest/FunctionManipulatorTest.cpp index 5a594b411..1830f6f96 100644 --- a/src/Agent/NewRelic/Profiler/MethodRewriterTest/FunctionManipulatorTest.cpp +++ b/src/Agent/NewRelic/Profiler/MethodRewriterTest/FunctionManipulatorTest.cpp @@ -8,7 +8,6 @@ #include "../Common/Macros.h" #include "MockFunction.h" -#include "MockSystemCalls.h" #include "../MethodRewriter/FunctionManipulator.h" #include "../MethodRewriter/InstrumentFunctionManipulator.h" diff --git a/src/Agent/NewRelic/Profiler/MethodRewriterTest/MethodRewriterTest.cpp b/src/Agent/NewRelic/Profiler/MethodRewriterTest/MethodRewriterTest.cpp index 24d085211..a71f15888 100644 --- a/src/Agent/NewRelic/Profiler/MethodRewriterTest/MethodRewriterTest.cpp +++ b/src/Agent/NewRelic/Profiler/MethodRewriterTest/MethodRewriterTest.cpp @@ -11,7 +11,6 @@ #include "../MethodRewriter/MethodRewriter.h" #include "CppUnitTest.h" #include "MockFunction.h" -#include "MockSystemCalls.h" #include "UnreferencedFunctions.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; diff --git a/src/Agent/NewRelic/Profiler/MethodRewriterTest/MethodRewriterTest.vcxproj b/src/Agent/NewRelic/Profiler/MethodRewriterTest/MethodRewriterTest.vcxproj index 35749b852..1c79257ea 100644 --- a/src/Agent/NewRelic/Profiler/MethodRewriterTest/MethodRewriterTest.vcxproj +++ b/src/Agent/NewRelic/Profiler/MethodRewriterTest/MethodRewriterTest.vcxproj @@ -182,7 +182,6 @@ - diff --git a/src/Agent/NewRelic/Profiler/MethodRewriterTest/MockSystemCalls.h b/src/Agent/NewRelic/Profiler/MethodRewriterTest/MockSystemCalls.h deleted file mode 100644 index 7eb30b582..000000000 --- a/src/Agent/NewRelic/Profiler/MethodRewriterTest/MockSystemCalls.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -#pragma once -#include -#include -#include -#include "../MethodRewriter/ISystemCalls.h" - -namespace NewRelic { namespace Profiler { namespace MethodRewriter { namespace Test { - struct MockSystemCalls : ISystemCalls - { - std::function(const std::wstring&)> EnvironmentVariableResult; - - MockSystemCalls() - { - EnvironmentVariableResult = [](const std::wstring&) - { - return std::unique_ptr(new std::wstring(L"C:\\foo\\bar")); - }; - } - - virtual std::unique_ptr TryGetEnvironmentVariable(const std::wstring& variableName) - { - return EnvironmentVariableResult(variableName); - } - - virtual bool FileExists(const xstring_t&) override - { - return true; - } - }; -}}}} diff --git a/src/Agent/NewRelic/Profiler/Profiler/CorProfilerCallbackImpl.h b/src/Agent/NewRelic/Profiler/Profiler/CorProfilerCallbackImpl.h index 1ca4b5c51..6fc76d4c0 100644 --- a/src/Agent/NewRelic/Profiler/Profiler/CorProfilerCallbackImpl.h +++ b/src/Agent/NewRelic/Profiler/Profiler/CorProfilerCallbackImpl.h @@ -207,10 +207,29 @@ namespace NewRelic { namespace Profiler { return CORPROF_E_PROFILER_CANCEL_ACTIVATION; } - HRESULT loggingInitResult = InitializeLogging(); - if (FAILED(loggingInitResult)) + // A bit of a catch-22: we want to load the config file first in case there are logging + // settings, but we also want to log if there are issues with the config file. + // So first, we try to load the config file... + NewRelic::Profiler::Configuration::ConfigurationPtr configuration; + bool configFailed = false; + try + { + configuration = InitializeConfigAndSetLogLevel(); + } + catch (...) + { + configFailed = true; + } + + // ...then we initialize the log + InitializeLogging(); + + // If we failed to load the config file, try again. Not because we expect it + // to succeed, but because we want to log the error. We couldn't do that the + // first time because the logger hadn't been initialized yet + if (configFailed) { - return loggingInitResult; + configuration = InitializeConfigAndSetLogLevel(); } LogTrace(_productName); @@ -222,7 +241,6 @@ namespace NewRelic { namespace Profiler { //Init does not start threads or requires cleanup. RequestProfile will create the threads for the TP. _threadProfiler.Init(_corProfilerInfo4); - auto configuration = InitializeConfigAndSetLogLevel(); HRESULT corePathInitResult = InitializeAndSetAgentCoreDllPath(_productName); if (FAILED(corePathInitResult)) { @@ -1064,23 +1082,24 @@ namespace NewRelic { namespace Profiler { return millisecondsInteger; } - HRESULT InitializeLogging() + void InitializeLogging() { - // if logging fails to initialize then just bail - try { - xstring_t logfilename(nrlog::DefaultFileLogLocation(_systemCalls).GetPathAndFileName()); - std::string wlogfilename(std::begin(logfilename), std::end(logfilename)); - nrlog::StdLog.get_dest().open(wlogfilename); - nrlog::StdLog.get_dest().exceptions(std::wostream::failbit | std::wostream::badbit); - LogInfo("Logger initialized."); - } catch (...) { - printf("Unable to initialize the New Relic .NET Agent log file, but YOLO.\n"); - // we can't log errors if the logger failed to initialize - //return CORPROF_E_PROFILER_CANCEL_ACTIVATION; - //nrlog::StdLog. set to console? - return S_OK; + // Only need to initialize the file if we're doing file logging + if (nrlog::StdLog.GetEnabled() && !nrlog::StdLog.GetConsoleLogging()) + { + try { + xstring_t logfilename(nrlog::DefaultFileLogLocation(_systemCalls).GetPathAndFileName()); + std::string wlogfilename(std::begin(logfilename), std::end(logfilename)); + nrlog::StdLog.get_dest().open(wlogfilename); + nrlog::StdLog.get_dest().exceptions(std::wostream::failbit | std::wostream::badbit); + LogInfo("Logger initialized."); + } + catch (...) { + // If we fail to create a log file, there's no sense in trying to log going forward. + // We want the Profiler continue to run, though, so swallow the exception + nrlog::StdLog.SetEnabled(false); + } } - return S_OK; } std::shared_ptr InitializeConfigAndSetLogLevel() @@ -1091,7 +1110,20 @@ namespace NewRelic { namespace Profiler { auto configuration = std::make_shared(globalNewRelicConfigurationXml, localNewRelicConfigurationXml, applicationConfigurationXml, _systemCalls); nrlog::StdLog.SetLevel(configuration->GetLoggingLevel()); - LogInfo(L"<-- New logging level set: ", nrlog::GetLevelString(nrlog::StdLog.GetLevel())); + nrlog::StdLog.SetConsoleLogging(_systemCalls->GetConsoleLoggingEnabled(configuration->GetConsoleLogging())); + nrlog::StdLog.SetEnabled(_systemCalls->GetLoggingEnabled(configuration->GetLoggingEnabled())); + nrlog::StdLog.SetInitalized(); + + if (nrlog::StdLog.GetEnabled()) + { + LogInfo(L"<-- New logging level set: ", nrlog::GetLevelString(nrlog::StdLog.GetLevel())); + if (nrlog::StdLog.GetConsoleLogging()) + { + LogInfo(L"Console logging enabled"); + } + } + // While we would like to indicate that logging is disabled somehow, there's of + // course no log to write to return configuration; } From 822c54112d419b93b374fec819aad20cd090f7d8 Mon Sep 17 00:00:00 2001 From: Chris Hynes <111462425+chynesNR@users.noreply.github.com> Date: Thu, 9 Nov 2023 15:34:54 -0800 Subject: [PATCH 3/7] Agent support for read-only file systems (#2045) * New option to disable logging * Env var for console logging * Supportability metric if logging fails * Don't allow audit logging if logging is disabled --- .../Core/AgentHealth/AgentHealthReporter.cs | 13 ++ src/Agent/NewRelic/Agent/Core/AgentManager.cs | 2 + .../Agent/Core/Config/Configuration.cs | 16 ++ .../Agent/Core/Config/Configuration.xsd | 8 + .../Agent/Core/Config/ConfigurationLoader.cs | 44 ++++- .../NewRelic/Agent/Core/Config/ILogConfig.cs | 2 + .../Configuration/ConfigurationService.cs | 2 +- .../Configuration/DefaultConfiguration.cs | 2 + .../Configuration/ReportedConfiguration.cs | 3 + .../Agent/Core/Logging/LoggerBootstrapper.cs | 22 +-- .../Agent/Core/Metrics/MetricNames.cs | 3 + .../Configuration/IConfiguration.cs | 1 + src/NewRelic.Core/Logging/Log.cs | 2 + .../AgentHealth/AgentHealthReporterTests.cs | 40 +++- .../DataTransport/AgentSettingsTests.cs | 2 +- .../DataTransport/ConnectModelTests.cs | 2 +- .../ExhaustiveTestConfiguration.cs | 4 +- .../LoggerBootstrapperTest.cs | 186 ++++++++++++++++++ 18 files changed, 335 insertions(+), 19 deletions(-) diff --git a/src/Agent/NewRelic/Agent/Core/AgentHealth/AgentHealthReporter.cs b/src/Agent/NewRelic/Agent/Core/AgentHealth/AgentHealthReporter.cs index bdc065684..5fd930454 100644 --- a/src/Agent/NewRelic/Agent/Core/AgentHealth/AgentHealthReporter.cs +++ b/src/Agent/NewRelic/Agent/Core/AgentHealth/AgentHealthReporter.cs @@ -695,6 +695,7 @@ private void CollectOneTimeMetrics() ReportLogForwardingConfiguredValues(); ReportIfAppDomainCachingDisabled(); ReportInfiniteTracingOneTimeMetrics(); + ReportIfLoggingDisabled(); } public void CollectMetrics() @@ -829,5 +830,17 @@ protected override void OnConfigurationUpdated(ConfigurationUpdateSource configu // Some one time metrics are reporting configured values, so we want to re-report them if the configuration changed _oneTimeMetricsCollected = false; } + + private void ReportIfLoggingDisabled() + { + if (!_configuration.LoggingEnabled) + { + ReportSupportabilityCountMetric(MetricNames.SupportabilityLoggingDisabled); + } + if (Log.FileLoggingHasFailed) + { + ReportSupportabilityCountMetric(MetricNames.SupportabilityLoggingFatalError); + } + } } } diff --git a/src/Agent/NewRelic/Agent/Core/AgentManager.cs b/src/Agent/NewRelic/Agent/Core/AgentManager.cs index c42363611..d55ba5211 100644 --- a/src/Agent/NewRelic/Agent/Core/AgentManager.cs +++ b/src/Agent/NewRelic/Agent/Core/AgentManager.cs @@ -220,6 +220,8 @@ private void LogInitialized() "NEW_RELIC_LOG", "NEWRELIC_PROFILER_LOG_DIRECTORY", "NEWRELIC_LOG_LEVEL", + "NEW_RELIC_LOG_ENABLED", + "NEW_RELIC_LOG_CONSOLE", "NEW_RELIC_LABELS", "NEW_RELIC_PROXY_HOST", "NEW_RELIC_PROXY_URI_PATH", diff --git a/src/Agent/NewRelic/Agent/Core/Config/Configuration.cs b/src/Agent/NewRelic/Agent/Core/Config/Configuration.cs index 7f0227d26..9048e75d6 100644 --- a/src/Agent/NewRelic/Agent/Core/Config/Configuration.cs +++ b/src/Agent/NewRelic/Agent/Core/Config/Configuration.cs @@ -1284,6 +1284,7 @@ public virtual configurationApplication Clone() [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:newrelic-config")] public partial class configurationLog { + private bool enabledField; private string levelField; @@ -1300,6 +1301,7 @@ public partial class configurationLog /// public configurationLog() { + this.enabledField = true; this.levelField = "info"; this.consoleField = false; this.auditLogField = false; @@ -1358,6 +1360,20 @@ public bool console this.consoleField = value; } } + + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(true)] + public bool enabled + { + get + { + return this.enabledField; + } + set + { + this.enabledField = value; + } + } [System.Xml.Serialization.XmlAttributeAttribute()] [System.ComponentModel.DefaultValueAttribute(false)] diff --git a/src/Agent/NewRelic/Agent/Core/Config/Configuration.xsd b/src/Agent/NewRelic/Agent/Core/Config/Configuration.xsd index 843e175d0..5a5c6e0af 100644 --- a/src/Agent/NewRelic/Agent/Core/Config/Configuration.xsd +++ b/src/Agent/NewRelic/Agent/Core/Config/Configuration.xsd @@ -313,6 +313,14 @@ + + + + If this is false, no attempts will be made to write to a log file. This is primarily used for installations on read-only file systems. + + + + diff --git a/src/Agent/NewRelic/Agent/Core/Config/ConfigurationLoader.cs b/src/Agent/NewRelic/Agent/Core/Config/ConfigurationLoader.cs index 8c019aa85..2353f7b1f 100644 --- a/src/Agent/NewRelic/Agent/Core/Config/ConfigurationLoader.cs +++ b/src/Agent/NewRelic/Agent/Core/Config/ConfigurationLoader.cs @@ -59,6 +59,7 @@ private static string InternalGetAppDomainAppPath() public static Func FileExists = File.Exists; public static Func PathGetDirectoryName = Path.GetDirectoryName; + public static Func GetEnvironmentVar = System.Environment.GetEnvironmentVariable; private static string InternalGetNewRelicHome() { @@ -522,6 +523,10 @@ public string LogLevel { get { + if (!Enabled) + { + return "off"; + } // Environment variable or log.level from config... return (AgentInstallConfiguration.NewRelicLogLevel ?? this.level).ToUpper(); @@ -559,7 +564,7 @@ public string GetFullLogFileName() private string GetLogFileName() { - string name = System.Environment.GetEnvironmentVariable("NEW_RELIC_LOG"); + string name = ConfigurationLoader.GetEnvironmentVar("NEW_RELIC_LOG"); if (name != null) { return Strings.SafeFileName(name); @@ -594,11 +599,46 @@ private string GetLogFileName() return "newrelic_agent_" + Strings.SafeFileName(name) + ".log"; } + private bool GetOverride(string name, bool fallback) + { + var val = ConfigurationLoader.GetEnvironmentVar(name); + + if (val != null) + { + val = val.ToLower(); + } + + if (bool.TryParse(val, out var parsedValue)) + { + return parsedValue; + } + + if ("0" == val) + { + return false; + } + + if ("1" == val) + { + return true; + } + + return fallback; + } + public bool Console { get { - return console; + return GetOverride("NEW_RELIC_LOG_CONSOLE", console); + } + } + + public bool Enabled + { + get + { + return GetOverride("NEW_RELIC_LOG_ENABLED", enabled); } } diff --git a/src/Agent/NewRelic/Agent/Core/Config/ILogConfig.cs b/src/Agent/NewRelic/Agent/Core/Config/ILogConfig.cs index 8b072cbdd..cfc9d6a15 100644 --- a/src/Agent/NewRelic/Agent/Core/Config/ILogConfig.cs +++ b/src/Agent/NewRelic/Agent/Core/Config/ILogConfig.cs @@ -5,6 +5,8 @@ namespace NewRelic.Agent.Core.Config { public interface ILogConfig { + bool Enabled { get; } + string LogLevel { get; } string GetFullLogFileName(); diff --git a/src/Agent/NewRelic/Agent/Core/Configuration/ConfigurationService.cs b/src/Agent/NewRelic/Agent/Core/Configuration/ConfigurationService.cs index 18283fce9..51398dea5 100644 --- a/src/Agent/NewRelic/Agent/Core/Configuration/ConfigurationService.cs +++ b/src/Agent/NewRelic/Agent/Core/Configuration/ConfigurationService.cs @@ -64,7 +64,7 @@ private void OnConfigurationDeserialized(ConfigurationDeserializedEvent configur private static void UpdateLogLevel(configuration localConfiguration) { Log.Info("The log level was updated to {0}", localConfiguration.LogConfig.LogLevel); - LoggerBootstrapper.UpdateLoggingLevel(localConfiguration.LogConfig.LogLevel); + LoggerBootstrapper.SetLoggingLevel(localConfiguration.LogConfig.LogLevel); } private void OnServerConfigurationUpdated(ServerConfigurationUpdatedEvent serverConfigurationUpdatedEvent) diff --git a/src/Agent/NewRelic/Agent/Core/Configuration/DefaultConfiguration.cs b/src/Agent/NewRelic/Agent/Core/Configuration/DefaultConfiguration.cs index e874bba86..24ab8eaac 100644 --- a/src/Agent/NewRelic/Agent/Core/Configuration/DefaultConfiguration.cs +++ b/src/Agent/NewRelic/Agent/Core/Configuration/DefaultConfiguration.cs @@ -2765,6 +2765,8 @@ public bool CodeLevelMetricsEnabled #endregion + public bool LoggingEnabled => _localConfiguration.log.Enabled; + private const bool CaptureTransactionTraceAttributesDefault = true; private const bool CaptureErrorCollectorAttributesDefault = true; private const bool CaptureBrowserMonitoringAttributesDefault = false; diff --git a/src/Agent/NewRelic/Agent/Core/Configuration/ReportedConfiguration.cs b/src/Agent/NewRelic/Agent/Core/Configuration/ReportedConfiguration.cs index e57235795..c296c12f7 100644 --- a/src/Agent/NewRelic/Agent/Core/Configuration/ReportedConfiguration.cs +++ b/src/Agent/NewRelic/Agent/Core/Configuration/ReportedConfiguration.cs @@ -644,6 +644,9 @@ public ReportedConfiguration(IConfiguration configuration) [JsonProperty("stackexchangeredis_cleanup.cycle")] public TimeSpan StackExchangeRedisCleanupCycle => _configuration.StackExchangeRedisCleanupCycle; + [JsonProperty("agent.logging_enabled")] + public bool LoggingEnabled => _configuration.LoggingEnabled; + public IReadOnlyDictionary GetAppSettings() { return _configuration.GetAppSettings(); diff --git a/src/Agent/NewRelic/Agent/Core/Logging/LoggerBootstrapper.cs b/src/Agent/NewRelic/Agent/Core/Logging/LoggerBootstrapper.cs index 71c27ae57..041ff6bdd 100644 --- a/src/Agent/NewRelic/Agent/Core/Logging/LoggerBootstrapper.cs +++ b/src/Agent/NewRelic/Agent/Core/Logging/LoggerBootstrapper.cs @@ -32,10 +32,7 @@ public static class LoggerBootstrapper private static InMemorySink _inMemorySink = new InMemorySink(); - public static void UpdateLoggingLevel(string newLogLevel) - { - _loggingLevelSwitch.MinimumLevel = newLogLevel.MapToSerilogLogLevel(); - } + public static void SetLoggingLevel(string newLogLevel) => _loggingLevelSwitch.MinimumLevel = newLogLevel.MapToSerilogLogLevel(); public static void Initialize() { @@ -55,7 +52,7 @@ public static void Initialize() /// This should only be called once, as soon as you have a valid config. public static void ConfigureLogger(ILogConfig config) { - SetupLogLevel(config); + SetLoggingLevel(config.LogLevel); var loggerConfig = new LoggerConfiguration() .MinimumLevel.ControlledBy(_loggingLevelSwitch) @@ -77,6 +74,8 @@ public static void ConfigureLogger(ILogConfig config) Log.Logger = configuredLogger; NewRelic.Core.Logging.Log.Initialize(new Logger()); + + Log.Logger.Information("Log level set to {0}", config.LogLevel); } private static void EchoInMemoryLogsToConfiguredLogger(ILogger configuredLogger) @@ -89,12 +88,6 @@ private static void EchoInMemoryLogsToConfiguredLogger(ILogger configuredLogger) _inMemorySink.Dispose(); } - /// - /// Sets the log level for logger to either the level provided by the config or an public default. - /// - /// The LogConfig to look for the level setting in. - private static void SetupLogLevel(ILogConfig config) => _loggingLevelSwitch.MinimumLevel = config.LogLevel.MapToSerilogLogLevel(); - private static LoggerConfiguration ConfigureInMemoryLogSink(this LoggerConfiguration loggerConfiguration) { // formatter not needed since this will be pushed to other sinks for output. @@ -194,6 +187,10 @@ private static LoggerConfiguration ConfigureConsoleSink(this LoggerConfiguration /// The configuration for the appender. private static LoggerConfiguration ConfigureFileSink(this LoggerConfiguration loggerConfiguration, ILogConfig config) { + if (!config.Enabled) + { + return loggerConfiguration; + } string logFileName = config.GetFullLogFileName(); try @@ -214,6 +211,7 @@ private static LoggerConfiguration ConfigureFileSink(this LoggerConfiguration lo Log.Logger.Warning(ex, "Unexpected exception when configuring file sink."); // Fallback to the event log sink if we cannot setup a file logger. + NewRelic.Core.Logging.Log.FileLoggingHasFailed = true; Log.Logger.Warning("Falling back to EventLog sink."); loggerConfiguration.ConfigureEventLogSink(); } @@ -226,7 +224,7 @@ private static LoggerConfiguration ConfigureFileSink(this LoggerConfiguration lo /// private static LoggerConfiguration ConfigureAuditLogSink(this LoggerConfiguration loggerConfiguration, ILogConfig config) { - if (!config.IsAuditLogEnabled) return loggerConfiguration; + if (!config.IsAuditLogEnabled || !config.Enabled) return loggerConfiguration; string logFileName = config.GetFullLogFileName().Replace(".log", "_audit.log"); diff --git a/src/Agent/NewRelic/Agent/Core/Metrics/MetricNames.cs b/src/Agent/NewRelic/Agent/Core/Metrics/MetricNames.cs index b30a45436..8e9bba92b 100644 --- a/src/Agent/NewRelic/Agent/Core/Metrics/MetricNames.cs +++ b/src/Agent/NewRelic/Agent/Core/Metrics/MetricNames.cs @@ -833,6 +833,9 @@ public static string GetSupportabilityInstallType(string installType) // AppDomain caching disabled public const string SupportabilityAppDomainCachingDisabled = "Supportability/DotNET/AppDomainCaching/Disabled"; + public const string SupportabilityLoggingDisabled = "Supportability/DotNET/AgentLogging/Disabled"; + public const string SupportabilityLoggingFatalError = "Supportability/DotNET/AgentLogging/DisabledDueToError"; + #endregion Supportability #region Distributed Trace Metrics diff --git a/src/Agent/NewRelic/Agent/Extensions/NewRelic.Agent.Extensions/Configuration/IConfiguration.cs b/src/Agent/NewRelic/Agent/Extensions/NewRelic.Agent.Extensions/Configuration/IConfiguration.cs index bfb4f99c8..81410c12a 100644 --- a/src/Agent/NewRelic/Agent/Extensions/NewRelic.Agent.Extensions/Configuration/IConfiguration.cs +++ b/src/Agent/NewRelic/Agent/Extensions/NewRelic.Agent.Extensions/Configuration/IConfiguration.cs @@ -204,5 +204,6 @@ public interface IConfiguration TimeSpan SqlTracesHarvestCycle { get; } TimeSpan UpdateLoadedModulesCycle { get; } TimeSpan StackExchangeRedisCleanupCycle { get; } + bool LoggingEnabled { get; } } } diff --git a/src/NewRelic.Core/Logging/Log.cs b/src/NewRelic.Core/Logging/Log.cs index 8d75d5f32..e044bfc87 100644 --- a/src/NewRelic.Core/Logging/Log.cs +++ b/src/NewRelic.Core/Logging/Log.cs @@ -23,6 +23,8 @@ public static void Initialize(ILogger logger) Logger = logger; } + public static bool FileLoggingHasFailed { get; set; } + #region Error /// diff --git a/tests/Agent/UnitTests/Core.UnitTest/AgentHealth/AgentHealthReporterTests.cs b/tests/Agent/UnitTests/Core.UnitTest/AgentHealth/AgentHealthReporterTests.cs index dc5f2eb83..37e5e7077 100644 --- a/tests/Agent/UnitTests/Core.UnitTest/AgentHealth/AgentHealthReporterTests.cs +++ b/tests/Agent/UnitTests/Core.UnitTest/AgentHealth/AgentHealthReporterTests.cs @@ -9,6 +9,7 @@ using NewRelic.Agent.Core.Utilities; using NewRelic.Agent.Core.WireModels; using NewRelic.Agent.Extensions.Providers.Wrapper; +using NewRelic.Core.Logging; using NewRelic.SystemInterfaces; using NewRelic.Testing.Assertions; using NUnit.Framework; @@ -26,10 +27,12 @@ public class AgentHealthReporterTests private AgentHealthReporter _agentHealthReporter; private List _publishedMetrics; private ConfigurationAutoResponder _configurationAutoResponder; + private bool _enableLogging; [SetUp] public void SetUp() { + _enableLogging = true; var configuration = GetDefaultConfiguration(); _configurationAutoResponder = new ConfigurationAutoResponder(configuration); @@ -45,13 +48,14 @@ public void TearDown() _configurationAutoResponder.Dispose(); } - private static IConfiguration GetDefaultConfiguration() + private IConfiguration GetDefaultConfiguration() { var configuration = Mock.Create(); Mock.Arrange(() => configuration.LogEventCollectorEnabled).Returns(true); Mock.Arrange(() => configuration.LogDecoratorEnabled).Returns(true); Mock.Arrange(() => configuration.LogMetricsCollectorEnabled).Returns(true); Mock.Arrange(() => configuration.InfiniteTracingCompression).Returns(true); + Mock.Arrange(() => configuration.LoggingEnabled).Returns(() => _enableLogging); return configuration; } @@ -425,5 +429,39 @@ public void LoggingConfigurationSupportabilityMetricsOnlyReportedOnce() actualMetricNamesAndValues = _publishedMetrics.Select(x => new KeyValuePair(x.MetricName.Name, x.Data.Value0)); CollectionAssert.IsNotSubsetOf(expectedMetricNamesAndValues, actualMetricNamesAndValues); } + + [Test] + public void LoggingDisabledSupportabilityMetricsPresent() + { + _enableLogging = false; + Log.FileLoggingHasFailed = true; + _agentHealthReporter.CollectMetrics(); + + var expectedMetricNamesAndValues = new Dictionary + { + { "Supportability/DotNET/AgentLogging/Disabled", 1 }, + { "Supportability/DotNET/AgentLogging/DisabledDueToError", 1 }, + }; + var actualMetricNamesAndValues = _publishedMetrics.Select(x => new KeyValuePair(x.MetricName.Name, x.Data.Value0)); + + CollectionAssert.IsSubsetOf(expectedMetricNamesAndValues, actualMetricNamesAndValues); + + Log.FileLoggingHasFailed = false; + } + + [Test] + public void LoggingDisabledSupportabilityMetricsMissing() + { + Log.FileLoggingHasFailed = false; + _agentHealthReporter.CollectMetrics(); + + var expectedMetricNamesAndValues = new Dictionary + { + { "Supportability/DotNET/AgentLogging/Disabled", 1 }, + { "Supportability/DotNET/AgentLogging/DisabledDueToError", 1 }, + }; + Assert.False(_publishedMetrics.Any(x => x.MetricName.Name == "Supportability/DotNET/AgentLogging/Disabled")); + Assert.False(_publishedMetrics.Any(x => x.MetricName.Name == "Supportability/DotNET/AgentLogging/DisabledDueToError")); + } } } diff --git a/tests/Agent/UnitTests/Core.UnitTest/DataTransport/AgentSettingsTests.cs b/tests/Agent/UnitTests/Core.UnitTest/DataTransport/AgentSettingsTests.cs index ec4707f0a..6c85dfcc2 100644 --- a/tests/Agent/UnitTests/Core.UnitTest/DataTransport/AgentSettingsTests.cs +++ b/tests/Agent/UnitTests/Core.UnitTest/DataTransport/AgentSettingsTests.cs @@ -24,7 +24,7 @@ public void serializes_correctly() var json = JsonConvert.SerializeObject(agentSettings); - const string expectedJson = @"{""agent.name"":"".NET Agent"",""agent.run_id"":""AgentRunId"",""agent.enabled"":true,""agent.license_key.configured"":true,""agent.application_names"":[""name1"",""name2"",""name3""],""agent.application_names_source"":""ApplicationNameSource"",""agent.auto_start"":true,""browser_monitoring.application_id"":""BrowserMonitoringApplicationId"",""browser_monitoring.auto_instrument"":true,""browser_monitoring.beacon_address"":""BrowserMonitoringBeaconAddress"",""browser_monitoring.error_beacon_address"":""BrowserMonitoringErrorBeaconAddress"",""browser_monitoring.javascript_agent.populated"":true,""browser_monitoring.javascript_agent_file"":""BrowserMonitoringJavaScriptAgentFile"",""browser_monitoring.loader"":""BrowserMonitoringJavaScriptAgentLoaderType"",""browser_monitoring.loader_debug"":false,""browser_monitoring.monitoring_key.populated"":true,""browser_monitoring.use_ssl"":true,""security.policies_token"":""SecurityPoliciesToken"",""security.policies_token_exists"":true,""agent.allow_all_request_headers"":true,""agent.attributes_enabled"":true,""agent.can_use_attributes_includes"":true,""agent.can_use_attributes_includes_source"":""CanUseAttributesIncludesSource"",""agent.attributes_include"":[""include1"",""include2"",""include3""],""agent.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""agent.attributes_default_excludes"":[""defaultExclude1"",""defaultExclude2"",""defaultExclude3""],""transaction_events.attributes_enabled"":false,""transaction_events.attributes_include"":[""attributeInclude1"",""attributeInclude2"",""attributeInclude3""],""transaction_events.attributes_exclude"":[""attributeExclude1"",""attributeExclude2"",""attributeExclude3""],""transaction_trace.attributes_enabled"":true,""transaction_trace.attributes_include"":[""include1"",""include2"",""include3""],""transaction_trace.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""error_collector.attributes_enabled"":false,""error_collector.attributes_include"":[""include1"",""include2"",""include3""],""error_collector.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""browser_monitoring.attributes_enabled"":false,""browser_monitoring.attributes_include"":[""include1"",""include2"",""include3""],""browser_monitoring.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""custom_parameters.enabled"":false,""custom_parameters.source"":""CaptureCustomParametersSource"",""collector.host"":""CollectorHost"",""collector.port"":1234,""collector.send_data_on_exit"":true,""collector.send_data_on_exit_threshold"":4321.0,""collector.send_environment_info"":true,""collector.sync_startup"":true,""collector.timeout"":1234,""collector.max_payload_size_in_bytes"":4321,""agent.complete_transactions_on_thread"":true,""agent.compressed_content_encoding"":""CompressedContentEncoding"",""agent.configuration_version"":1234,""cross_application_tracer.cross_process_id"":""CrossApplicationTracingCrossProcessId"",""cross_application_tracer.enabled"":true,""distributed_tracing.enabled"":true,""span_events.enabled"":true,""span_events.harvest_cycle"":""00:20:34"",""span_events.attributes_enabled"":true,""span_events.attributes_include"":[""attributeInclude1"",""attributeInclude2"",""attributeInclude3""],""span_events.attributes_exclude"":[""attributeExclude1"",""attributeExclude2"",""attributeExclude3""],""infinite_tracing.trace_count_consumers"":1234,""infinite_tracing.trace_observer_host"":""InfiniteTracingTraceObserverHost"",""infinite_tracing.trace_observer_port"":""InfiniteTracingTraceObserverPort"",""infinite_tracing.trace_observer_ssl"":""InfiniteTracingTraceObserverSsl"",""infinite_tracing.dev.test_flaky"":1234.0,""infinite_tracing.dev.test_flaky_code"":4321,""infinite_tracing.dev.test_delay_ms"":1234,""infinite_tracing.spans_queue_size"":4321,""infinite_tracing.spans_partition_count"":1234,""infinite_tracing.spans_batch_size"":4321,""infinite_tracing.connect_timeout_ms"":1234,""infinite_tracing.send_data_timeout_ms"":4321,""infinite_tracing.exit_timeout_ms"":1234,""infinite_tracing.compression"":true,""agent.primary_application_id"":""PrimaryApplicationId"",""agent.trusted_account_key"":""TrustedAccountKey"",""agent.account_id"":""AccountId"",""datastore_tracer.name_reporting_enabled"":true,""datastore_tracer.query_parameters_enabled"":true,""error_collector.enabled"":true,""error_collector.capture_events_enabled"":true,""error_collector.max_samples_stored"":1234,""error_collector.harvest_cycle"":""00:20:34"",""error_collector.max_per_period"":4321,""error_collector.expected_classes"":[""expected1"",""expected2"",""expected3""],""error_collector.expected_messages"":{""first"":[""first1"",""first2""],""second"":[""second1"",""second2""]},""error_collector.expected_status_codes"":[""expectedError1"",""expectedError2"",""expectedError3""],""error_collector.expected_errors_config"":{""third"":[""third1"",""third2""],""fourth"":[""fourth1"",""fourth2""]},""error_collector.ignore_errors_config"":{""fifth"":[""fifth1"",""fifth2""],""sixth"":[""sixth1"",""sixth2""]},""error_collector.ignore_classes"":[""ignoreError1"",""ignoreError2"",""ignoreError3""],""error_collector.ignore_messages"":{""seven"":[""seven1"",""seven2""],""eight"":[""eight1"",""eight2""]},""agent.request_headers_map"":{""one"":""1"",""two"":""2""},""cross_application_tracer.encoding_key"":""EncodingKey"",""agent.entity_guid"":""EntityGuid"",""agent.high_security_mode_enabled"":true,""agent.custom_instrumentation_editor_enabled"":true,""agent.custom_instrumentation_editor_enabled_source"":""CustomInstrumentationEditorEnabledSource"",""agent.strip_exception_messages"":true,""agent.strip_exception_messages_source"":""StripExceptionMessagesSource"",""agent.instance_reporting_enabled"":true,""agent.instrumentation_logging_enabled"":true,""agent.labels"":""Labels"",""agent.metric_name_regex_rules"":[{""MatchExpression"":""match1"",""Replacement"":""replacement1"",""Ignore"":true,""EvaluationOrder"":1,""TerminateChain"":true,""EachSegment"":true,""ReplaceAll"":true,""MatchRegex"":{""Pattern"":""match1"",""Options"":3}},{""MatchExpression"":""match2"",""Replacement"":""replacement2"",""Ignore"":false,""EvaluationOrder"":2,""TerminateChain"":false,""EachSegment"":false,""ReplaceAll"":false,""MatchRegex"":{""Pattern"":""match2"",""Options"":3}}],""agent.new_relic_config_file_path"":""NewRelicConfigFilePath"",""agent.app_settings_config_file_path"":""AppSettingsConfigFilePath"",""proxy.host.configured"":true,""proxy.uri_path.configured"":true,""proxy.port.configured"":true,""proxy.username.configured"":true,""proxy.password.configured"":true,""proxy.domain.configured"":true,""agent.put_for_data_sent"":true,""slow_sql.enabled"":true,""transaction_tracer.explain_threshold"":""00:20:34"",""transaction_tracer.explain_enabled"":true,""transaction_tracer.max_explain_plans"":1234,""transaction_tracer.max_sql_statements"":4321,""transaction_tracer.sql_traces_per_period"":1234,""transaction_tracer.max_stack_trace_lines"":4321,""error_collector.ignore_status_codes"":[""ignore1"",""ignore2"",""ignore3""],""agent.thread_profiling_methods_to_ignore"":[""ignoreMethod1"",""ignoreMethod2"",""ignoreMethod3""],""custom_events.enabled"":true,""custom_events.enabled_source"":""CustomEventsEnabledSource"",""custom_events.attributes_enabled"":true,""custom_events.attributes_include"":[""attributeInclude1"",""attributeInclude2"",""attributeInclude3""],""custom_events.attributes_exclude"":[""attributeExclude1"",""attributeExclude2"",""attributeExclude3""],""custom_events.max_samples_stored"":1234,""custom_events.harvest_cycle"":""00:20:34"",""agent.disable_samplers"":true,""thread_profiler.enabled"":true,""transaction_events.enabled"":true,""transaction_events.max_samples_stored"":4321,""transaction_events.harvest_cycle"":""01:12:01"",""transaction_events.transactions_enabled"":true,""transaction_name.regex_rules"":[{""MatchExpression"":""matchTrans1"",""Replacement"":""replacementTrans1"",""Ignore"":true,""EvaluationOrder"":1,""TerminateChain"":true,""EachSegment"":true,""ReplaceAll"":true,""MatchRegex"":{""Pattern"":""matchTrans1"",""Options"":3}},{""MatchExpression"":""matchTrans2"",""Replacement"":""replacementTrans2"",""Ignore"":false,""EvaluationOrder"":2,""TerminateChain"":false,""EachSegment"":false,""ReplaceAll"":false,""MatchRegex"":{""Pattern"":""matchTrans2"",""Options"":3}}],""transaction_name.whitelist_rules"":{""nine"":[""nine1"",""nine2""],""ten"":[""ten1"",""ten2""]},""transaction_tracer.apdex_f"":""00:20:34"",""transaction_tracer.apdex_t"":""01:12:01"",""transaction_tracer.transaction_threshold"":""00:20:34"",""transaction_tracer.enabled"":true,""transaction_tracer.max_segments"":1234,""transaction_tracer.record_sql"":""TransactionTracerRecordSql"",""transaction_tracer.record_sql_source"":""TransactionTracerRecordSqlSource"",""transaction_tracer.max_stack_traces"":4321,""agent.trusted_account_ids"":[1,2,3],""agent.server_side_config_enabled"":true,""agent.ignore_server_side_config"":true,""agent.url_regex_rules"":[{""MatchExpression"":""matchUrl1"",""Replacement"":""replacementUrl1"",""Ignore"":true,""EvaluationOrder"":1,""TerminateChain"":true,""EachSegment"":true,""ReplaceAll"":true,""MatchRegex"":{""Pattern"":""matchUrl1"",""Options"":3}},{""MatchExpression"":""matchUrl2"",""Replacement"":""replacementUrl2"",""Ignore"":false,""EvaluationOrder"":2,""TerminateChain"":false,""EachSegment"":false,""ReplaceAll"":false,""MatchRegex"":{""Pattern"":""matchUrl2"",""Options"":3}}],""agent.request_path_exclusion_list"":[{""Pattern"":""asdf"",""Options"":0},{""Pattern"":""qwerty"",""Options"":1},{""Pattern"":""yolo"",""Options"":4}],""agent.web_transactions_apdex"":{""first"":1.0,""second"":2.0},""agent.wrapper_exception_limit"":1234,""utilization.detect_aws_enabled"":true,""utilization.detect_azure_enabled"":true,""utilization.detect_gcp_enabled"":true,""utilization.detect_pcf_enabled"":true,""utilization.detect_docker_enabled"":true,""utilization.detect_kubernetes_enabled"":true,""utilization.logical_processors"":22,""utilization.total_ram_mib"":33,""utilization.billing_host"":""UtilizationBillingHost"",""utilization.hostname"":""UtilizationHostName"",""utilization.full_hostname"":""UtilizationFullHostName"",""diagnostics.capture_agent_timing_enabled"":true,""diagnostics.capture_agent_timing_frequency"":1234,""agent.use_resource_based_naming_for_wcf_enabled"":true,""agent.event_listener_samplers_enabled"":true,""agent.sampling_target"":1234,""span_events.max_samples_stored"":4321,""agent.sampling_target_period_in_seconds"":1234,""agent.payload_success_metrics_enabled"":true,""agent.process_host_display_name"":""ProcessHostDisplayName"",""transaction_tracer.database_statement_cache_capacity"":1234,""agent.force_synchronous_timing_calculation_for_http_client"":true,""agent.exclude_new_relic_header"":true,""application_logging.enabled"":true,""application_logging.metrics.enabled"":true,""application_logging.forwarding.enabled"":true,""application_logging.forwarding.max_samples_stored"":1234,""application_logging.forwarding.log_level_denylist"":[""testlevel1, testlevel2""],""application_logging.harvest_cycle"":""00:20:34"",""application_logging.local_decorating.enabled"":true,""agent.app_domain_caching_disabled"":true,""agent.force_new_transaction_on_new_thread_enabled"":true,""agent.code_level_metrics_enabled"":true,""agent.app_settings"":{""hello"":""friend"",""we"":""made"",""it"":""to"",""the"":""end""},""application_logging.forwarding.context_data.enabled"":true,""application_logging.forwarding.context_data.include"":[""attr1"",""attr2""],""application_logging.forwarding.context_data.exclude"":[""attr1"",""attr2""],""metrics.harvest_cycle"":""00:01:00"",""transaction_traces.harvest_cycle"":""00:01:00"",""error_traces.harvest_cycle"":""00:01:00"",""get_agent_commands.cycle"":""00:01:00"",""default.harvest_cycle"":""00:01:00"",""sql_traces.harvest_cycle"":""00:01:00"",""update_loaded_modules.cycle"":""00:01:00"",""stackexchangeredis_cleanup.cycle"":""00:01:00""}"; + const string expectedJson = @"{""agent.name"":"".NET Agent"",""agent.run_id"":""AgentRunId"",""agent.enabled"":true,""agent.license_key.configured"":true,""agent.application_names"":[""name1"",""name2"",""name3""],""agent.application_names_source"":""ApplicationNameSource"",""agent.auto_start"":true,""browser_monitoring.application_id"":""BrowserMonitoringApplicationId"",""browser_monitoring.auto_instrument"":true,""browser_monitoring.beacon_address"":""BrowserMonitoringBeaconAddress"",""browser_monitoring.error_beacon_address"":""BrowserMonitoringErrorBeaconAddress"",""browser_monitoring.javascript_agent.populated"":true,""browser_monitoring.javascript_agent_file"":""BrowserMonitoringJavaScriptAgentFile"",""browser_monitoring.loader"":""BrowserMonitoringJavaScriptAgentLoaderType"",""browser_monitoring.loader_debug"":false,""browser_monitoring.monitoring_key.populated"":true,""browser_monitoring.use_ssl"":true,""security.policies_token"":""SecurityPoliciesToken"",""security.policies_token_exists"":true,""agent.allow_all_request_headers"":true,""agent.attributes_enabled"":true,""agent.can_use_attributes_includes"":true,""agent.can_use_attributes_includes_source"":""CanUseAttributesIncludesSource"",""agent.attributes_include"":[""include1"",""include2"",""include3""],""agent.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""agent.attributes_default_excludes"":[""defaultExclude1"",""defaultExclude2"",""defaultExclude3""],""transaction_events.attributes_enabled"":false,""transaction_events.attributes_include"":[""attributeInclude1"",""attributeInclude2"",""attributeInclude3""],""transaction_events.attributes_exclude"":[""attributeExclude1"",""attributeExclude2"",""attributeExclude3""],""transaction_trace.attributes_enabled"":true,""transaction_trace.attributes_include"":[""include1"",""include2"",""include3""],""transaction_trace.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""error_collector.attributes_enabled"":false,""error_collector.attributes_include"":[""include1"",""include2"",""include3""],""error_collector.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""browser_monitoring.attributes_enabled"":false,""browser_monitoring.attributes_include"":[""include1"",""include2"",""include3""],""browser_monitoring.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""custom_parameters.enabled"":false,""custom_parameters.source"":""CaptureCustomParametersSource"",""collector.host"":""CollectorHost"",""collector.port"":1234,""collector.send_data_on_exit"":true,""collector.send_data_on_exit_threshold"":4321.0,""collector.send_environment_info"":true,""collector.sync_startup"":true,""collector.timeout"":1234,""collector.max_payload_size_in_bytes"":4321,""agent.complete_transactions_on_thread"":true,""agent.compressed_content_encoding"":""CompressedContentEncoding"",""agent.configuration_version"":1234,""cross_application_tracer.cross_process_id"":""CrossApplicationTracingCrossProcessId"",""cross_application_tracer.enabled"":true,""distributed_tracing.enabled"":true,""span_events.enabled"":true,""span_events.harvest_cycle"":""00:20:34"",""span_events.attributes_enabled"":true,""span_events.attributes_include"":[""attributeInclude1"",""attributeInclude2"",""attributeInclude3""],""span_events.attributes_exclude"":[""attributeExclude1"",""attributeExclude2"",""attributeExclude3""],""infinite_tracing.trace_count_consumers"":1234,""infinite_tracing.trace_observer_host"":""InfiniteTracingTraceObserverHost"",""infinite_tracing.trace_observer_port"":""InfiniteTracingTraceObserverPort"",""infinite_tracing.trace_observer_ssl"":""InfiniteTracingTraceObserverSsl"",""infinite_tracing.dev.test_flaky"":1234.0,""infinite_tracing.dev.test_flaky_code"":4321,""infinite_tracing.dev.test_delay_ms"":1234,""infinite_tracing.spans_queue_size"":4321,""infinite_tracing.spans_partition_count"":1234,""infinite_tracing.spans_batch_size"":4321,""infinite_tracing.connect_timeout_ms"":1234,""infinite_tracing.send_data_timeout_ms"":4321,""infinite_tracing.exit_timeout_ms"":1234,""infinite_tracing.compression"":true,""agent.primary_application_id"":""PrimaryApplicationId"",""agent.trusted_account_key"":""TrustedAccountKey"",""agent.account_id"":""AccountId"",""datastore_tracer.name_reporting_enabled"":true,""datastore_tracer.query_parameters_enabled"":true,""error_collector.enabled"":true,""error_collector.capture_events_enabled"":true,""error_collector.max_samples_stored"":1234,""error_collector.harvest_cycle"":""00:20:34"",""error_collector.max_per_period"":4321,""error_collector.expected_classes"":[""expected1"",""expected2"",""expected3""],""error_collector.expected_messages"":{""first"":[""first1"",""first2""],""second"":[""second1"",""second2""]},""error_collector.expected_status_codes"":[""expectedError1"",""expectedError2"",""expectedError3""],""error_collector.expected_errors_config"":{""third"":[""third1"",""third2""],""fourth"":[""fourth1"",""fourth2""]},""error_collector.ignore_errors_config"":{""fifth"":[""fifth1"",""fifth2""],""sixth"":[""sixth1"",""sixth2""]},""error_collector.ignore_classes"":[""ignoreError1"",""ignoreError2"",""ignoreError3""],""error_collector.ignore_messages"":{""seven"":[""seven1"",""seven2""],""eight"":[""eight1"",""eight2""]},""agent.request_headers_map"":{""one"":""1"",""two"":""2""},""cross_application_tracer.encoding_key"":""EncodingKey"",""agent.entity_guid"":""EntityGuid"",""agent.high_security_mode_enabled"":true,""agent.custom_instrumentation_editor_enabled"":true,""agent.custom_instrumentation_editor_enabled_source"":""CustomInstrumentationEditorEnabledSource"",""agent.strip_exception_messages"":true,""agent.strip_exception_messages_source"":""StripExceptionMessagesSource"",""agent.instance_reporting_enabled"":true,""agent.instrumentation_logging_enabled"":true,""agent.labels"":""Labels"",""agent.metric_name_regex_rules"":[{""MatchExpression"":""match1"",""Replacement"":""replacement1"",""Ignore"":true,""EvaluationOrder"":1,""TerminateChain"":true,""EachSegment"":true,""ReplaceAll"":true,""MatchRegex"":{""Pattern"":""match1"",""Options"":3}},{""MatchExpression"":""match2"",""Replacement"":""replacement2"",""Ignore"":false,""EvaluationOrder"":2,""TerminateChain"":false,""EachSegment"":false,""ReplaceAll"":false,""MatchRegex"":{""Pattern"":""match2"",""Options"":3}}],""agent.new_relic_config_file_path"":""NewRelicConfigFilePath"",""agent.app_settings_config_file_path"":""AppSettingsConfigFilePath"",""proxy.host.configured"":true,""proxy.uri_path.configured"":true,""proxy.port.configured"":true,""proxy.username.configured"":true,""proxy.password.configured"":true,""proxy.domain.configured"":true,""agent.put_for_data_sent"":true,""slow_sql.enabled"":true,""transaction_tracer.explain_threshold"":""00:20:34"",""transaction_tracer.explain_enabled"":true,""transaction_tracer.max_explain_plans"":1234,""transaction_tracer.max_sql_statements"":4321,""transaction_tracer.sql_traces_per_period"":1234,""transaction_tracer.max_stack_trace_lines"":4321,""error_collector.ignore_status_codes"":[""ignore1"",""ignore2"",""ignore3""],""agent.thread_profiling_methods_to_ignore"":[""ignoreMethod1"",""ignoreMethod2"",""ignoreMethod3""],""custom_events.enabled"":true,""custom_events.enabled_source"":""CustomEventsEnabledSource"",""custom_events.attributes_enabled"":true,""custom_events.attributes_include"":[""attributeInclude1"",""attributeInclude2"",""attributeInclude3""],""custom_events.attributes_exclude"":[""attributeExclude1"",""attributeExclude2"",""attributeExclude3""],""custom_events.max_samples_stored"":1234,""custom_events.harvest_cycle"":""00:20:34"",""agent.disable_samplers"":true,""thread_profiler.enabled"":true,""transaction_events.enabled"":true,""transaction_events.max_samples_stored"":4321,""transaction_events.harvest_cycle"":""01:12:01"",""transaction_events.transactions_enabled"":true,""transaction_name.regex_rules"":[{""MatchExpression"":""matchTrans1"",""Replacement"":""replacementTrans1"",""Ignore"":true,""EvaluationOrder"":1,""TerminateChain"":true,""EachSegment"":true,""ReplaceAll"":true,""MatchRegex"":{""Pattern"":""matchTrans1"",""Options"":3}},{""MatchExpression"":""matchTrans2"",""Replacement"":""replacementTrans2"",""Ignore"":false,""EvaluationOrder"":2,""TerminateChain"":false,""EachSegment"":false,""ReplaceAll"":false,""MatchRegex"":{""Pattern"":""matchTrans2"",""Options"":3}}],""transaction_name.whitelist_rules"":{""nine"":[""nine1"",""nine2""],""ten"":[""ten1"",""ten2""]},""transaction_tracer.apdex_f"":""00:20:34"",""transaction_tracer.apdex_t"":""01:12:01"",""transaction_tracer.transaction_threshold"":""00:20:34"",""transaction_tracer.enabled"":true,""transaction_tracer.max_segments"":1234,""transaction_tracer.record_sql"":""TransactionTracerRecordSql"",""transaction_tracer.record_sql_source"":""TransactionTracerRecordSqlSource"",""transaction_tracer.max_stack_traces"":4321,""agent.trusted_account_ids"":[1,2,3],""agent.server_side_config_enabled"":true,""agent.ignore_server_side_config"":true,""agent.url_regex_rules"":[{""MatchExpression"":""matchUrl1"",""Replacement"":""replacementUrl1"",""Ignore"":true,""EvaluationOrder"":1,""TerminateChain"":true,""EachSegment"":true,""ReplaceAll"":true,""MatchRegex"":{""Pattern"":""matchUrl1"",""Options"":3}},{""MatchExpression"":""matchUrl2"",""Replacement"":""replacementUrl2"",""Ignore"":false,""EvaluationOrder"":2,""TerminateChain"":false,""EachSegment"":false,""ReplaceAll"":false,""MatchRegex"":{""Pattern"":""matchUrl2"",""Options"":3}}],""agent.request_path_exclusion_list"":[{""Pattern"":""asdf"",""Options"":0},{""Pattern"":""qwerty"",""Options"":1},{""Pattern"":""yolo"",""Options"":4}],""agent.web_transactions_apdex"":{""first"":1.0,""second"":2.0},""agent.wrapper_exception_limit"":1234,""utilization.detect_aws_enabled"":true,""utilization.detect_azure_enabled"":true,""utilization.detect_gcp_enabled"":true,""utilization.detect_pcf_enabled"":true,""utilization.detect_docker_enabled"":true,""utilization.detect_kubernetes_enabled"":true,""utilization.logical_processors"":22,""utilization.total_ram_mib"":33,""utilization.billing_host"":""UtilizationBillingHost"",""utilization.hostname"":""UtilizationHostName"",""utilization.full_hostname"":""UtilizationFullHostName"",""diagnostics.capture_agent_timing_enabled"":true,""diagnostics.capture_agent_timing_frequency"":1234,""agent.use_resource_based_naming_for_wcf_enabled"":true,""agent.event_listener_samplers_enabled"":true,""agent.sampling_target"":1234,""span_events.max_samples_stored"":4321,""agent.sampling_target_period_in_seconds"":1234,""agent.payload_success_metrics_enabled"":true,""agent.process_host_display_name"":""ProcessHostDisplayName"",""transaction_tracer.database_statement_cache_capacity"":1234,""agent.force_synchronous_timing_calculation_for_http_client"":true,""agent.exclude_new_relic_header"":true,""application_logging.enabled"":true,""application_logging.metrics.enabled"":true,""application_logging.forwarding.enabled"":true,""application_logging.forwarding.max_samples_stored"":1234,""application_logging.forwarding.log_level_denylist"":[""testlevel1, testlevel2""],""application_logging.harvest_cycle"":""00:20:34"",""application_logging.local_decorating.enabled"":true,""agent.app_domain_caching_disabled"":true,""agent.force_new_transaction_on_new_thread_enabled"":true,""agent.code_level_metrics_enabled"":true,""agent.app_settings"":{""hello"":""friend"",""we"":""made"",""it"":""to"",""the"":""end""},""application_logging.forwarding.context_data.enabled"":true,""application_logging.forwarding.context_data.include"":[""attr1"",""attr2""],""application_logging.forwarding.context_data.exclude"":[""attr1"",""attr2""],""metrics.harvest_cycle"":""00:01:00"",""transaction_traces.harvest_cycle"":""00:01:00"",""error_traces.harvest_cycle"":""00:01:00"",""get_agent_commands.cycle"":""00:01:00"",""default.harvest_cycle"":""00:01:00"",""sql_traces.harvest_cycle"":""00:01:00"",""update_loaded_modules.cycle"":""00:01:00"",""stackexchangeredis_cleanup.cycle"":""00:01:00"",""agent.logging_enabled"":true}"; // Confirm that JsonIgnored properties are present, but not serialized Assert.NotNull(agentSettings.AgentLicenseKey); diff --git a/tests/Agent/UnitTests/Core.UnitTest/DataTransport/ConnectModelTests.cs b/tests/Agent/UnitTests/Core.UnitTest/DataTransport/ConnectModelTests.cs index 9e543aa78..ea9e08d23 100644 --- a/tests/Agent/UnitTests/Core.UnitTest/DataTransport/ConnectModelTests.cs +++ b/tests/Agent/UnitTests/Core.UnitTest/DataTransport/ConnectModelTests.cs @@ -60,7 +60,7 @@ public void serializes_correctly() var json = JsonConvert.SerializeObject(connectModel); - const string expectedJson = @"{""pid"":1,""language"":""dotnet"",""display_host"":""customHostName"",""host"":""myHost"",""app_name"":[""name1"",""name2""],""agent_version"":""1.0"",""agent_version_timestamp"":0,""security_settings"":{""transaction_tracer"":{""record_sql"":""raw""}},""high_security"":true,""event_harvest_config"":{""harvest_limits"":{""analytic_event_data"":4321,""custom_event_data"":1234,""error_event_data"":1234,""span_event_data"":4321,""log_event_data"":1234}},""identifier"":""myIdentifier"",""labels"":[{""label_type"":""type1"",""label_value"":""value1""}],""settings"":{""agent.name"":"".NET Agent"",""agent.run_id"":""AgentRunId"",""agent.enabled"":true,""agent.license_key.configured"":true,""agent.application_names"":[""name1"",""name2"",""name3""],""agent.application_names_source"":""ApplicationNameSource"",""agent.auto_start"":true,""browser_monitoring.application_id"":""BrowserMonitoringApplicationId"",""browser_monitoring.auto_instrument"":true,""browser_monitoring.beacon_address"":""BrowserMonitoringBeaconAddress"",""browser_monitoring.error_beacon_address"":""BrowserMonitoringErrorBeaconAddress"",""browser_monitoring.javascript_agent.populated"":true,""browser_monitoring.javascript_agent_file"":""BrowserMonitoringJavaScriptAgentFile"",""browser_monitoring.loader"":""BrowserMonitoringJavaScriptAgentLoaderType"",""browser_monitoring.loader_debug"":false,""browser_monitoring.monitoring_key.populated"":true,""browser_monitoring.use_ssl"":true,""security.policies_token"":""SecurityPoliciesToken"",""security.policies_token_exists"":true,""agent.allow_all_request_headers"":true,""agent.attributes_enabled"":true,""agent.can_use_attributes_includes"":true,""agent.can_use_attributes_includes_source"":""CanUseAttributesIncludesSource"",""agent.attributes_include"":[""include1"",""include2"",""include3""],""agent.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""agent.attributes_default_excludes"":[""defaultExclude1"",""defaultExclude2"",""defaultExclude3""],""transaction_events.attributes_enabled"":false,""transaction_events.attributes_include"":[""attributeInclude1"",""attributeInclude2"",""attributeInclude3""],""transaction_events.attributes_exclude"":[""attributeExclude1"",""attributeExclude2"",""attributeExclude3""],""transaction_trace.attributes_enabled"":true,""transaction_trace.attributes_include"":[""include1"",""include2"",""include3""],""transaction_trace.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""error_collector.attributes_enabled"":false,""error_collector.attributes_include"":[""include1"",""include2"",""include3""],""error_collector.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""browser_monitoring.attributes_enabled"":false,""browser_monitoring.attributes_include"":[""include1"",""include2"",""include3""],""browser_monitoring.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""custom_parameters.enabled"":false,""custom_parameters.source"":""CaptureCustomParametersSource"",""collector.host"":""CollectorHost"",""collector.port"":1234,""collector.send_data_on_exit"":true,""collector.send_data_on_exit_threshold"":4321.0,""collector.send_environment_info"":true,""collector.sync_startup"":true,""collector.timeout"":1234,""collector.max_payload_size_in_bytes"":4321,""agent.complete_transactions_on_thread"":true,""agent.compressed_content_encoding"":""CompressedContentEncoding"",""agent.configuration_version"":1234,""cross_application_tracer.cross_process_id"":""CrossApplicationTracingCrossProcessId"",""cross_application_tracer.enabled"":true,""distributed_tracing.enabled"":true,""span_events.enabled"":true,""span_events.harvest_cycle"":""00:20:34"",""span_events.attributes_enabled"":true,""span_events.attributes_include"":[""attributeInclude1"",""attributeInclude2"",""attributeInclude3""],""span_events.attributes_exclude"":[""attributeExclude1"",""attributeExclude2"",""attributeExclude3""],""infinite_tracing.trace_count_consumers"":1234,""infinite_tracing.trace_observer_host"":""InfiniteTracingTraceObserverHost"",""infinite_tracing.trace_observer_port"":""InfiniteTracingTraceObserverPort"",""infinite_tracing.trace_observer_ssl"":""InfiniteTracingTraceObserverSsl"",""infinite_tracing.dev.test_flaky"":1234.0,""infinite_tracing.dev.test_flaky_code"":4321,""infinite_tracing.dev.test_delay_ms"":1234,""infinite_tracing.spans_queue_size"":4321,""infinite_tracing.spans_partition_count"":1234,""infinite_tracing.spans_batch_size"":4321,""infinite_tracing.connect_timeout_ms"":1234,""infinite_tracing.send_data_timeout_ms"":4321,""infinite_tracing.exit_timeout_ms"":1234,""infinite_tracing.compression"":true,""agent.primary_application_id"":""PrimaryApplicationId"",""agent.trusted_account_key"":""TrustedAccountKey"",""agent.account_id"":""AccountId"",""datastore_tracer.name_reporting_enabled"":true,""datastore_tracer.query_parameters_enabled"":true,""error_collector.enabled"":true,""error_collector.capture_events_enabled"":true,""error_collector.max_samples_stored"":1234,""error_collector.harvest_cycle"":""00:20:34"",""error_collector.max_per_period"":4321,""error_collector.expected_classes"":[""expected1"",""expected2"",""expected3""],""error_collector.expected_messages"":{""first"":[""first1"",""first2""],""second"":[""second1"",""second2""]},""error_collector.expected_status_codes"":[""expectedError1"",""expectedError2"",""expectedError3""],""error_collector.expected_errors_config"":{""third"":[""third1"",""third2""],""fourth"":[""fourth1"",""fourth2""]},""error_collector.ignore_errors_config"":{""fifth"":[""fifth1"",""fifth2""],""sixth"":[""sixth1"",""sixth2""]},""error_collector.ignore_classes"":[""ignoreError1"",""ignoreError2"",""ignoreError3""],""error_collector.ignore_messages"":{""seven"":[""seven1"",""seven2""],""eight"":[""eight1"",""eight2""]},""agent.request_headers_map"":{""one"":""1"",""two"":""2""},""cross_application_tracer.encoding_key"":""EncodingKey"",""agent.entity_guid"":""EntityGuid"",""agent.high_security_mode_enabled"":true,""agent.custom_instrumentation_editor_enabled"":true,""agent.custom_instrumentation_editor_enabled_source"":""CustomInstrumentationEditorEnabledSource"",""agent.strip_exception_messages"":true,""agent.strip_exception_messages_source"":""StripExceptionMessagesSource"",""agent.instance_reporting_enabled"":true,""agent.instrumentation_logging_enabled"":true,""agent.labels"":""Labels"",""agent.metric_name_regex_rules"":[{""MatchExpression"":""match1"",""Replacement"":""replacement1"",""Ignore"":true,""EvaluationOrder"":1,""TerminateChain"":true,""EachSegment"":true,""ReplaceAll"":true,""MatchRegex"":{""Pattern"":""match1"",""Options"":3}},{""MatchExpression"":""match2"",""Replacement"":""replacement2"",""Ignore"":false,""EvaluationOrder"":2,""TerminateChain"":false,""EachSegment"":false,""ReplaceAll"":false,""MatchRegex"":{""Pattern"":""match2"",""Options"":3}}],""agent.new_relic_config_file_path"":""NewRelicConfigFilePath"",""agent.app_settings_config_file_path"":""AppSettingsConfigFilePath"",""proxy.host.configured"":true,""proxy.uri_path.configured"":true,""proxy.port.configured"":true,""proxy.username.configured"":true,""proxy.password.configured"":true,""proxy.domain.configured"":true,""agent.put_for_data_sent"":true,""slow_sql.enabled"":true,""transaction_tracer.explain_threshold"":""00:20:34"",""transaction_tracer.explain_enabled"":true,""transaction_tracer.max_explain_plans"":1234,""transaction_tracer.max_sql_statements"":4321,""transaction_tracer.sql_traces_per_period"":1234,""transaction_tracer.max_stack_trace_lines"":4321,""error_collector.ignore_status_codes"":[""ignore1"",""ignore2"",""ignore3""],""agent.thread_profiling_methods_to_ignore"":[""ignoreMethod1"",""ignoreMethod2"",""ignoreMethod3""],""custom_events.enabled"":true,""custom_events.enabled_source"":""CustomEventsEnabledSource"",""custom_events.attributes_enabled"":true,""custom_events.attributes_include"":[""attributeInclude1"",""attributeInclude2"",""attributeInclude3""],""custom_events.attributes_exclude"":[""attributeExclude1"",""attributeExclude2"",""attributeExclude3""],""custom_events.max_samples_stored"":1234,""custom_events.harvest_cycle"":""00:20:34"",""agent.disable_samplers"":true,""thread_profiler.enabled"":true,""transaction_events.enabled"":true,""transaction_events.max_samples_stored"":4321,""transaction_events.harvest_cycle"":""01:12:01"",""transaction_events.transactions_enabled"":true,""transaction_name.regex_rules"":[{""MatchExpression"":""matchTrans1"",""Replacement"":""replacementTrans1"",""Ignore"":true,""EvaluationOrder"":1,""TerminateChain"":true,""EachSegment"":true,""ReplaceAll"":true,""MatchRegex"":{""Pattern"":""matchTrans1"",""Options"":3}},{""MatchExpression"":""matchTrans2"",""Replacement"":""replacementTrans2"",""Ignore"":false,""EvaluationOrder"":2,""TerminateChain"":false,""EachSegment"":false,""ReplaceAll"":false,""MatchRegex"":{""Pattern"":""matchTrans2"",""Options"":3}}],""transaction_name.whitelist_rules"":{""nine"":[""nine1"",""nine2""],""ten"":[""ten1"",""ten2""]},""transaction_tracer.apdex_f"":""00:20:34"",""transaction_tracer.apdex_t"":""01:12:01"",""transaction_tracer.transaction_threshold"":""00:20:34"",""transaction_tracer.enabled"":true,""transaction_tracer.max_segments"":1234,""transaction_tracer.record_sql"":""TransactionTracerRecordSql"",""transaction_tracer.record_sql_source"":""TransactionTracerRecordSqlSource"",""transaction_tracer.max_stack_traces"":4321,""agent.trusted_account_ids"":[1,2,3],""agent.server_side_config_enabled"":true,""agent.ignore_server_side_config"":true,""agent.url_regex_rules"":[{""MatchExpression"":""matchUrl1"",""Replacement"":""replacementUrl1"",""Ignore"":true,""EvaluationOrder"":1,""TerminateChain"":true,""EachSegment"":true,""ReplaceAll"":true,""MatchRegex"":{""Pattern"":""matchUrl1"",""Options"":3}},{""MatchExpression"":""matchUrl2"",""Replacement"":""replacementUrl2"",""Ignore"":false,""EvaluationOrder"":2,""TerminateChain"":false,""EachSegment"":false,""ReplaceAll"":false,""MatchRegex"":{""Pattern"":""matchUrl2"",""Options"":3}}],""agent.request_path_exclusion_list"":[{""Pattern"":""asdf"",""Options"":0},{""Pattern"":""qwerty"",""Options"":1},{""Pattern"":""yolo"",""Options"":4}],""agent.web_transactions_apdex"":{""first"":1.0,""second"":2.0},""agent.wrapper_exception_limit"":1234,""utilization.detect_aws_enabled"":true,""utilization.detect_azure_enabled"":true,""utilization.detect_gcp_enabled"":true,""utilization.detect_pcf_enabled"":true,""utilization.detect_docker_enabled"":true,""utilization.detect_kubernetes_enabled"":true,""utilization.logical_processors"":22,""utilization.total_ram_mib"":33,""utilization.billing_host"":""UtilizationBillingHost"",""utilization.hostname"":""UtilizationHostName"",""utilization.full_hostname"":""UtilizationFullHostName"",""diagnostics.capture_agent_timing_enabled"":true,""diagnostics.capture_agent_timing_frequency"":1234,""agent.use_resource_based_naming_for_wcf_enabled"":true,""agent.event_listener_samplers_enabled"":true,""agent.sampling_target"":1234,""span_events.max_samples_stored"":4321,""agent.sampling_target_period_in_seconds"":1234,""agent.payload_success_metrics_enabled"":true,""agent.process_host_display_name"":""ProcessHostDisplayName"",""transaction_tracer.database_statement_cache_capacity"":1234,""agent.force_synchronous_timing_calculation_for_http_client"":true,""agent.exclude_new_relic_header"":true,""application_logging.enabled"":true,""application_logging.metrics.enabled"":true,""application_logging.forwarding.enabled"":true,""application_logging.forwarding.max_samples_stored"":1234,""application_logging.forwarding.log_level_denylist"":[""testlevel1, testlevel2""],""application_logging.harvest_cycle"":""00:20:34"",""application_logging.local_decorating.enabled"":true,""agent.app_domain_caching_disabled"":true,""agent.force_new_transaction_on_new_thread_enabled"":true,""agent.code_level_metrics_enabled"":true,""agent.app_settings"":{""hello"":""friend"",""we"":""made"",""it"":""to"",""the"":""end""},""application_logging.forwarding.context_data.enabled"":true,""application_logging.forwarding.context_data.include"":[""attr1"",""attr2""],""application_logging.forwarding.context_data.exclude"":[""attr1"",""attr2""],""metrics.harvest_cycle"":""00:01:00"",""transaction_traces.harvest_cycle"":""00:01:00"",""error_traces.harvest_cycle"":""00:01:00"",""get_agent_commands.cycle"":""00:01:00"",""default.harvest_cycle"":""00:01:00"",""sql_traces.harvest_cycle"":""00:01:00"",""update_loaded_modules.cycle"":""00:01:00"",""stackexchangeredis_cleanup.cycle"":""00:01:00""},""metadata"":{""hello"":""there""},""utilization"":{""metadata_version"":5,""logical_processors"":2,""total_ram_mib"":0,""hostname"":""myHost2"",""full_hostname"":""myHost2.domain.com"",""ip_address"":[""1.2.3.4"",""5.6.7.8""],""config"":{""hostname"":""my-host"",""logical_processors"":1,""total_ram_mib"":2048},""vendors"":{""aws"":{""availabilityZone"":""myZone"",""instanceId"":""myInstanceId"",""instanceType"":""myInstanceType""},""azure"":{""location"":""myLocation"",""name"":""myName"",""vmId"":""myVmId"",""vmSize"":""myVmSize""},""gcp"":{""id"":""myId"",""machineType"":""myMachineType"",""name"":""myName"",""zone"":""myZone""},""pcf"":{""cf_instance_guid"":""myInstanceGuid"",""cf_instance_ip"":""myInstanceIp"",""memory_limit"":""myMemoryLimit""},""kubernetes"":{""kubernetes_service_host"":""10.96.0.1""}}},""security_policies"":{""record_sql"":{""enabled"":false},""attributes_include"":{""enabled"":true},""allow_raw_exception_messages"":{""enabled"":false},""custom_events"":{""enabled"":true},""custom_parameters"":{""enabled"":false},""custom_instrumentation_editor"":{""enabled"":true}}}"; + const string expectedJson = @"{""pid"":1,""language"":""dotnet"",""display_host"":""customHostName"",""host"":""myHost"",""app_name"":[""name1"",""name2""],""agent_version"":""1.0"",""agent_version_timestamp"":0,""security_settings"":{""transaction_tracer"":{""record_sql"":""raw""}},""high_security"":true,""event_harvest_config"":{""harvest_limits"":{""analytic_event_data"":4321,""custom_event_data"":1234,""error_event_data"":1234,""span_event_data"":4321,""log_event_data"":1234}},""identifier"":""myIdentifier"",""labels"":[{""label_type"":""type1"",""label_value"":""value1""}],""settings"":{""agent.name"":"".NET Agent"",""agent.run_id"":""AgentRunId"",""agent.enabled"":true,""agent.license_key.configured"":true,""agent.application_names"":[""name1"",""name2"",""name3""],""agent.application_names_source"":""ApplicationNameSource"",""agent.auto_start"":true,""browser_monitoring.application_id"":""BrowserMonitoringApplicationId"",""browser_monitoring.auto_instrument"":true,""browser_monitoring.beacon_address"":""BrowserMonitoringBeaconAddress"",""browser_monitoring.error_beacon_address"":""BrowserMonitoringErrorBeaconAddress"",""browser_monitoring.javascript_agent.populated"":true,""browser_monitoring.javascript_agent_file"":""BrowserMonitoringJavaScriptAgentFile"",""browser_monitoring.loader"":""BrowserMonitoringJavaScriptAgentLoaderType"",""browser_monitoring.loader_debug"":false,""browser_monitoring.monitoring_key.populated"":true,""browser_monitoring.use_ssl"":true,""security.policies_token"":""SecurityPoliciesToken"",""security.policies_token_exists"":true,""agent.allow_all_request_headers"":true,""agent.attributes_enabled"":true,""agent.can_use_attributes_includes"":true,""agent.can_use_attributes_includes_source"":""CanUseAttributesIncludesSource"",""agent.attributes_include"":[""include1"",""include2"",""include3""],""agent.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""agent.attributes_default_excludes"":[""defaultExclude1"",""defaultExclude2"",""defaultExclude3""],""transaction_events.attributes_enabled"":false,""transaction_events.attributes_include"":[""attributeInclude1"",""attributeInclude2"",""attributeInclude3""],""transaction_events.attributes_exclude"":[""attributeExclude1"",""attributeExclude2"",""attributeExclude3""],""transaction_trace.attributes_enabled"":true,""transaction_trace.attributes_include"":[""include1"",""include2"",""include3""],""transaction_trace.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""error_collector.attributes_enabled"":false,""error_collector.attributes_include"":[""include1"",""include2"",""include3""],""error_collector.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""browser_monitoring.attributes_enabled"":false,""browser_monitoring.attributes_include"":[""include1"",""include2"",""include3""],""browser_monitoring.attributes_exclude"":[""exclude1"",""exclude2"",""exclude3""],""custom_parameters.enabled"":false,""custom_parameters.source"":""CaptureCustomParametersSource"",""collector.host"":""CollectorHost"",""collector.port"":1234,""collector.send_data_on_exit"":true,""collector.send_data_on_exit_threshold"":4321.0,""collector.send_environment_info"":true,""collector.sync_startup"":true,""collector.timeout"":1234,""collector.max_payload_size_in_bytes"":4321,""agent.complete_transactions_on_thread"":true,""agent.compressed_content_encoding"":""CompressedContentEncoding"",""agent.configuration_version"":1234,""cross_application_tracer.cross_process_id"":""CrossApplicationTracingCrossProcessId"",""cross_application_tracer.enabled"":true,""distributed_tracing.enabled"":true,""span_events.enabled"":true,""span_events.harvest_cycle"":""00:20:34"",""span_events.attributes_enabled"":true,""span_events.attributes_include"":[""attributeInclude1"",""attributeInclude2"",""attributeInclude3""],""span_events.attributes_exclude"":[""attributeExclude1"",""attributeExclude2"",""attributeExclude3""],""infinite_tracing.trace_count_consumers"":1234,""infinite_tracing.trace_observer_host"":""InfiniteTracingTraceObserverHost"",""infinite_tracing.trace_observer_port"":""InfiniteTracingTraceObserverPort"",""infinite_tracing.trace_observer_ssl"":""InfiniteTracingTraceObserverSsl"",""infinite_tracing.dev.test_flaky"":1234.0,""infinite_tracing.dev.test_flaky_code"":4321,""infinite_tracing.dev.test_delay_ms"":1234,""infinite_tracing.spans_queue_size"":4321,""infinite_tracing.spans_partition_count"":1234,""infinite_tracing.spans_batch_size"":4321,""infinite_tracing.connect_timeout_ms"":1234,""infinite_tracing.send_data_timeout_ms"":4321,""infinite_tracing.exit_timeout_ms"":1234,""infinite_tracing.compression"":true,""agent.primary_application_id"":""PrimaryApplicationId"",""agent.trusted_account_key"":""TrustedAccountKey"",""agent.account_id"":""AccountId"",""datastore_tracer.name_reporting_enabled"":true,""datastore_tracer.query_parameters_enabled"":true,""error_collector.enabled"":true,""error_collector.capture_events_enabled"":true,""error_collector.max_samples_stored"":1234,""error_collector.harvest_cycle"":""00:20:34"",""error_collector.max_per_period"":4321,""error_collector.expected_classes"":[""expected1"",""expected2"",""expected3""],""error_collector.expected_messages"":{""first"":[""first1"",""first2""],""second"":[""second1"",""second2""]},""error_collector.expected_status_codes"":[""expectedError1"",""expectedError2"",""expectedError3""],""error_collector.expected_errors_config"":{""third"":[""third1"",""third2""],""fourth"":[""fourth1"",""fourth2""]},""error_collector.ignore_errors_config"":{""fifth"":[""fifth1"",""fifth2""],""sixth"":[""sixth1"",""sixth2""]},""error_collector.ignore_classes"":[""ignoreError1"",""ignoreError2"",""ignoreError3""],""error_collector.ignore_messages"":{""seven"":[""seven1"",""seven2""],""eight"":[""eight1"",""eight2""]},""agent.request_headers_map"":{""one"":""1"",""two"":""2""},""cross_application_tracer.encoding_key"":""EncodingKey"",""agent.entity_guid"":""EntityGuid"",""agent.high_security_mode_enabled"":true,""agent.custom_instrumentation_editor_enabled"":true,""agent.custom_instrumentation_editor_enabled_source"":""CustomInstrumentationEditorEnabledSource"",""agent.strip_exception_messages"":true,""agent.strip_exception_messages_source"":""StripExceptionMessagesSource"",""agent.instance_reporting_enabled"":true,""agent.instrumentation_logging_enabled"":true,""agent.labels"":""Labels"",""agent.metric_name_regex_rules"":[{""MatchExpression"":""match1"",""Replacement"":""replacement1"",""Ignore"":true,""EvaluationOrder"":1,""TerminateChain"":true,""EachSegment"":true,""ReplaceAll"":true,""MatchRegex"":{""Pattern"":""match1"",""Options"":3}},{""MatchExpression"":""match2"",""Replacement"":""replacement2"",""Ignore"":false,""EvaluationOrder"":2,""TerminateChain"":false,""EachSegment"":false,""ReplaceAll"":false,""MatchRegex"":{""Pattern"":""match2"",""Options"":3}}],""agent.new_relic_config_file_path"":""NewRelicConfigFilePath"",""agent.app_settings_config_file_path"":""AppSettingsConfigFilePath"",""proxy.host.configured"":true,""proxy.uri_path.configured"":true,""proxy.port.configured"":true,""proxy.username.configured"":true,""proxy.password.configured"":true,""proxy.domain.configured"":true,""agent.put_for_data_sent"":true,""slow_sql.enabled"":true,""transaction_tracer.explain_threshold"":""00:20:34"",""transaction_tracer.explain_enabled"":true,""transaction_tracer.max_explain_plans"":1234,""transaction_tracer.max_sql_statements"":4321,""transaction_tracer.sql_traces_per_period"":1234,""transaction_tracer.max_stack_trace_lines"":4321,""error_collector.ignore_status_codes"":[""ignore1"",""ignore2"",""ignore3""],""agent.thread_profiling_methods_to_ignore"":[""ignoreMethod1"",""ignoreMethod2"",""ignoreMethod3""],""custom_events.enabled"":true,""custom_events.enabled_source"":""CustomEventsEnabledSource"",""custom_events.attributes_enabled"":true,""custom_events.attributes_include"":[""attributeInclude1"",""attributeInclude2"",""attributeInclude3""],""custom_events.attributes_exclude"":[""attributeExclude1"",""attributeExclude2"",""attributeExclude3""],""custom_events.max_samples_stored"":1234,""custom_events.harvest_cycle"":""00:20:34"",""agent.disable_samplers"":true,""thread_profiler.enabled"":true,""transaction_events.enabled"":true,""transaction_events.max_samples_stored"":4321,""transaction_events.harvest_cycle"":""01:12:01"",""transaction_events.transactions_enabled"":true,""transaction_name.regex_rules"":[{""MatchExpression"":""matchTrans1"",""Replacement"":""replacementTrans1"",""Ignore"":true,""EvaluationOrder"":1,""TerminateChain"":true,""EachSegment"":true,""ReplaceAll"":true,""MatchRegex"":{""Pattern"":""matchTrans1"",""Options"":3}},{""MatchExpression"":""matchTrans2"",""Replacement"":""replacementTrans2"",""Ignore"":false,""EvaluationOrder"":2,""TerminateChain"":false,""EachSegment"":false,""ReplaceAll"":false,""MatchRegex"":{""Pattern"":""matchTrans2"",""Options"":3}}],""transaction_name.whitelist_rules"":{""nine"":[""nine1"",""nine2""],""ten"":[""ten1"",""ten2""]},""transaction_tracer.apdex_f"":""00:20:34"",""transaction_tracer.apdex_t"":""01:12:01"",""transaction_tracer.transaction_threshold"":""00:20:34"",""transaction_tracer.enabled"":true,""transaction_tracer.max_segments"":1234,""transaction_tracer.record_sql"":""TransactionTracerRecordSql"",""transaction_tracer.record_sql_source"":""TransactionTracerRecordSqlSource"",""transaction_tracer.max_stack_traces"":4321,""agent.trusted_account_ids"":[1,2,3],""agent.server_side_config_enabled"":true,""agent.ignore_server_side_config"":true,""agent.url_regex_rules"":[{""MatchExpression"":""matchUrl1"",""Replacement"":""replacementUrl1"",""Ignore"":true,""EvaluationOrder"":1,""TerminateChain"":true,""EachSegment"":true,""ReplaceAll"":true,""MatchRegex"":{""Pattern"":""matchUrl1"",""Options"":3}},{""MatchExpression"":""matchUrl2"",""Replacement"":""replacementUrl2"",""Ignore"":false,""EvaluationOrder"":2,""TerminateChain"":false,""EachSegment"":false,""ReplaceAll"":false,""MatchRegex"":{""Pattern"":""matchUrl2"",""Options"":3}}],""agent.request_path_exclusion_list"":[{""Pattern"":""asdf"",""Options"":0},{""Pattern"":""qwerty"",""Options"":1},{""Pattern"":""yolo"",""Options"":4}],""agent.web_transactions_apdex"":{""first"":1.0,""second"":2.0},""agent.wrapper_exception_limit"":1234,""utilization.detect_aws_enabled"":true,""utilization.detect_azure_enabled"":true,""utilization.detect_gcp_enabled"":true,""utilization.detect_pcf_enabled"":true,""utilization.detect_docker_enabled"":true,""utilization.detect_kubernetes_enabled"":true,""utilization.logical_processors"":22,""utilization.total_ram_mib"":33,""utilization.billing_host"":""UtilizationBillingHost"",""utilization.hostname"":""UtilizationHostName"",""utilization.full_hostname"":""UtilizationFullHostName"",""diagnostics.capture_agent_timing_enabled"":true,""diagnostics.capture_agent_timing_frequency"":1234,""agent.use_resource_based_naming_for_wcf_enabled"":true,""agent.event_listener_samplers_enabled"":true,""agent.sampling_target"":1234,""span_events.max_samples_stored"":4321,""agent.sampling_target_period_in_seconds"":1234,""agent.payload_success_metrics_enabled"":true,""agent.process_host_display_name"":""ProcessHostDisplayName"",""transaction_tracer.database_statement_cache_capacity"":1234,""agent.force_synchronous_timing_calculation_for_http_client"":true,""agent.exclude_new_relic_header"":true,""application_logging.enabled"":true,""application_logging.metrics.enabled"":true,""application_logging.forwarding.enabled"":true,""application_logging.forwarding.max_samples_stored"":1234,""application_logging.forwarding.log_level_denylist"":[""testlevel1, testlevel2""],""application_logging.harvest_cycle"":""00:20:34"",""application_logging.local_decorating.enabled"":true,""agent.app_domain_caching_disabled"":true,""agent.force_new_transaction_on_new_thread_enabled"":true,""agent.code_level_metrics_enabled"":true,""agent.app_settings"":{""hello"":""friend"",""we"":""made"",""it"":""to"",""the"":""end""},""application_logging.forwarding.context_data.enabled"":true,""application_logging.forwarding.context_data.include"":[""attr1"",""attr2""],""application_logging.forwarding.context_data.exclude"":[""attr1"",""attr2""],""metrics.harvest_cycle"":""00:01:00"",""transaction_traces.harvest_cycle"":""00:01:00"",""error_traces.harvest_cycle"":""00:01:00"",""get_agent_commands.cycle"":""00:01:00"",""default.harvest_cycle"":""00:01:00"",""sql_traces.harvest_cycle"":""00:01:00"",""update_loaded_modules.cycle"":""00:01:00"",""stackexchangeredis_cleanup.cycle"":""00:01:00"",""agent.logging_enabled"":true},""metadata"":{""hello"":""there""},""utilization"":{""metadata_version"":5,""logical_processors"":2,""total_ram_mib"":0,""hostname"":""myHost2"",""full_hostname"":""myHost2.domain.com"",""ip_address"":[""1.2.3.4"",""5.6.7.8""],""config"":{""hostname"":""my-host"",""logical_processors"":1,""total_ram_mib"":2048},""vendors"":{""aws"":{""availabilityZone"":""myZone"",""instanceId"":""myInstanceId"",""instanceType"":""myInstanceType""},""azure"":{""location"":""myLocation"",""name"":""myName"",""vmId"":""myVmId"",""vmSize"":""myVmSize""},""gcp"":{""id"":""myId"",""machineType"":""myMachineType"",""name"":""myName"",""zone"":""myZone""},""pcf"":{""cf_instance_guid"":""myInstanceGuid"",""cf_instance_ip"":""myInstanceIp"",""memory_limit"":""myMemoryLimit""},""kubernetes"":{""kubernetes_service_host"":""10.96.0.1""}}},""security_policies"":{""record_sql"":{""enabled"":false},""attributes_include"":{""enabled"":true},""allow_raw_exception_messages"":{""enabled"":false},""custom_events"":{""enabled"":true},""custom_parameters"":{""enabled"":false},""custom_instrumentation_editor"":{""enabled"":true}}}"; // Confirm that JsonIgnored properties are present, but not serialized Assert.NotNull(agentSettings.AgentLicenseKey); diff --git a/tests/Agent/UnitTests/Core.UnitTest/DataTransport/ExhaustiveTestConfiguration.cs b/tests/Agent/UnitTests/Core.UnitTest/DataTransport/ExhaustiveTestConfiguration.cs index b241ddc80..018e2ecd8 100644 --- a/tests/Agent/UnitTests/Core.UnitTest/DataTransport/ExhaustiveTestConfiguration.cs +++ b/tests/Agent/UnitTests/Core.UnitTest/DataTransport/ExhaustiveTestConfiguration.cs @@ -1,4 +1,4 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. +// Copyright 2020 New Relic, Inc. All rights reserved. // SPDX-License-Identifier: Apache-2.0 using System; @@ -455,5 +455,7 @@ public IReadOnlyDictionary GetAppSettings() { "the", "end" } }; } + + public bool LoggingEnabled => true; } } diff --git a/tests/Agent/UnitTests/Core.UnitTest/NewRelic.Agent.Core.FromLegacy/LoggerBootstrapperTest.cs b/tests/Agent/UnitTests/Core.UnitTest/NewRelic.Agent.Core.FromLegacy/LoggerBootstrapperTest.cs index 95dc4f1fd..270cb85f7 100644 --- a/tests/Agent/UnitTests/Core.UnitTest/NewRelic.Agent.Core.FromLegacy/LoggerBootstrapperTest.cs +++ b/tests/Agent/UnitTests/Core.UnitTest/NewRelic.Agent.Core.FromLegacy/LoggerBootstrapperTest.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using System.IO; using NewRelic.Testing.Assertions; +using System.Collections.Generic; namespace NewRelic.Agent.Core { @@ -14,6 +15,41 @@ namespace NewRelic.Agent.Core [TestFixture] public class LoggerBootstrapperTest { + private Func _originalGetEnvironmentVar; + private Dictionary _envVars = new Dictionary(); + + private void SetEnvironmentVar(string name, string value) + { + _envVars[name] = value; + } + + private void ClearEnvironmentVars() =>_envVars.Clear(); + + private string MockGetEnvironmentVar(string name) + { + if (_envVars.TryGetValue(name, out var value)) return value; + return null; + } + + [OneTimeSetUp] + public void OneTimeSetUp() + { + _originalGetEnvironmentVar = ConfigurationLoader.GetEnvironmentVar; + ConfigurationLoader.GetEnvironmentVar = MockGetEnvironmentVar; + } + + [OneTimeTearDown] + public void OneTimeTearDown() + { + ConfigurationLoader.GetEnvironmentVar = _originalGetEnvironmentVar; + } + + [SetUp] + public void Setup() + { + ClearEnvironmentVars(); + } + [Test] public static void No_log_levels_are_enabled_when_config_log_is_off() { @@ -111,6 +147,119 @@ public static void Config_IsConsoleEnabled_for_config_is_false_when_not_added_to Assert.IsFalse(config.Console); } + [Test] + public static void Fatal_exception_can_be_recorded() + { + Assert.IsFalse(Log.FileLoggingHasFailed); + Log.FileLoggingHasFailed = true; + Assert.IsTrue(Log.FileLoggingHasFailed); + } + + [Test] + public void test_ways_to_disable_logging() + { + ILogConfig config; + + config = GetLogConfig("debug"); + Assert.IsTrue(config.Enabled); + + config = LogConfigFixtureWithLogEnabled(false); + Assert.IsFalse(config.Enabled); + + SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "0"); + config = LogConfigFixtureWithLogEnabled(true); + Assert.IsFalse(config.Enabled); + + SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "false"); + config = LogConfigFixtureWithLogEnabled(true); + Assert.IsFalse(config.Enabled); + + SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "1"); + config = LogConfigFixtureWithLogEnabled(true); + Assert.IsTrue(config.Enabled); + + SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "true"); + config = LogConfigFixtureWithLogEnabled(true); + Assert.IsTrue(config.Enabled); + + SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "not a valid bool"); + config = LogConfigFixtureWithLogEnabled(true); + Assert.IsTrue(config.Enabled); + + SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "0"); + config = LogConfigFixtureWithLogEnabled(false); + Assert.IsFalse(config.Enabled); + + SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "false"); + config = LogConfigFixtureWithLogEnabled(false); + Assert.IsFalse(config.Enabled); + + SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "1"); + config = LogConfigFixtureWithLogEnabled(false); + Assert.IsTrue(config.Enabled); + + SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "true"); + config = LogConfigFixtureWithLogEnabled(false); + Assert.IsTrue(config.Enabled); + + SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "not a valid bool"); + config = LogConfigFixtureWithLogEnabled(false); + Assert.IsFalse(config.Enabled); + } + + [Test] + public void test_ways_to_enable_console_logging() + { + ILogConfig config; + + config = GetLogConfig("debug"); + Assert.IsFalse(config.Console); + + config = LogConfigFixtureWithConsoleEnabled(true); + Assert.IsTrue(config.Console); + + SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "0"); + config = LogConfigFixtureWithConsoleEnabled(true); + Assert.IsFalse(config.Console); + + SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "false"); + config = LogConfigFixtureWithConsoleEnabled(true); + Assert.IsFalse(config.Console); + + SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "1"); + config = LogConfigFixtureWithConsoleEnabled(true); + Assert.IsTrue(config.Console); + + SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "true"); + config = LogConfigFixtureWithConsoleEnabled(true); + Assert.IsTrue(config.Console); + + SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "not a valid bool"); + config = LogConfigFixtureWithConsoleEnabled(true); + Assert.IsTrue(config.Console); + + SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "0"); + config = LogConfigFixtureWithConsoleEnabled(false); + Assert.IsFalse(config.Console); + + SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "false"); + config = LogConfigFixtureWithConsoleEnabled(false); + Assert.IsFalse(config.Console); + + SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "1"); + config = LogConfigFixtureWithConsoleEnabled(false); + Assert.IsTrue(config.Console); + + SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "true"); + config = LogConfigFixtureWithConsoleEnabled(false); + Assert.IsTrue(config.Console); + + SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "not a valid bool"); + config = LogConfigFixtureWithConsoleEnabled(false); + Assert.IsFalse(config.Console); + } + + private static ILogConfig GetLogConfig(string logLevel) { var xml = string.Format( @@ -164,6 +313,43 @@ private static ILogConfig LogConfigFixtureWithConsoleLogEnabled(string logLevel) var xsdFile = Path.Combine(TestContext.CurrentContext.TestDirectory, "Configuration.xsd"); Func configSchemaSource = () => File.ReadAllText(xsdFile); + var configuration = ConfigurationLoader.InitializeFromXml(xml, configSchemaSource); + return configuration.LogConfig; + } + private static ILogConfig LogConfigFixtureWithLogEnabled(bool enabled) + { + var xml = string.Format( + "" + + " " + + " " + + " Test" + + " " + + " " + + "", + enabled.ToString().ToLower()); + + var xsdFile = Path.Combine(TestContext.CurrentContext.TestDirectory, "Configuration.xsd"); + Func configSchemaSource = () => File.ReadAllText(xsdFile); + + var configuration = ConfigurationLoader.InitializeFromXml(xml, configSchemaSource); + return configuration.LogConfig; + } + + private static ILogConfig LogConfigFixtureWithConsoleEnabled(bool enabled) + { + var xml = string.Format( + "" + + " " + + " " + + " Test" + + " " + + " " + + "", + enabled.ToString().ToLower()); + + var xsdFile = Path.Combine(TestContext.CurrentContext.TestDirectory, "Configuration.xsd"); + Func configSchemaSource = () => File.ReadAllText(xsdFile); + var configuration = ConfigurationLoader.InitializeFromXml(xml, configSchemaSource); return configuration.LogConfig; } From 33023fd3e30747b7d502436c6834c2e0aaaf209c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 16 Nov 2023 13:31:21 -0800 Subject: [PATCH 4/7] chore: Update Profiler NuGet Package Reference to v10.18.0.15. (#2077) Co-authored-by: nr-ahemsath --- src/Agent/NewRelic/Home/Home.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Agent/NewRelic/Home/Home.csproj b/src/Agent/NewRelic/Home/Home.csproj index cc871a146..392fff2f8 100644 --- a/src/Agent/NewRelic/Home/Home.csproj +++ b/src/Agent/NewRelic/Home/Home.csproj @@ -13,7 +13,7 @@ - + From a3e5a9dd79a3c766725d6e9472c8271d6da834dd Mon Sep 17 00:00:00 2001 From: Alex Hemsath <57361211+nr-ahemsath@users.noreply.github.com> Date: Thu, 16 Nov 2023 17:37:09 -0800 Subject: [PATCH 5/7] Add integration tests for file logging disabled and console logging enabled (#2076) * Checkpoint in order to switch branches * Refactored AgentLogFile Moved AgentLogFile to the fixtures instead of the applications * Shorten some names * Fix bug caused by Visual Studio autocorrect * WIP * Working tests for logging disabled * Working console logging tests * Fix nuget package warnings-as-errors * Fix GuidConfigurationTests EndsWith() fails if the profiler logs the version, e.g. New Relic .NET CoreCLR Agent v10.18.0.26. Use Contains() instead --- .../IntegrationTestHelpers/AgentLogBase.cs | 16 ++-- .../IntegrationTestHelpers/AgentLogFile.cs | 5 +- .../RemoteApplication.cs | 7 -- .../RemoteApplicationFixture.cs | 29 +++--- .../RemoteConsoleApplication.cs | 1 - .../IntegrationTestHelpers/Timing.cs | 4 - .../AgentLogs/ConsoleLoggingTests.cs | 90 +++++++++++++++++++ .../LogLevelAndDirectoryEnvironmentTests.cs | 6 +- .../AgentLogs/LoggingDisabledTests.cs | 89 ++++++++++++++++++ .../Configuration/GuidConfigurationTest.cs | 4 +- .../AspNetCoreDistTraceRequestChainTests.cs | 37 ++++---- .../HttpClientW3CTests.cs | 6 +- .../HttpClientW3CTestsNetCore.cs | 24 ++--- .../HttpWebRequestW3CTests.cs | 6 +- .../HttpWebRequestW3CTestsNetCore.cs | 20 ++--- .../RestSharpW3CTests.cs | 6 +- .../W3CInstrumentationTests/TraceIdTests.cs | 4 +- .../W3CInstrumentationTests/W3CTestBase.cs | 6 +- .../Owin/OwinCATChainTests.cs | 4 +- .../IntegrationTests/Owin/OwinDTChainTests.cs | 12 +-- .../AspNetCoreDistTraceRequestChainFixture.cs | 14 ++- .../MockNewRelicFixture.cs | 4 +- .../TracingChainFixture.cs | 9 +- .../IntegrationTests/WCF/WCFLogHelpers.cs | 4 +- tests/Directory.Build.props | 1 + 25 files changed, 294 insertions(+), 114 deletions(-) create mode 100644 tests/Agent/IntegrationTests/IntegrationTests/AgentLogs/ConsoleLoggingTests.cs create mode 100644 tests/Agent/IntegrationTests/IntegrationTests/AgentLogs/LoggingDisabledTests.cs diff --git a/tests/Agent/IntegrationTests/IntegrationTestHelpers/AgentLogBase.cs b/tests/Agent/IntegrationTests/IntegrationTestHelpers/AgentLogBase.cs index 63865711f..f03df34a4 100644 --- a/tests/Agent/IntegrationTests/IntegrationTestHelpers/AgentLogBase.cs +++ b/tests/Agent/IntegrationTests/IntegrationTestHelpers/AgentLogBase.cs @@ -6,15 +6,13 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Contracts; -using System.Dynamic; using System.Linq; using System.Text.RegularExpressions; using System.Threading; using NewRelic.Agent.IntegrationTestHelpers.Models; -using NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures; using Newtonsoft.Json; -using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; +using Xunit.Abstractions; namespace NewRelic.Agent.IntegrationTestHelpers { @@ -73,12 +71,12 @@ public abstract class AgentLogBase // Transactions (either with an ID or "noop") public const string TransactionLinePrefix = FinestLogLinePrefixRegex + @"Trx ([a-fA-F0-9]*|Noop): "; - public AgentLogBase(RemoteApplication remoteApplication) + public AgentLogBase(ITestOutputHelper testLogger) { - _remoteApplication = remoteApplication; + _testLogger = testLogger; } - private RemoteApplication _remoteApplication; + private ITestOutputHelper _testLogger; public abstract IEnumerable GetFileLines(); @@ -158,7 +156,7 @@ public IEnumerable WaitForLogLines(string regularExpression, TimeSpan? ti var timeout = timeoutOrZero ?? TimeSpan.Zero; - _remoteApplication.TestLogger?.WriteLine($"{Timestamp} WaitForLogLines Waiting for expression: {regularExpression}. Duration: {timeout.TotalSeconds} seconds. Minimum count: {minimumCount}"); + _testLogger?.WriteLine($"{Timestamp} WaitForLogLines Waiting for expression: {regularExpression}. Duration: {timeout.TotalSeconds} seconds. Minimum count: {minimumCount}"); var timeTaken = Stopwatch.StartNew(); do @@ -166,7 +164,7 @@ public IEnumerable WaitForLogLines(string regularExpression, TimeSpan? ti var matches = TryGetLogLines(regularExpression).ToList(); if (matches.Count >= minimumCount) { - _remoteApplication.TestLogger?.WriteLine($"{Timestamp} WaitForLogLines Matched expression: {regularExpression}."); + _testLogger?.WriteLine($"{Timestamp} WaitForLogLines Matched expression: {regularExpression}."); return matches; } @@ -174,7 +172,7 @@ public IEnumerable WaitForLogLines(string regularExpression, TimeSpan? ti } while (timeTaken.Elapsed < timeout); var message = $"{Timestamp} Log line did not appear a minimum of {minimumCount} times within {timeout.TotalSeconds} seconds. Expected line expression: {regularExpression}"; - _remoteApplication.TestLogger?.WriteLine(message); + _testLogger?.WriteLine(message); throw new Exception(message); } diff --git a/tests/Agent/IntegrationTests/IntegrationTestHelpers/AgentLogFile.cs b/tests/Agent/IntegrationTests/IntegrationTestHelpers/AgentLogFile.cs index 087d155a4..1a6f5faa9 100644 --- a/tests/Agent/IntegrationTests/IntegrationTestHelpers/AgentLogFile.cs +++ b/tests/Agent/IntegrationTests/IntegrationTestHelpers/AgentLogFile.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Threading; using NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures; +using Xunit.Abstractions; namespace NewRelic.Agent.IntegrationTestHelpers { @@ -20,8 +21,8 @@ public class AgentLogFile : AgentLogBase public bool Found => File.Exists(_filePath); - public AgentLogFile(string logDirectoryPath, RemoteApplication remoteApplication, string fileName = "", TimeSpan? timeoutOrZero = null, bool throwIfNotFound = true) - : base(remoteApplication) + public AgentLogFile(string logDirectoryPath, ITestOutputHelper testLogger, string fileName = "", TimeSpan? timeoutOrZero = null, bool throwIfNotFound = true) + : base(testLogger) { Contract.Assert(logDirectoryPath != null); diff --git a/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteApplication.cs b/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteApplication.cs index a3473aced..c6873d82e 100644 --- a/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteApplication.cs +++ b/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteApplication.cs @@ -131,9 +131,6 @@ public string DefaultLogFileDirectoryPath } } - - private string AgentLogFileName { get { return CommonUtils.GetAgentLogFileNameFromNewRelicConfig(DestinationNewRelicConfigFilePath); } } - #endregion #region Abstract/Virtual @@ -227,10 +224,6 @@ public string UniqueFolderName public string DestinationNewRelicExtensionsDirectoryPath { get { return Path.Combine(DestinationNewRelicHomeDirectoryPath, "extensions"); } } - private AgentLogFile _agentLogFile; - - public AgentLogFile AgentLog => _agentLogFile ?? (_agentLogFile = new AgentLogFile(DestinationNewRelicLogFileDirectoryPath, this, AgentLogFileName, Timing.TimeToWaitForLog)); - public ProfilerLogFile ProfilerLog { get { return new ProfilerLogFile(DefaultLogFileDirectoryPath, Timing.TimeToConnect); } } public bool CaptureStandardOutput { get; set; } = true; diff --git a/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteApplicationFixture.cs b/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteApplicationFixture.cs index 5ebef0eba..c4679a7ab 100644 --- a/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteApplicationFixture.cs +++ b/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteApplicationFixture.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Net; using System.Net.Http; using System.Threading; @@ -47,8 +46,14 @@ public void SetTestClassType(Type testClassType) public readonly RemoteApplication RemoteApplication; public string UniqueFolderName { get { return RemoteApplication.UniqueFolderName; } } + private string AgentLogFileName { get { return CommonUtils.GetAgentLogFileNameFromNewRelicConfig(DestinationNewRelicConfigFilePath); } } + + + private AgentLogFile _agentLogFile; + public bool AgentLogExpected { get; set; } = true; + + public AgentLogFile AgentLog => _agentLogFile ?? (_agentLogFile = new AgentLogFile(DestinationNewRelicLogFileDirectoryPath, TestLogger, AgentLogFileName, Timing.TimeToWaitForLog, AgentLogExpected)); - public AgentLogFile AgentLog { get { return RemoteApplication.AgentLog; } } public ProfilerLogFile ProfilerLog { get { return RemoteApplication.ProfilerLog; } } @@ -325,17 +330,19 @@ public virtual void Initialize() finally { - TestLogger?.WriteLine("===== Begin Agent log file ====="); - try + if (AgentLogExpected) { - TestLogger?.WriteLine(AgentLog.GetFullLogAsString()); - } - catch (Exception) - { - TestLogger?.WriteLine("No log file found."); + TestLogger?.WriteLine("===== Begin Agent log file ====="); + try + { + TestLogger?.WriteLine(AgentLog.GetFullLogAsString()); + } + catch (Exception) + { + TestLogger?.WriteLine("No log file found."); + } + TestLogger?.WriteLine("----- End of Agent log file -----"); } - TestLogger?.WriteLine("----- End of Agent log file -----"); - } } } diff --git a/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteConsoleApplication.cs b/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteConsoleApplication.cs index 8c5efd30d..421e42c09 100644 --- a/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteConsoleApplication.cs +++ b/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteConsoleApplication.cs @@ -3,7 +3,6 @@ using System; -using System.Collections.Generic; using System.Diagnostics; namespace NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures diff --git a/tests/Agent/IntegrationTests/IntegrationTestHelpers/Timing.cs b/tests/Agent/IntegrationTests/IntegrationTestHelpers/Timing.cs index 7422d0bd7..837d10a4d 100644 --- a/tests/Agent/IntegrationTests/IntegrationTestHelpers/Timing.cs +++ b/tests/Agent/IntegrationTests/IntegrationTestHelpers/Timing.cs @@ -11,11 +11,7 @@ public static class Timing public static readonly TimeSpan TimeToColdStart = TimeSpan.FromMinutes(5); public static readonly TimeSpan TimeToConnect = TimeSpan.FromSeconds(30); public static readonly TimeSpan TimeToWaitForLog = TimeSpan.FromMinutes(3); - public static readonly TimeSpan TimeToApm = TimeSpan.FromMinutes(7); public static readonly TimeSpan TimeBetweenHarvests = TimeSpan.FromMinutes(1); - public static readonly TimeSpan ApmCheckInterval = TimeSpan.FromSeconds(5); - // how long to keep pinging APM for data until we get expected results (this is after the metrics show up but are incorrect) - public static readonly TimeSpan ApmRetyTimeout = TimeSpan.FromMinutes(1); public static readonly TimeSpan TimeBetweenFileExistChecks = TimeSpan.FromSeconds(1); public static readonly TimeSpan RequestTimeout = TimeSpan.FromMinutes(1); public static readonly TimeSpan TimeToDockerComposeUp = TimeSpan.FromMinutes(5); diff --git a/tests/Agent/IntegrationTests/IntegrationTests/AgentLogs/ConsoleLoggingTests.cs b/tests/Agent/IntegrationTests/IntegrationTests/AgentLogs/ConsoleLoggingTests.cs new file mode 100644 index 000000000..e57f6023a --- /dev/null +++ b/tests/Agent/IntegrationTests/IntegrationTests/AgentLogs/ConsoleLoggingTests.cs @@ -0,0 +1,90 @@ +// Copyright 2020 New Relic, Inc. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +using System; +using NewRelic.Agent.IntegrationTestHelpers; +using NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures; +using Xunit; +using Xunit.Abstractions; + +namespace NewRelic.Agent.IntegrationTests.AgentLogs +{ + public abstract class ConsoleLoggingTestsBase : NewRelicIntegrationTest + where TFixture : ConsoleDynamicMethodFixture + { + private readonly TFixture _fixture; + + public ConsoleLoggingTestsBase(TFixture fixture, ITestOutputHelper output) : base(fixture) + { + _fixture = fixture; + _fixture.SetTimeout(TimeSpan.FromMinutes(1)); + _fixture.TestLogger = output; + + _fixture.AddCommand($"RootCommands InstrumentedMethodToStartAgent"); + _fixture.AddCommand($"RootCommands DelaySeconds 10"); + + _fixture.AddActions + ( + setupConfiguration: () => + { + var configModifier = new NewRelicConfigModifier(fixture.DestinationNewRelicConfigFilePath); + configModifier + .SetLogLevel("debug"); + + _fixture.RemoteApplication.SetAdditionalEnvironmentVariable("NEW_RELIC_LOG_CONSOLE", "true"); + + }, + exerciseApplication: () => + { + } + ); + + _fixture.Initialize(); + } + + [Fact] + public void ConsoleLogsExist() + { + var stdOut = _fixture.RemoteApplication.CapturedOutput.StandardOutput; + + Assert.Contains("Console logging enabled", stdOut); // A profiler log message + Assert.Contains("Log level set to DEBUG", stdOut); // An agent log message + } + } + + [NetFrameworkTest] + public class ConsoleLoggingFWLatestTests : ConsoleLoggingTestsBase + { + public ConsoleLoggingFWLatestTests(ConsoleDynamicMethodFixtureFWLatest fixture, ITestOutputHelper output) + : base(fixture, output) + { + } + } + + [NetFrameworkTest] + public class ConsoleLoggingFW462Tests : ConsoleLoggingTestsBase + { + public ConsoleLoggingFW462Tests(ConsoleDynamicMethodFixtureFW462 fixture, ITestOutputHelper output) + : base(fixture, output) + { + } + } + + [NetCoreTest] + public class ConsoleLoggingCoreLatestTests : ConsoleLoggingTestsBase + { + public ConsoleLoggingCoreLatestTests(ConsoleDynamicMethodFixtureCoreLatest fixture, ITestOutputHelper output) + : base(fixture, output) + { + } + } + + [NetCoreTest] + public class ConsoleLoggingCoreOldestTests : ConsoleLoggingTestsBase + { + public ConsoleLoggingCoreOldestTests(ConsoleDynamicMethodFixtureCoreOldest fixture, ITestOutputHelper output) + : base(fixture, output) + { + } + } +} diff --git a/tests/Agent/IntegrationTests/IntegrationTests/AgentLogs/LogLevelAndDirectoryEnvironmentTests.cs b/tests/Agent/IntegrationTests/IntegrationTests/AgentLogs/LogLevelAndDirectoryEnvironmentTests.cs index e7f30c5b3..9385d0d27 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/AgentLogs/LogLevelAndDirectoryEnvironmentTests.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/AgentLogs/LogLevelAndDirectoryEnvironmentTests.cs @@ -46,9 +46,9 @@ public LogLevelAndDirectoryEnvironmentTests(T fixture, ITestOutputHelper output) [Fact] public void AgentLog() { - var configLocation = new AgentLogFile(_configLogDirectory, _fixture.RemoteApplication, throwIfNotFound: false); - var generalEnvLocation = new AgentLogFile(_generalEnvLogDirectory, _fixture.RemoteApplication, throwIfNotFound: false); - var profilerEnvLocation = new AgentLogFile(_profilerEnvLogDirectory, _fixture.RemoteApplication, throwIfNotFound: false); + var configLocation = new AgentLogFile(_configLogDirectory, _fixture.TestLogger, throwIfNotFound: false); + var generalEnvLocation = new AgentLogFile(_generalEnvLogDirectory, _fixture.TestLogger, throwIfNotFound: false); + var profilerEnvLocation = new AgentLogFile(_profilerEnvLogDirectory, _fixture.TestLogger, throwIfNotFound: false); Assert.False(configLocation.Found); Assert.True(generalEnvLocation.Found); diff --git a/tests/Agent/IntegrationTests/IntegrationTests/AgentLogs/LoggingDisabledTests.cs b/tests/Agent/IntegrationTests/IntegrationTests/AgentLogs/LoggingDisabledTests.cs new file mode 100644 index 000000000..e0982d75c --- /dev/null +++ b/tests/Agent/IntegrationTests/IntegrationTests/AgentLogs/LoggingDisabledTests.cs @@ -0,0 +1,89 @@ +// Copyright 2020 New Relic, Inc. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +using System; +using System.IO; +using NewRelic.Agent.IntegrationTestHelpers; +using NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures; +using Xunit; +using Xunit.Abstractions; + +namespace NewRelic.Agent.IntegrationTests.AgentLogs +{ + public abstract class LoggingDisabledTestsBase : NewRelicIntegrationTest + where TFixture : ConsoleDynamicMethodFixture + { + private readonly TFixture _fixture; + + public LoggingDisabledTestsBase(TFixture fixture, ITestOutputHelper output) : base(fixture) + { + _fixture = fixture; + _fixture.SetTimeout(TimeSpan.FromMinutes(1)); + _fixture.TestLogger = output; + _fixture.AgentLogExpected = false; + + _fixture.AddCommand($"RootCommands InstrumentedMethodToStartAgent"); + _fixture.AddCommand($"RootCommands DelaySeconds 10"); + + _fixture.AddActions + ( + setupConfiguration: () => + { + var configModifier = new NewRelicConfigModifier(fixture.DestinationNewRelicConfigFilePath); + configModifier + .SetLogLevel("debug"); + + _fixture.RemoteApplication.SetAdditionalEnvironmentVariable("NEW_RELIC_LOG_ENABLED", "false"); + + }, + exerciseApplication: () => + { + } + ); + + _fixture.Initialize(); + } + + [Fact] + public void LogsDirShouldNotExist() + { + Assert.False(Directory.Exists(_fixture.RemoteApplication.DefaultLogFileDirectoryPath), "Logs are disabled so logs dir should not exist."); + } + } + + [NetFrameworkTest] + public class LoggingDisabledFWLatestTests : LoggingDisabledTestsBase + { + public LoggingDisabledFWLatestTests(ConsoleDynamicMethodFixtureFWLatest fixture, ITestOutputHelper output) + : base(fixture, output) + { + } + } + + [NetFrameworkTest] + public class LoggingDisabledFW462Tests : LoggingDisabledTestsBase + { + public LoggingDisabledFW462Tests(ConsoleDynamicMethodFixtureFW462 fixture, ITestOutputHelper output) + : base(fixture, output) + { + } + } + + [NetCoreTest] + public class LoggingDisabledCoreLatestTests : LoggingDisabledTestsBase + { + public LoggingDisabledCoreLatestTests(ConsoleDynamicMethodFixtureCoreLatest fixture, ITestOutputHelper output) + : base(fixture, output) + { + } + } + + [NetCoreTest] + public class LoggingDisabledCoreOldestTests : LoggingDisabledTestsBase + { + public LoggingDisabledCoreOldestTests(ConsoleDynamicMethodFixtureCoreOldest fixture, ITestOutputHelper output) + : base(fixture, output) + { + } + } +} diff --git a/tests/Agent/IntegrationTests/IntegrationTests/Configuration/GuidConfigurationTest.cs b/tests/Agent/IntegrationTests/IntegrationTests/Configuration/GuidConfigurationTest.cs index bf0dce51f..116056884 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/Configuration/GuidConfigurationTest.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/Configuration/GuidConfigurationTest.cs @@ -1,4 +1,4 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. +// Copyright 2020 New Relic, Inc. All rights reserved. // SPDX-License-Identifier: Apache-2.0 using System.Linq; @@ -49,7 +49,7 @@ public void Test() var match = IsCore ? CORE_LOG : FRAMEWORK_LOG; // Profiler should flag correctly regardless - Assert.True(_fixture.ProfilerLog.GetFileLines().Any(l => l.EndsWith(match)), + Assert.True(_fixture.ProfilerLog.GetFileLines().Any(l => l.Contains(match)), $"Expected '{match}' in Profiler, but was not found."); } } diff --git a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/AspNetCoreDistTraceRequestChainTests.cs b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/AspNetCoreDistTraceRequestChainTests.cs index f8c70e502..8c3957d73 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/AspNetCoreDistTraceRequestChainTests.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/AspNetCoreDistTraceRequestChainTests.cs @@ -7,7 +7,6 @@ using System.Linq; using NewRelic.Agent.IntegrationTestHelpers; using NewRelic.Agent.IntegrationTestHelpers.Models; -using NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures; using NewRelic.Agent.IntegrationTests.RemoteServiceFixtures; using NewRelic.Testing.Assertions; using Xunit; @@ -39,8 +38,8 @@ public AspNetCoreDistTraceRequestChainTests(AspNetCoreDistTraceRequestChainFixtu _fixture.ExecuteTraceRequestChain("CallNext", "CallNext", "CallEnd", null); _fixture.ExecuteTraceRequestChain("CallNext", "CallNext", "CallError", null); - _fixture.FirstCallApplication.AgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); - _fixture.SecondCallApplication.AgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); + _fixture.FirstCallAppAgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); + _fixture.SecondCallAppAgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); _fixture.AgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); } ); @@ -51,7 +50,7 @@ public AspNetCoreDistTraceRequestChainTests(AspNetCoreDistTraceRequestChainFixtu [Fact] public void VerifyFirstApplication() { - var metrics = _fixture.FirstCallApplication.AgentLog.GetMetrics().ToList(); + var metrics = _fixture.FirstCallAppAgentLog.GetMetrics().ToList(); Assert.NotNull(metrics); @@ -64,7 +63,7 @@ public void VerifyFirstApplication() Assertions.MetricsExist(FirstAppExpectedData.CallNextMetrics, metrics); - var transactionEvents = _fixture.FirstCallApplication.AgentLog.GetTransactionEvents().ToList(); + var transactionEvents = _fixture.FirstCallAppAgentLog.GetTransactionEvents().ToList(); Assert.Equal(ExpectedTransactionCount, transactionEvents.Count); @@ -81,7 +80,7 @@ void AssertFirstAppTransactionEvent(int eventIndex) ); } - var allSpanEvents = _fixture.FirstCallApplication.AgentLog.GetSpanEvents() + var allSpanEvents = _fixture.FirstCallAppAgentLog.GetSpanEvents() .OrderBy(s => s.IntrinsicAttributes["timestamp"]).ToList(); ValidateSpanEventAttributesForTransactionEvent(0); @@ -101,7 +100,7 @@ void ValidateSpanEventAttributesForTransactionEvent(int eventIndex) [Fact] public void VerifySecondApplication() { - var metrics = _fixture.SecondCallApplication.AgentLog.GetMetrics().ToList(); + var metrics = _fixture.SecondCallAppAgentLog.GetMetrics().ToList(); var accountId = _fixture.AgentLog.GetAccountId(); var secondAppExpectedData = new SecondAppExpectedData(accountId); @@ -116,7 +115,7 @@ public void VerifySecondApplication() Assertions.MetricsExist(SecondAppExpectedData.CallNextMetrics, metrics); - var transactionEvents = _fixture.SecondCallApplication.AgentLog.GetTransactionEvents() + var transactionEvents = _fixture.SecondCallAppAgentLog.GetTransactionEvents() .OrderBy(evt => evt.IntrinsicAttributes["timestamp"]) .ToList(); @@ -125,14 +124,14 @@ public void VerifySecondApplication() AssertSecondAppTransactionEvent(0); AssertSecondAppTransactionEvent(1); - var parentTransactionEvent = _fixture.FirstCallApplication.AgentLog.GetTransactionEvents() + var parentTransactionEvent = _fixture.FirstCallAppAgentLog.GetTransactionEvents() .OrderBy(evt => evt.IntrinsicAttributes["timestamp"]).ToList().First(); Assert.True(TraceIdsAreEqual(parentTransactionEvent, transactionEvents.First())); void AssertSecondAppTransactionEvent(int eventIndex) { - var expectedPersistedParentEventAttributes = GetExpectedTransactionAttributesFromPreviousApp(_fixture.FirstCallApplication, eventIndex); + var expectedPersistedParentEventAttributes = GetExpectedTransactionAttributesFromPreviousApp(_fixture.FirstCallAppAgentLog, eventIndex); var transactionEvent = transactionEvents[eventIndex]; NrAssert.Multiple( @@ -144,7 +143,7 @@ void AssertSecondAppTransactionEvent(int eventIndex) ); } - var allSpanEvents = _fixture.SecondCallApplication.AgentLog.GetSpanEvents() + var allSpanEvents = _fixture.SecondCallAppAgentLog.GetSpanEvents() .OrderBy(s => s.IntrinsicAttributes["timestamp"]).ToList(); ValidateSpanEventAttributesForTransactionEvent(0); @@ -154,7 +153,7 @@ void ValidateSpanEventAttributesForTransactionEvent(int eventIndex) { var transactionId = transactionEvents[eventIndex].IntrinsicAttributes["guid"].ToString(); var expectedTraceId = - _fixture.FirstCallApplication.AgentLog.GetTransactionEvents() + _fixture.FirstCallAppAgentLog.GetTransactionEvents() .OrderBy(e => e.IntrinsicAttributes["timestamp"]).ToList()[eventIndex] .IntrinsicAttributes["traceId"].ToString(); @@ -195,7 +194,7 @@ public void VerifyFinalApplication() AssertFinalAppTransactionEvent(0); AssertFinalAppTransactionEvent(1); - var parentTransactionEvent = _fixture.SecondCallApplication.AgentLog.GetTransactionEvents() + var parentTransactionEvent = _fixture.SecondCallAppAgentLog.GetTransactionEvents() .OrderBy(evt => evt.IntrinsicAttributes["timestamp"]) .ToList() .First(); @@ -204,8 +203,8 @@ public void VerifyFinalApplication() void AssertFinalAppTransactionEvent(int eventIndex) { - var expectedPersistedParentEventAttributes = GetExpectedTransactionAttributesFromPreviousApp(_fixture.SecondCallApplication, eventIndex); - var expectedAttributeValuesPayloadReceived = GetExpectedAttributeValuesPayloadReceived(_fixture.SecondCallApplication.AgentLog.GetAccountId()); + var expectedPersistedParentEventAttributes = GetExpectedTransactionAttributesFromPreviousApp(_fixture.SecondCallAppAgentLog, eventIndex); + var expectedAttributeValuesPayloadReceived = GetExpectedAttributeValuesPayloadReceived(_fixture.SecondCallAppAgentLog.GetAccountId()); var transactionEvent = transactionEvents[eventIndex]; try @@ -234,7 +233,7 @@ void ValidateSpanEventAttributesForTransactionEvent(int eventIndex) { var transactionId = transactionEvents[eventIndex].IntrinsicAttributes["guid"].ToString(); var expectedTraceId = - _fixture.FirstCallApplication.AgentLog.GetTransactionEvents() + _fixture.FirstCallAppAgentLog.GetTransactionEvents() .OrderBy(e => e.IntrinsicAttributes["timestamp"]).ToList()[eventIndex] .IntrinsicAttributes["traceId"].ToString(); @@ -247,10 +246,10 @@ void ValidateSpanEventAttributesForTransactionEvent(int eventIndex) #region Transaction Event Validation - private static Dictionary GetExpectedTransactionAttributesFromPreviousApp(RemoteApplication application, int index) + private static Dictionary GetExpectedTransactionAttributesFromPreviousApp(AgentLogFile agentLog, int index) { - var parentAccountId = application.AgentLog.GetAccountId(); - var transactionEvents = application.AgentLog.GetTransactionEvents() + var parentAccountId = agentLog.GetAccountId(); + var transactionEvents = agentLog.GetTransactionEvents() .OrderBy(evt => evt.IntrinsicAttributes["timestamp"]) .ToList(); diff --git a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpClientW3CTests.cs b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpClientW3CTests.cs index e47680496..7f95c419a 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpClientW3CTests.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpClientW3CTests.cs @@ -26,9 +26,9 @@ public HttpClientW3CTests(OwinTracingChainFixture fixture, ITestOutputHelper out { fixture.ExecuteTraceRequestChainHttpClient(Headers); - fixture.ReceiverApplication.AgentLog.WaitForLogLine(AgentLogFile.AnalyticsEventDataLogLineRegex, TimeSpan.FromMinutes(2)); - fixture.ReceiverApplication.AgentLog.WaitForLogLine(AgentLogFile.SpanEventDataLogLineRegex, TimeSpan.FromMinutes(2)); - fixture.ReceiverApplication.AgentLog.WaitForLogLine(AgentLogFile.MetricDataLogLineRegex, TimeSpan.FromMinutes(2)); + fixture.ReceiverAppAgentLog.WaitForLogLine(AgentLogFile.AnalyticsEventDataLogLineRegex, TimeSpan.FromMinutes(2)); + fixture.ReceiverAppAgentLog.WaitForLogLine(AgentLogFile.SpanEventDataLogLineRegex, TimeSpan.FromMinutes(2)); + fixture.ReceiverAppAgentLog.WaitForLogLine(AgentLogFile.MetricDataLogLineRegex, TimeSpan.FromMinutes(2)); } ); diff --git a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpClientW3CTestsNetCore.cs b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpClientW3CTestsNetCore.cs index 769815ea8..aa3d9e55d 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpClientW3CTestsNetCore.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpClientW3CTestsNetCore.cs @@ -46,8 +46,8 @@ public HttpClientW3CTestsNetCore(AspNetCoreDistTraceRequestChainFixture fixture, _fixture.ExecuteTraceRequestChain("CallNext", "CallNext", "CallEnd", headers); - _fixture.FirstCallApplication.AgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); - _fixture.SecondCallApplication.AgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); + _fixture.FirstCallAppAgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); + _fixture.SecondCallAppAgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); _fixture.AgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); } ); @@ -58,18 +58,18 @@ public HttpClientW3CTestsNetCore(AspNetCoreDistTraceRequestChainFixture fixture, [Fact] public void Test() { - var senderAppTxEvent = _fixture.FirstCallApplication.AgentLog.GetTransactionEvents().FirstOrDefault(); + var senderAppTxEvent = _fixture.FirstCallAppAgentLog.GetTransactionEvents().FirstOrDefault(); Assert.NotNull(senderAppTxEvent); - var receiverAppTxEvents = _fixture.SecondCallApplication.AgentLog.GetTransactionEvents().FirstOrDefault(); + var receiverAppTxEvents = _fixture.SecondCallAppAgentLog.GetTransactionEvents().FirstOrDefault(); Assert.NotNull(receiverAppTxEvents); - var lastCallAppTxEvents = _fixture.RemoteApplication.AgentLog.GetTransactionEvents().FirstOrDefault(); + var lastCallAppTxEvents = _fixture.AgentLog.GetTransactionEvents().FirstOrDefault(); Assert.NotNull(lastCallAppTxEvents); - var senderAppSpanEvents = _fixture.FirstCallApplication.AgentLog.GetSpanEvents(); - var receiverAppSpanEvents = _fixture.SecondCallApplication.AgentLog.GetSpanEvents(); - var lastCallAppSpanEvents = _fixture.RemoteApplication.AgentLog.GetSpanEvents(); + var senderAppSpanEvents = _fixture.FirstCallAppAgentLog.GetSpanEvents(); + var receiverAppSpanEvents = _fixture.SecondCallAppAgentLog.GetSpanEvents(); + var lastCallAppSpanEvents = _fixture.AgentLog.GetSpanEvents(); Assert.Equal(senderAppTxEvent.IntrinsicAttributes["guid"], receiverAppTxEvents.IntrinsicAttributes["parentId"]); Assert.Equal(receiverAppTxEvents.IntrinsicAttributes["guid"], lastCallAppTxEvents.IntrinsicAttributes["parentId"]); @@ -126,8 +126,8 @@ public void Test() new Assertions.ExpectedMetric { metricName = @"Supportability/TraceContext/TraceState/NoNrEntry", callCount = 1 } }; - var accountId = _fixture.SecondCallApplication.AgentLog.GetAccountId(); - var appId = _fixture.SecondCallApplication.AgentLog.GetApplicationId(); + var accountId = _fixture.SecondCallAppAgentLog.GetAccountId(); + var appId = _fixture.SecondCallAppAgentLog.GetApplicationId(); var receiverExpectedMetrics = new List { @@ -146,8 +146,8 @@ public void Test() }; - var senderActualMetrics = _fixture.FirstCallApplication.AgentLog.GetMetrics(); - var receiverActualMetrics = _fixture.SecondCallApplication.AgentLog.GetMetrics(); + var senderActualMetrics = _fixture.FirstCallAppAgentLog.GetMetrics(); + var receiverActualMetrics = _fixture.SecondCallAppAgentLog.GetMetrics(); NrAssert.Multiple( () => Assertions.MetricsExist(senderExpectedMetrics, senderActualMetrics), diff --git a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpWebRequestW3CTests.cs b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpWebRequestW3CTests.cs index 396d5b82c..70f08e882 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpWebRequestW3CTests.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpWebRequestW3CTests.cs @@ -25,9 +25,9 @@ public HttpWebRequestW3CTests(RemoteServiceFixtures.FrameworkTracingChainFixture { fixture.ExecuteTraceRequestChainHttpWebRequest(Headers); - fixture.ReceiverApplication.AgentLog.WaitForLogLine(AgentLogFile.AnalyticsEventDataLogLineRegex, TimeSpan.FromMinutes(2)); - fixture.ReceiverApplication.AgentLog.WaitForLogLine(AgentLogFile.SpanEventDataLogLineRegex, TimeSpan.FromMinutes(2)); - fixture.ReceiverApplication.AgentLog.WaitForLogLine(AgentLogFile.MetricDataLogLineRegex, TimeSpan.FromMinutes(2)); + fixture.ReceiverAppAgentLog.WaitForLogLine(AgentLogFile.AnalyticsEventDataLogLineRegex, TimeSpan.FromMinutes(2)); + fixture.ReceiverAppAgentLog.WaitForLogLine(AgentLogFile.SpanEventDataLogLineRegex, TimeSpan.FromMinutes(2)); + fixture.ReceiverAppAgentLog.WaitForLogLine(AgentLogFile.MetricDataLogLineRegex, TimeSpan.FromMinutes(2)); } ); diff --git a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpWebRequestW3CTestsNetCore.cs b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpWebRequestW3CTestsNetCore.cs index 23327b6e9..2aba08ef3 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpWebRequestW3CTestsNetCore.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/HttpWebRequestW3CTestsNetCore.cs @@ -45,8 +45,8 @@ public HttpWebRequestW3CTestsNetCore(AspNetCoreDistTraceRequestChainFixture fixt _fixture.ExecuteTraceRequestChain("WebRequestCallNext", "WebRequestCallNext", "CallEnd", headers); - _fixture.FirstCallApplication.AgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); - _fixture.SecondCallApplication.AgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); + _fixture.FirstCallAppAgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); + _fixture.SecondCallAppAgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); _fixture.AgentLog.WaitForLogLines(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromSeconds(15), ExpectedTransactionCount); } ); @@ -56,14 +56,14 @@ public HttpWebRequestW3CTestsNetCore(AspNetCoreDistTraceRequestChainFixture fixt [Fact] public void Test() { - var senderAppTxEvent = _fixture.FirstCallApplication.AgentLog.GetTransactionEvents().FirstOrDefault(); + var senderAppTxEvent = _fixture.FirstCallAppAgentLog.GetTransactionEvents().FirstOrDefault(); Assert.NotNull(senderAppTxEvent); - var receiverAppTxEvents = _fixture.SecondCallApplication.AgentLog.GetTransactionEvents().FirstOrDefault(); + var receiverAppTxEvents = _fixture.SecondCallAppAgentLog.GetTransactionEvents().FirstOrDefault(); Assert.NotNull(receiverAppTxEvents); - var senderAppSpanEvents = _fixture.FirstCallApplication.AgentLog.GetSpanEvents(); - var receiverAppSpanEvents = _fixture.SecondCallApplication.AgentLog.GetSpanEvents(); + var senderAppSpanEvents = _fixture.FirstCallAppAgentLog.GetSpanEvents(); + var receiverAppSpanEvents = _fixture.SecondCallAppAgentLog.GetSpanEvents(); Assert.Equal(senderAppTxEvent.IntrinsicAttributes["guid"], receiverAppTxEvents.IntrinsicAttributes["parentId"]); @@ -102,8 +102,8 @@ public void Test() new Assertions.ExpectedMetric { metricName = @"Supportability/TraceContext/TraceState/NoNrEntry", callCount = 1 } }; - var accountId = _fixture.SecondCallApplication.AgentLog.GetAccountId(); - var appId = _fixture.SecondCallApplication.AgentLog.GetApplicationId(); + var accountId = _fixture.SecondCallAppAgentLog.GetAccountId(); + var appId = _fixture.SecondCallAppAgentLog.GetApplicationId(); var receiverExpectedMetrics = new List { @@ -120,8 +120,8 @@ public void Test() new Assertions.ExpectedMetric { metricName = @"Supportability/TraceContext/TraceState/NoNrEntry", callCount = 1 } }; - var senderActualMetrics = _fixture.FirstCallApplication.AgentLog.GetMetrics(); - var receiverActualMetrics = _fixture.SecondCallApplication.AgentLog.GetMetrics(); + var senderActualMetrics = _fixture.FirstCallAppAgentLog.GetMetrics(); + var receiverActualMetrics = _fixture.SecondCallAppAgentLog.GetMetrics(); NrAssert.Multiple( () => Assertions.MetricsExist(senderExpectedMetrics, senderActualMetrics), diff --git a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/RestSharpW3CTests.cs b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/RestSharpW3CTests.cs index 69a1bd7c4..997b47bf4 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/RestSharpW3CTests.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/RestSharpW3CTests.cs @@ -25,9 +25,9 @@ public RestSharpW3CTests(RemoteServiceFixtures.FrameworkTracingChainFixture fixt { fixture.ExecuteTraceRequestChainRestSharp(Headers); - fixture.ReceiverApplication.AgentLog.WaitForLogLine(AgentLogFile.AnalyticsEventDataLogLineRegex, TimeSpan.FromMinutes(2)); - fixture.ReceiverApplication.AgentLog.WaitForLogLine(AgentLogFile.SpanEventDataLogLineRegex, TimeSpan.FromMinutes(2)); - fixture.ReceiverApplication.AgentLog.WaitForLogLine(AgentLogFile.MetricDataLogLineRegex, TimeSpan.FromMinutes(2)); + fixture.ReceiverAppAgentLog.WaitForLogLine(AgentLogFile.AnalyticsEventDataLogLineRegex, TimeSpan.FromMinutes(2)); + fixture.ReceiverAppAgentLog.WaitForLogLine(AgentLogFile.SpanEventDataLogLineRegex, TimeSpan.FromMinutes(2)); + fixture.ReceiverAppAgentLog.WaitForLogLine(AgentLogFile.MetricDataLogLineRegex, TimeSpan.FromMinutes(2)); } ); fixture.Initialize(); diff --git a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/TraceIdTests.cs b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/TraceIdTests.cs index 7be52c0d8..fa2787ebf 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/TraceIdTests.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/TraceIdTests.cs @@ -33,8 +33,8 @@ public TraceIdTests(AspNetCoreBasicWebApiApplicationFixture fixture, ITestOutput exerciseApplication: () => { _traceId = _fixture.GetTraceId(); - _fixture.RemoteApplication.AgentLog.WaitForLogLine(AgentLogFile.AnalyticsEventDataLogLineRegex, TimeSpan.FromMinutes(2)); - _fixture.RemoteApplication.AgentLog.WaitForLogLine(AgentLogFile.SpanEventDataLogLineRegex, TimeSpan.FromMinutes(2)); + _fixture.AgentLog.WaitForLogLine(AgentLogFile.AnalyticsEventDataLogLineRegex, TimeSpan.FromMinutes(2)); + _fixture.AgentLog.WaitForLogLine(AgentLogFile.SpanEventDataLogLineRegex, TimeSpan.FromMinutes(2)); } ); diff --git a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/W3CTestBase.cs b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/W3CTestBase.cs index bcd6cd14e..a266f2d55 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/W3CTestBase.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/W3CInstrumentationTests/W3CTestBase.cs @@ -50,19 +50,19 @@ public W3CTestBase(T fixture, ITestOutputHelper output) : base(fixture) protected TransactionEvent SenderAppTxEvent => _senderAppTxEvent ?? (_senderAppTxEvent = _fixture.AgentLog.GetTransactionEvents().FirstOrDefault()); private TransactionEvent _receiverAppTxEvent; - protected TransactionEvent ReceiverAppTxEvent => _receiverAppTxEvent ?? (_receiverAppTxEvent = _fixture.ReceiverApplication.AgentLog.GetTransactionEvents().FirstOrDefault()); + protected TransactionEvent ReceiverAppTxEvent => _receiverAppTxEvent ?? (_receiverAppTxEvent = _fixture.ReceiverAppAgentLog.GetTransactionEvents().FirstOrDefault()); private List _senderAppSpanEvents; protected List SenderAppSpanEvents => _senderAppSpanEvents ?? (_senderAppSpanEvents = _fixture.AgentLog.GetSpanEvents().ToList()); private SpanEvent[] _receiverAppSpanEvents; - protected SpanEvent[] ReceiverAppSpanEvents => _receiverAppSpanEvents ?? (_receiverAppSpanEvents = _fixture.ReceiverApplication.AgentLog.GetSpanEvents().ToArray()); + protected SpanEvent[] ReceiverAppSpanEvents => _receiverAppSpanEvents ?? (_receiverAppSpanEvents = _fixture.ReceiverAppAgentLog.GetSpanEvents().ToArray()); private Metric[] _senderActualMetrics; protected Metric[] SenderActualMetrics => _senderActualMetrics ?? (_senderActualMetrics = _fixture.AgentLog.GetMetrics().ToArray()); private Metric[] _receiverActualMetrics; - protected Metric[] ReceiverActualMetrics => _receiverActualMetrics ?? (_receiverActualMetrics = _fixture.ReceiverApplication.AgentLog.GetMetrics().ToArray()); + protected Metric[] ReceiverActualMetrics => _receiverActualMetrics ?? (_receiverActualMetrics = _fixture.ReceiverAppAgentLog.GetMetrics().ToArray()); [Fact] public void TransactionsAttributes() diff --git a/tests/Agent/IntegrationTests/IntegrationTests/Owin/OwinCATChainTests.cs b/tests/Agent/IntegrationTests/IntegrationTests/Owin/OwinCATChainTests.cs index c663d4050..499437718 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/Owin/OwinCATChainTests.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/Owin/OwinCATChainTests.cs @@ -40,7 +40,7 @@ public OwinCATChainTests(OwinTracingChainFixture fixture, ITestOutputHelper outp { _fixture.ExecuteTraceRequestChainHttpClient(); - _fixture.ReceiverApplication.AgentLog.WaitForLogLine(AgentLogFile.AnalyticsEventDataLogLineRegex, TimeSpan.FromMinutes(2)); + _fixture.AgentLog.WaitForLogLine(AgentLogFile.AnalyticsEventDataLogLineRegex, TimeSpan.FromMinutes(2)); } ); @@ -53,7 +53,7 @@ public void Test() var senderAppTxEvent = _fixture.AgentLog.GetTransactionEvents().FirstOrDefault(); Assert.NotNull(senderAppTxEvent); - var receiverAppTxEvent = _fixture.ReceiverApplication.AgentLog.GetTransactionEvents().FirstOrDefault(); + var receiverAppTxEvent = _fixture.ReceiverAppAgentLog.GetTransactionEvents().FirstOrDefault(); Assert.NotNull(receiverAppTxEvent); var expectedSenderAttributes = new List diff --git a/tests/Agent/IntegrationTests/IntegrationTests/Owin/OwinDTChainTests.cs b/tests/Agent/IntegrationTests/IntegrationTests/Owin/OwinDTChainTests.cs index 02d6355c9..5c43e78a1 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/Owin/OwinDTChainTests.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/Owin/OwinDTChainTests.cs @@ -41,8 +41,8 @@ public OwinDTChainTests(OwinTracingChainFixture fixture, ITestOutputHelper outpu { _fixture.ExecuteTraceRequestChainHttpClient(); - _fixture.ReceiverApplication.AgentLog.WaitForLogLine(AgentLogFile.AnalyticsEventDataLogLineRegex, TimeSpan.FromMinutes(1)); - _fixture.ReceiverApplication.AgentLog.WaitForLogLine(AgentLogFile.SpanEventDataLogLineRegex, TimeSpan.FromMinutes(1)); + _fixture.ReceiverAppAgentLog.WaitForLogLine(AgentLogFile.AnalyticsEventDataLogLineRegex, TimeSpan.FromMinutes(1)); + _fixture.ReceiverAppAgentLog.WaitForLogLine(AgentLogFile.SpanEventDataLogLineRegex, TimeSpan.FromMinutes(1)); } ); @@ -55,11 +55,11 @@ public void Test() var senderAppTxEvent = _fixture.AgentLog.GetTransactionEvents().FirstOrDefault(); Assert.NotNull(senderAppTxEvent); - var receiverAppTxEvent = _fixture.ReceiverApplication.AgentLog.GetTransactionEvents().FirstOrDefault(); + var receiverAppTxEvent = _fixture.ReceiverAppAgentLog.GetTransactionEvents().FirstOrDefault(); Assert.NotNull(receiverAppTxEvent); var senderAppSpanEvents = _fixture.AgentLog.GetSpanEvents(); - var receiverAppSpanEvents = _fixture.ReceiverApplication.AgentLog.GetSpanEvents(); + var receiverAppSpanEvents = _fixture.ReceiverAppAgentLog.GetSpanEvents(); var externalSpanEvent = senderAppSpanEvents.Where(@event => @event?.IntrinsicAttributes?["name"]?.ToString() == "External/localhost/Stream/GET") .FirstOrDefault(); @@ -113,14 +113,14 @@ public void Test() }; var senderActualMetrics = _fixture.AgentLog.GetMetrics(); - var receiverActualMetrics = _fixture.ReceiverApplication.AgentLog.GetMetrics(); + var receiverActualMetrics = _fixture.ReceiverAppAgentLog.GetMetrics(); NrAssert.Multiple( () => Assertions.MetricsExist(senderExpectedMetrics, senderActualMetrics), () => Assertions.MetricsExist(receiverExpectedMetrics, receiverActualMetrics) ); - var transportDurationMetric = _fixture.ReceiverApplication.AgentLog.GetMetricByName($"TransportDuration/App/{acctId}/{appId}/HTTP/all"); + var transportDurationMetric = _fixture.ReceiverAppAgentLog.GetMetricByName($"TransportDuration/App/{acctId}/{appId}/HTTP/all"); Assert.True(transportDurationMetric.Values.Total > 0); } } diff --git a/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AspNetCoreDistTraceRequestChainFixture.cs b/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AspNetCoreDistTraceRequestChainFixture.cs index 29dd1385a..adb0193ad 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AspNetCoreDistTraceRequestChainFixture.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AspNetCoreDistTraceRequestChainFixture.cs @@ -18,6 +18,12 @@ public class AspNetCoreDistTraceRequestChainFixture : RemoteApplicationFixture public RemoteService FirstCallApplication { get; set; } public RemoteService SecondCallApplication { get; set; } + private AgentLogFile _firstCallAppAgentLog; + private AgentLogFile _secondCallAppAgentLog; + + public AgentLogFile FirstCallAppAgentLog => _firstCallAppAgentLog ?? (_firstCallAppAgentLog = new AgentLogFile(FirstCallApplication.DefaultLogFileDirectoryPath, TestLogger, string.Empty, Timing.TimeToWaitForLog)); + public AgentLogFile SecondCallAppAgentLog => _secondCallAppAgentLog ?? (_secondCallAppAgentLog = new AgentLogFile(SecondCallApplication.DefaultLogFileDirectoryPath, TestLogger, string.Empty, Timing.TimeToWaitForLog)); + public AspNetCoreDistTraceRequestChainFixture() : base(new RemoteService(ApplicationDirectoryName, ExecutableName, "net7.0", ApplicationType.Bounded, true, true, true)) { @@ -82,18 +88,18 @@ public override void Initialize() { base.Initialize(); - WriteApplicationAgentLogToTestLogger(nameof(FirstCallApplication), FirstCallApplication); - WriteApplicationAgentLogToTestLogger(nameof(SecondCallApplication), SecondCallApplication); + WriteApplicationAgentLogToTestLogger(nameof(FirstCallApplication), FirstCallAppAgentLog); + WriteApplicationAgentLogToTestLogger(nameof(SecondCallApplication), SecondCallAppAgentLog); } - private void WriteApplicationAgentLogToTestLogger(string applicationName, RemoteService application) + private void WriteApplicationAgentLogToTestLogger(string applicationName, AgentLogFile agentLog) { TestLogger?.WriteLine(""); TestLogger?.WriteLine($"===== Begin {applicationName} log file ====="); try { - TestLogger?.WriteLine(application.AgentLog.GetFullLogAsString()); + TestLogger?.WriteLine(agentLog.GetFullLogAsString()); } catch (Exception) { diff --git a/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/MockNewRelicFixture.cs b/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/MockNewRelicFixture.cs index 10f69fb2f..64a3463e1 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/MockNewRelicFixture.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/MockNewRelicFixture.cs @@ -135,7 +135,7 @@ public override void Initialize() { base.Initialize(); - RemoteApplication.AgentLog.WaitForLogLine(AgentLogFile.ShutdownLogLineRegex, TimeSpan.FromMinutes(2)); + AgentLog.WaitForLogLine(AgentLogFile.ShutdownLogLineRegex, TimeSpan.FromMinutes(2)); MockNewRelicApplication.Shutdown(); MockNewRelicApplication.CapturedOutput?.WriteProcessOutputToLog("MockNewRelic application:"); } @@ -150,7 +150,7 @@ public override void Initialize() public override void ShutdownRemoteApplication() { base.ShutdownRemoteApplication(); - RemoteApplication.AgentLog.WaitForLogLine(AgentLogFile.ShutdownLogLineRegex, TimeSpan.FromMinutes(2)); + AgentLog.WaitForLogLine(AgentLogFile.ShutdownLogLineRegex, TimeSpan.FromMinutes(2)); MockNewRelicApplication.Shutdown(); } diff --git a/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/TracingChainFixture.cs b/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/TracingChainFixture.cs index 2f96915e7..6d7eb9760 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/TracingChainFixture.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/TracingChainFixture.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Headers; -using System.Threading.Tasks; using NewRelic.Agent.IntegrationTestHelpers; using NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures; @@ -17,8 +16,10 @@ public class TracingChainFixture : RemoteApplicationFixture private string _applicationDirectoryName; private string _executableName; private string _targetFramework; + private AgentLogFile _recieverAppAgentLog; public RemoteApplication ReceiverApplication { get; set; } + public AgentLogFile ReceiverAppAgentLog => _recieverAppAgentLog ?? (_recieverAppAgentLog = new AgentLogFile(ReceiverApplication.DefaultLogFileDirectoryPath, TestLogger, string.Empty, Timing.TimeToWaitForLog)); public RemoteWebApplication SenderApplication => (RemoteWebApplication)RemoteApplication; public TracingChainFixture(string ApplicationDirectoryName, string ExecutableName, string TargetFramework) : base(new RemoteService(ApplicationDirectoryName, ExecutableName, TargetFramework, ApplicationType.Bounded)) @@ -37,7 +38,7 @@ public override void Initialize() { base.Initialize(); - WriteApplicationAgentLogToTestLogger(nameof(ReceiverApplication), ReceiverApplication); + WriteApplicationAgentLogToTestLogger(nameof(ReceiverApplication), ReceiverAppAgentLog); } public override void ShutdownRemoteApplication() @@ -54,14 +55,14 @@ public override void Dispose() base.Dispose(); } - private void WriteApplicationAgentLogToTestLogger(string applicationName, RemoteApplication application) + private void WriteApplicationAgentLogToTestLogger(string applicationName, AgentLogFile agentLog) { TestLogger?.WriteLine(""); TestLogger?.WriteLine($"===== Begin {applicationName} log file ====="); try { - TestLogger?.WriteLine(application.AgentLog.GetFullLogAsString()); + TestLogger?.WriteLine(agentLog.GetFullLogAsString()); } catch (Exception) { diff --git a/tests/Agent/IntegrationTests/IntegrationTests/WCF/WCFLogHelpers.cs b/tests/Agent/IntegrationTests/IntegrationTests/WCF/WCFLogHelpers.cs index 32abde054..219e2a3c1 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/WCF/WCFLogHelpers.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/WCF/WCFLogHelpers.cs @@ -65,7 +65,7 @@ public AgentLogFile AgentLog_Client .Where(f => !f.Name.StartsWith("NewRelic.Profiler.", StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(f => f.Name.EndsWith("ConsoleMultiFunctionApplicationFW.log", StringComparison.OrdinalIgnoreCase)); - _agentLog_Client = new AgentLogFile(_fixture.DestinationNewRelicLogFileDirectoryPath, _fixture.RemoteApplication, logFile.Name); + _agentLog_Client = new AgentLogFile(_fixture.DestinationNewRelicLogFileDirectoryPath, _fixture.TestLogger, logFile.Name); } return _agentLog_Client; @@ -85,7 +85,7 @@ public AgentLogFile AgentLog_Service .Where(f => !f.Name.StartsWith("NewRelic.Profiler.", StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(f => !f.Name.EndsWith("ConsoleMultiFunctionApplicationFW.log", StringComparison.OrdinalIgnoreCase)); - _agentLog_Service = new AgentLogFile(_fixture.DestinationNewRelicLogFileDirectoryPath, _fixture.RemoteApplication, logFile.Name); + _agentLog_Service = new AgentLogFile(_fixture.DestinationNewRelicLogFileDirectoryPath, _fixture.TestLogger, logFile.Name); } return _agentLog_Service; diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props index 1f89c424d..198a9cd3e 100644 --- a/tests/Directory.Build.props +++ b/tests/Directory.Build.props @@ -4,5 +4,6 @@ true + false From a372fbae72c553442918bb64491d3c5b6b99db2f Mon Sep 17 00:00:00 2001 From: Marty Tippin <120425148+tippmar-nr@users.noreply.github.com> Date: Mon, 20 Nov 2023 10:02:07 -0600 Subject: [PATCH 6/7] Fix integration test build error --- .../DistributedTracing/AspNetCoreDistTraceRequestChainTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/AspNetCoreDistTraceRequestChainTests.cs b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/AspNetCoreDistTraceRequestChainTests.cs index 7dfca8cde..fa4b3c9e5 100644 --- a/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/AspNetCoreDistTraceRequestChainTests.cs +++ b/tests/Agent/IntegrationTests/IntegrationTests/DistributedTracing/AspNetCoreDistTraceRequestChainTests.cs @@ -7,6 +7,7 @@ using System.Linq; using NewRelic.Agent.IntegrationTestHelpers; using NewRelic.Agent.IntegrationTestHelpers.Models; +using NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures; using NewRelic.Agent.IntegrationTests.RemoteServiceFixtures; using NewRelic.Testing.Assertions; using Xunit; From 0a3c69a3be216f58c802814c73515c30d131fc06 Mon Sep 17 00:00:00 2001 From: Alex Hemsath Date: Mon, 20 Nov 2023 15:22:34 -0800 Subject: [PATCH 7/7] PR feedback --- .../LoggerBootstrapperTest.cs | 125 +++++------------- 1 file changed, 36 insertions(+), 89 deletions(-) diff --git a/tests/Agent/UnitTests/Core.UnitTest/NewRelic.Agent.Core.FromLegacy/LoggerBootstrapperTest.cs b/tests/Agent/UnitTests/Core.UnitTest/NewRelic.Agent.Core.FromLegacy/LoggerBootstrapperTest.cs index 270cb85f7..09449c219 100644 --- a/tests/Agent/UnitTests/Core.UnitTest/NewRelic.Agent.Core.FromLegacy/LoggerBootstrapperTest.cs +++ b/tests/Agent/UnitTests/Core.UnitTest/NewRelic.Agent.Core.FromLegacy/LoggerBootstrapperTest.cs @@ -156,107 +156,54 @@ public static void Fatal_exception_can_be_recorded() } [Test] - public void test_ways_to_disable_logging() + [TestCase(null, false, false)] + [TestCase("0", true, false)] + [TestCase("0", false, false)] + [TestCase("false", true, false)] + [TestCase("false", false, false)] + [TestCase("1", true, true)] + [TestCase("1", false, true)] + [TestCase("true", true, true)] + [TestCase("true", false, true)] + [TestCase("not a valid bool", true, true)] + [TestCase("not a valid bool", false, false)] + public void test_ways_to_disable_logging(string envVarValue, bool logsEnabledInConfig, bool expectedLogConfig) { ILogConfig config; - config = GetLogConfig("debug"); - Assert.IsTrue(config.Enabled); - - config = LogConfigFixtureWithLogEnabled(false); - Assert.IsFalse(config.Enabled); - - SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "0"); - config = LogConfigFixtureWithLogEnabled(true); - Assert.IsFalse(config.Enabled); - - SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "false"); - config = LogConfigFixtureWithLogEnabled(true); - Assert.IsFalse(config.Enabled); - - SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "1"); - config = LogConfigFixtureWithLogEnabled(true); - Assert.IsTrue(config.Enabled); - - SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "true"); - config = LogConfigFixtureWithLogEnabled(true); - Assert.IsTrue(config.Enabled); - - SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "not a valid bool"); - config = LogConfigFixtureWithLogEnabled(true); - Assert.IsTrue(config.Enabled); - - SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "0"); - config = LogConfigFixtureWithLogEnabled(false); - Assert.IsFalse(config.Enabled); - - SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "false"); - config = LogConfigFixtureWithLogEnabled(false); - Assert.IsFalse(config.Enabled); - - SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "1"); - config = LogConfigFixtureWithLogEnabled(false); - Assert.IsTrue(config.Enabled); - - SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "true"); - config = LogConfigFixtureWithLogEnabled(false); - Assert.IsTrue(config.Enabled); - - SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", "not a valid bool"); - config = LogConfigFixtureWithLogEnabled(false); - Assert.IsFalse(config.Enabled); + if (envVarValue != null) + { + SetEnvironmentVar("NEW_RELIC_LOG_ENABLED", envVarValue); + } + config = LogConfigFixtureWithLogEnabled(logsEnabledInConfig); + Assert.AreEqual(config.Enabled, expectedLogConfig); } [Test] - public void test_ways_to_enable_console_logging() + [TestCase(null, false, false)] + [TestCase("0", true, false)] + [TestCase("0", false, false)] + [TestCase("false", true, false)] + [TestCase("false", false, false)] + [TestCase("1", true, true)] + [TestCase("1", false, true)] + [TestCase("true", true, true)] + [TestCase("true", false, true)] + [TestCase("not a valid bool", true, true)] + [TestCase("not a valid bool", false, false)] + public void test_ways_to_enable_console_logging(string envVarValue, bool consoleLogEnabledInConfig, bool expectedConsoleLogConfig) { ILogConfig config; - config = GetLogConfig("debug"); - Assert.IsFalse(config.Console); - config = LogConfigFixtureWithConsoleEnabled(true); Assert.IsTrue(config.Console); - SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "0"); - config = LogConfigFixtureWithConsoleEnabled(true); - Assert.IsFalse(config.Console); - - SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "false"); - config = LogConfigFixtureWithConsoleEnabled(true); - Assert.IsFalse(config.Console); - - SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "1"); - config = LogConfigFixtureWithConsoleEnabled(true); - Assert.IsTrue(config.Console); - - SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "true"); - config = LogConfigFixtureWithConsoleEnabled(true); - Assert.IsTrue(config.Console); - - SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "not a valid bool"); - config = LogConfigFixtureWithConsoleEnabled(true); - Assert.IsTrue(config.Console); - - SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "0"); - config = LogConfigFixtureWithConsoleEnabled(false); - Assert.IsFalse(config.Console); - - SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "false"); - config = LogConfigFixtureWithConsoleEnabled(false); - Assert.IsFalse(config.Console); - - SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "1"); - config = LogConfigFixtureWithConsoleEnabled(false); - Assert.IsTrue(config.Console); - - SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "true"); - config = LogConfigFixtureWithConsoleEnabled(false); - Assert.IsTrue(config.Console); - - SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", "not a valid bool"); - config = LogConfigFixtureWithConsoleEnabled(false); - Assert.IsFalse(config.Console); + if (envVarValue != null) + { + SetEnvironmentVar("NEW_RELIC_LOG_CONSOLE", envVarValue); + } + config = LogConfigFixtureWithConsoleEnabled(consoleLogEnabledInConfig); + Assert.AreEqual(config.Console, expectedConsoleLogConfig); }