diff --git a/src/Agent/NewRelic/Agent/Core/Config/Configuration.cs b/src/Agent/NewRelic/Agent/Core/Config/Configuration.cs
index 8bd464b15b..8acea3728f 100644
--- a/src/Agent/NewRelic/Agent/Core/Config/Configuration.cs
+++ b/src/Agent/NewRelic/Agent/Core/Config/Configuration.cs
@@ -1539,6 +1539,8 @@ public partial class configurationInstrumentation
private bool logField;
+ private bool disableFileSystemWatcherField;
+
///
/// configurationInstrumentation class constructor
///
@@ -1547,6 +1549,7 @@ public configurationInstrumentation()
this.applicationsField = new List();
this.rulesField = new List();
this.logField = false;
+ this.disableFileSystemWatcherField = false;
}
[System.Xml.Serialization.XmlArrayItemAttribute("ignore", IsNullable=false)]
@@ -1589,6 +1592,20 @@ public bool log
}
}
+ [System.Xml.Serialization.XmlAttributeAttribute()]
+ [System.ComponentModel.DefaultValueAttribute(false)]
+ public bool disableFileSystemWatcher
+ {
+ get
+ {
+ return this.disableFileSystemWatcherField;
+ }
+ set
+ {
+ this.disableFileSystemWatcherField = value;
+ }
+ }
+
#region Clone method
///
/// Create a clone of this configurationInstrumentation object
diff --git a/src/Agent/NewRelic/Agent/Core/Config/Configuration.xsd b/src/Agent/NewRelic/Agent/Core/Config/Configuration.xsd
index cfbd1e6508..6baf646283 100644
--- a/src/Agent/NewRelic/Agent/Core/Config/Configuration.xsd
+++ b/src/Agent/NewRelic/Agent/Core/Config/Configuration.xsd
@@ -487,6 +487,14 @@
+
+
+
+ If disableFileSystemWatcher is set to true, then instrumentation XML file changes, additions, or deletions will not be detected and applied after the application has been started.
+
+
+
+
diff --git a/src/Agent/NewRelic/Agent/Core/Configuration/DefaultConfiguration.cs b/src/Agent/NewRelic/Agent/Core/Configuration/DefaultConfiguration.cs
index 1df9bb67a5..bdd4cec642 100644
--- a/src/Agent/NewRelic/Agent/Core/Configuration/DefaultConfiguration.cs
+++ b/src/Agent/NewRelic/Agent/Core/Configuration/DefaultConfiguration.cs
@@ -2058,6 +2058,14 @@ public IEnumerable> IgnoredInstrumentation
}
}
+ public bool DisableFileSystemWatcher
+ {
+ get
+ {
+ return EnvironmentOverrides(_localConfiguration.instrumentation.disableFileSystemWatcher, "NEW_RELIC_DISABLE_FILE_SYSTEM_WATCHER");
+ }
+ }
+
#region AI Monitoring
public bool AiMonitoringEnabled
diff --git a/src/Agent/NewRelic/Agent/Core/Configuration/ReportedConfiguration.cs b/src/Agent/NewRelic/Agent/Core/Configuration/ReportedConfiguration.cs
index 124738043b..032c84a196 100644
--- a/src/Agent/NewRelic/Agent/Core/Configuration/ReportedConfiguration.cs
+++ b/src/Agent/NewRelic/Agent/Core/Configuration/ReportedConfiguration.cs
@@ -662,6 +662,9 @@ public ReportedConfiguration(IConfiguration configuration)
[JsonProperty("agent.instrumentation.ignore")]
public IEnumerable> IgnoredInstrumentation => _configuration.IgnoredInstrumentation;
+ [JsonProperty("agent.disable_file_system_watcher")]
+ public bool DisableFileSystemWatcher => _configuration.DisableFileSystemWatcher;
+
[JsonProperty("agent.ai_monitoring.enabled")]
public bool AiMonitoringEnabled => _configuration.AiMonitoringEnabled;
diff --git a/src/Agent/NewRelic/Agent/Core/Instrumentation/InstrumentationWatcher.cs b/src/Agent/NewRelic/Agent/Core/Instrumentation/InstrumentationWatcher.cs
index 6825b17a42..cf17659c5f 100644
--- a/src/Agent/NewRelic/Agent/Core/Instrumentation/InstrumentationWatcher.cs
+++ b/src/Agent/NewRelic/Agent/Core/Instrumentation/InstrumentationWatcher.cs
@@ -1,6 +1,7 @@
// Copyright 2020 New Relic, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
+using NewRelic.Agent.Configuration;
using NewRelic.Agent.Core.Utilities;
using NewRelic.Agent.Core.Wrapper;
using NewRelic.Core.Logging;
@@ -16,18 +17,26 @@ public class InstrumentationWatcher : IDisposable
private readonly IInstrumentationService _instrumentationService;
private readonly IWrapperService _wrapperService;
+ private readonly IConfigurationService _configurationService;
private List _fileWatchers;
private SignalableAction _action;
- public InstrumentationWatcher(IWrapperService wrapperService, IInstrumentationService instrumentationService)
+ public InstrumentationWatcher(IWrapperService wrapperService, IInstrumentationService instrumentationService, IConfigurationService configurationService)
{
_wrapperService = wrapperService;
_instrumentationService = instrumentationService;
+ _configurationService = configurationService;
}
public void Start()
{
+ if (_configurationService.Configuration.DisableFileSystemWatcher)
+ {
+ Log.Debug("Live instrumentation updates due to instrumentation file changes will not be applied because they have been disabled by local configuration.");
+ return;
+ }
+
if (AgentInstallConfiguration.HomeExtensionsDirectory == null)
{
Log.Warn("Live instrumentation updates due to instrumentation file changes will not be applied because HomeExtensionsDirectory is null.");
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 73f7653a35..62f2f9723e 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
@@ -212,7 +212,7 @@ public interface IConfiguration
bool LoggingEnabled { get; }
string LoggingLevel { get; }
IEnumerable> IgnoredInstrumentation { get; }
-
+ bool DisableFileSystemWatcher { get; }
bool AiMonitoringEnabled { get; }
bool AiMonitoringStreamingEnabled { get; }
bool AiMonitoringRecordContentEnabled { get; }
diff --git a/tests/Agent/IntegrationTests/IntegrationTestHelpers/NewRelicConfigModifier.cs b/tests/Agent/IntegrationTests/IntegrationTestHelpers/NewRelicConfigModifier.cs
index a73363f0c7..ced7d0d667 100644
--- a/tests/Agent/IntegrationTests/IntegrationTestHelpers/NewRelicConfigModifier.cs
+++ b/tests/Agent/IntegrationTests/IntegrationTestHelpers/NewRelicConfigModifier.cs
@@ -497,5 +497,11 @@ public void SetDebugStartupDelaySeconds(int delaySeconds)
CommonUtils.ModifyOrCreateXmlAttributeInNewRelicConfig(_configFilePath, new[] { "configuration", },
"debugStartupDelaySeconds", delaySeconds.ToString());
}
+
+ public NewRelicConfigModifier SetDisableFileSystemWatcher(bool enabled = true)
+ {
+ CommonUtils.ModifyOrCreateXmlAttributeInNewRelicConfig(_configFilePath, new[] { "configuration", "instrumentation" }, "disableFileSystemWatcher", enabled.ToString().ToLower());
+ return this;
+ }
}
}
diff --git a/tests/Agent/IntegrationTests/IntegrationTests/ReJit/NetCore/RejitAddFile.cs b/tests/Agent/IntegrationTests/IntegrationTests/ReJit/NetCore/RejitAddFile.cs
index 11a38fc6c6..d76b184cfc 100644
--- a/tests/Agent/IntegrationTests/IntegrationTests/ReJit/NetCore/RejitAddFile.cs
+++ b/tests/Agent/IntegrationTests/IntegrationTests/ReJit/NetCore/RejitAddFile.cs
@@ -25,10 +25,12 @@ public abstract class RejitAddFileBase : NewRelicIntegrationTest
{
@@ -61,20 +64,29 @@ public void Test()
{
//transactions
new Assertions.ExpectedMetric { metricName = @"WebTransaction/MVC/Home/Index", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = @"WebTransaction/Custom/MyCustomAddMetricName", callCount = 1 },
new Assertions.ExpectedMetric { metricName = @"WebTransaction/MVC/Rejit/GetAddFile", callCount = 1 },
// Unscoped
new Assertions.ExpectedMetric { metricName = @"DotNet/HomeController/Index", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = @"Custom/MyCustomAddMetricName", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = @"DotNet/RejitController/GetAddFile", callCount = 2 },
// Scoped
new Assertions.ExpectedMetric { metricName = @"DotNet/HomeController/Index", metricScope = "WebTransaction/MVC/Home/Index", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = @"Custom/MyCustomAddMetricName", metricScope = "WebTransaction/Custom/MyCustomAddMetricName", callCount = 1 },
new Assertions.ExpectedMetric { metricName = @"DotNet/RejitController/GetAddFile", metricScope = "WebTransaction/MVC/Rejit/GetAddFile", callCount = 1 }
};
+ // Id file system watcher is disabled, these won't exist.
+ if (_disableFileSystemWatcher)
+ {
+ expectedMetrics.Add(new Assertions.ExpectedMetric { metricName = @"DotNet/RejitController/GetAddFile", callCount = 1 });
+ }
+ else
+ {
+ expectedMetrics.Add(new Assertions.ExpectedMetric { metricName = @"WebTransaction/Custom/MyCustomAddMetricName", callCount = 1 });
+ expectedMetrics.Add(new Assertions.ExpectedMetric { metricName = @"Custom/MyCustomAddMetricName", callCount = 1 });
+ expectedMetrics.Add(new Assertions.ExpectedMetric { metricName = @"Custom/MyCustomAddMetricName", metricScope = "WebTransaction/Custom/MyCustomAddMetricName", callCount = 1 });
+ expectedMetrics.Add(new Assertions.ExpectedMetric { metricName = @"DotNet/RejitController/GetAddFile", callCount = 2 });
+ }
+
var metrics = CommonUtils.GetMetrics(_fixture.AgentLog);
_fixture.TestLogger?.WriteLine(_fixture.AgentLog.GetFullLogAsString());
@@ -84,10 +96,18 @@ public void Test()
}
}
- public class RejitAddFile : RejitAddFileBase
+ public class RejitAddFileWithFileWatcherEnabled : RejitAddFileBase
+ {
+ public RejitAddFileWithFileWatcherEnabled(AspNetCoreReJitMvcApplicationFixture fixture, ITestOutputHelper output)
+ : base(fixture, output, false)
+ {
+ }
+ }
+
+ public class RejitAddFileWithFileWatcherDisabled : RejitAddFileBase
{
- public RejitAddFile(AspNetCoreReJitMvcApplicationFixture fixture, ITestOutputHelper output)
- : base(fixture, output)
+ public RejitAddFileWithFileWatcherDisabled(AspNetCoreReJitMvcApplicationFixture fixture, ITestOutputHelper output)
+ : base(fixture, output, true)
{
}
}
@@ -95,7 +115,7 @@ public RejitAddFile(AspNetCoreReJitMvcApplicationFixture fixture, ITestOutputHel
public class RejitAddFileWithTieredCompilation : RejitAddFileBase
{
public RejitAddFileWithTieredCompilation(AspNetCoreReJitMvcApplicationFixtureWithTieredCompilation fixture, ITestOutputHelper output)
- : base(fixture, output)
+ : base(fixture, output, false)
{
}
}
diff --git a/tests/Agent/IntegrationTests/IntegrationTests/ReJit/NetFramework/RejitAddFile.cs b/tests/Agent/IntegrationTests/IntegrationTests/ReJit/NetFramework/RejitAddFile.cs
index 5fe21cc78b..ee3ae72ec6 100644
--- a/tests/Agent/IntegrationTests/IntegrationTests/ReJit/NetFramework/RejitAddFile.cs
+++ b/tests/Agent/IntegrationTests/IntegrationTests/ReJit/NetFramework/RejitAddFile.cs
@@ -20,14 +20,17 @@ namespace NewRelic.Agent.IntegrationTests.ReJit.NetFramework
/// Files: Integration.Testing.AddXmlFileTest.xml
///
[NetFrameworkTest]
- public class RejitAddFile : NewRelicIntegrationTest
+ public abstract class RejitAddFileBase : NewRelicIntegrationTest
+ where TFixture : AspNetFrameworkReJitMvcApplicationFixture
{
private readonly AspNetFrameworkReJitMvcApplicationFixture _fixture;
+ private readonly bool _disableFileSystemWatcher;
- public RejitAddFile(AspNetFrameworkReJitMvcApplicationFixture fixture, ITestOutputHelper output)
+ public RejitAddFileBase(TFixture fixture, ITestOutputHelper output, bool disableFileSystemWatcher)
: base(fixture)
{
_fixture = fixture;
+ _disableFileSystemWatcher = disableFileSystemWatcher;
_fixture.TestLogger = output;
_fixture.Actions(
@@ -35,6 +38,7 @@ public RejitAddFile(AspNetFrameworkReJitMvcApplicationFixture fixture, ITestOutp
{
var configModifier = new NewRelicConfigModifier(_fixture.DestinationNewRelicConfigFilePath);
configModifier.AutoInstrumentBrowserMonitoring(false);
+ configModifier.SetDisableFileSystemWatcher(disableFileSystemWatcher);
},
exerciseApplication: () =>
{
@@ -59,20 +63,29 @@ public void Test()
{
//transactions
new Assertions.ExpectedMetric { metricName = @"WebTransaction/MVC/HomeController/Index", CallCountAllHarvests = 1 },
- new Assertions.ExpectedMetric { metricName = @"WebTransaction/Custom/MyCustomAddMetricName", CallCountAllHarvests = 1 },
new Assertions.ExpectedMetric { metricName = @"WebTransaction/MVC/RejitController/GetAddFile", CallCountAllHarvests = 1 },
// Unscoped
new Assertions.ExpectedMetric { metricName = @"DotNet/HomeController/Index", CallCountAllHarvests = 1 },
- new Assertions.ExpectedMetric { metricName = @"Custom/MyCustomAddMetricName", CallCountAllHarvests = 1 },
- new Assertions.ExpectedMetric { metricName = @"DotNet/RejitController/GetAddFile", CallCountAllHarvests = 2 },
// Scoped
new Assertions.ExpectedMetric { metricName = @"DotNet/HomeController/Index", metricScope = "WebTransaction/MVC/HomeController/Index", CallCountAllHarvests = 1 },
- new Assertions.ExpectedMetric { metricName = @"Custom/MyCustomAddMetricName", metricScope = "WebTransaction/Custom/MyCustomAddMetricName", CallCountAllHarvests = 1 },
new Assertions.ExpectedMetric { metricName = @"DotNet/RejitController/GetAddFile", metricScope = "WebTransaction/MVC/RejitController/GetAddFile", CallCountAllHarvests = 1 }
};
+ // Id file system watcher is disabled, these won't exist.
+ if (_disableFileSystemWatcher)
+ {
+ expectedMetrics.Add(new Assertions.ExpectedMetric { metricName = @"DotNet/RejitController/GetAddFile", CallCountAllHarvests = 1 });
+ }
+ else
+ {
+ expectedMetrics.Add(new Assertions.ExpectedMetric { metricName = @"WebTransaction/Custom/MyCustomAddMetricName", CallCountAllHarvests = 1 });
+ expectedMetrics.Add(new Assertions.ExpectedMetric { metricName = @"Custom/MyCustomAddMetricName", CallCountAllHarvests = 1 });
+ expectedMetrics.Add(new Assertions.ExpectedMetric { metricName = @"Custom/MyCustomAddMetricName", metricScope = "WebTransaction/Custom/MyCustomAddMetricName", CallCountAllHarvests = 1 });
+ expectedMetrics.Add(new Assertions.ExpectedMetric { metricName = @"DotNet/RejitController/GetAddFile", CallCountAllHarvests = 2 });
+ }
+
var metrics = CommonUtils.GetMetrics(_fixture.AgentLog);
_fixture.TestLogger?.WriteLine(_fixture.AgentLog.GetFullLogAsString());
@@ -81,4 +94,20 @@ public void Test()
);
}
}
+
+ public class RejitAddFileWithFileWatcherEnabled : RejitAddFileBase
+ {
+ public RejitAddFileWithFileWatcherEnabled(AspNetFrameworkReJitMvcApplicationFixture fixture, ITestOutputHelper output)
+ : base(fixture, output, false)
+ {
+ }
+ }
+
+ public class RejitAddFileWithFileWatcherDisabled : RejitAddFileBase
+ {
+ public RejitAddFileWithFileWatcherDisabled(AspNetFrameworkReJitMvcApplicationFixture fixture, ITestOutputHelper output)
+ : base(fixture, output, true)
+ {
+ }
+ }
}
diff --git a/tests/Agent/UnitTests/Core.UnitTest/DataTransport/ExhaustiveTestConfiguration.cs b/tests/Agent/UnitTests/Core.UnitTest/DataTransport/ExhaustiveTestConfiguration.cs
index fe6d2eb5bf..90a99a52dd 100644
--- a/tests/Agent/UnitTests/Core.UnitTest/DataTransport/ExhaustiveTestConfiguration.cs
+++ b/tests/Agent/UnitTests/Core.UnitTest/DataTransport/ExhaustiveTestConfiguration.cs
@@ -440,6 +440,8 @@ public class ExhaustiveTestConfiguration : IConfiguration
new Dictionary { { "assemblyName", "AssemblyToIgnore2" }, { "className", "ClassNameToIgnore" } }
};
+ public bool DisableFileSystemWatcher => false;
+
public TimeSpan MetricsHarvestCycle => TimeSpan.FromMinutes(1);
public TimeSpan TransactionTracesHarvestCycle => TimeSpan.FromMinutes(1);