Skip to content

Commit

Permalink
feat: Add an option to disable the instrumentation file system watcher.
Browse files Browse the repository at this point in the history
  • Loading branch information
jaffinito committed Jun 10, 2024
1 parent 227003a commit befc792
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 17 deletions.
17 changes: 17 additions & 0 deletions src/Agent/NewRelic/Agent/Core/Config/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1539,6 +1539,8 @@ public partial class configurationInstrumentation

private bool logField;

private bool disableFileSystemWatcherField;

/// <summary>
/// configurationInstrumentation class constructor
/// </summary>
Expand All @@ -1547,6 +1549,7 @@ public configurationInstrumentation()
this.applicationsField = new List<configurationInstrumentationApplication>();
this.rulesField = new List<configurationInstrumentationIgnore>();
this.logField = false;
this.disableFileSystemWatcherField = false;
}

[System.Xml.Serialization.XmlArrayItemAttribute("ignore", IsNullable=false)]
Expand Down Expand Up @@ -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
/// <summary>
/// Create a clone of this configurationInstrumentation object
Expand Down
8 changes: 8 additions & 0 deletions src/Agent/NewRelic/Agent/Core/Config/Configuration.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,14 @@
</xs:annotation>
</xs:attribute>

<xs:attribute name="disableFileSystemWatcher" type="xs:boolean" default="false">
<xs:annotation>
<xs:documentation>
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.
</xs:documentation>
</xs:annotation>
</xs:attribute>

</xs:complexType>
</xs:element>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2058,6 +2058,14 @@ public IEnumerable<IDictionary<string, string>> IgnoredInstrumentation
}
}

public bool DisableFileSystemWatcher
{
get
{
return EnvironmentOverrides(_localConfiguration.instrumentation.disableFileSystemWatcher, "NEW_RELIC_DISABLE_FILE_SYSTEM_WATCHER");
}
}

#region AI Monitoring

public bool AiMonitoringEnabled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,9 @@ public ReportedConfiguration(IConfiguration configuration)
[JsonProperty("agent.instrumentation.ignore")]
public IEnumerable<IDictionary<string, string>> IgnoredInstrumentation => _configuration.IgnoredInstrumentation;

[JsonProperty("agent.disable_file_system_watcher")]
public bool DisableFileSystemWatcher => _configuration.DisableFileSystemWatcher;

[JsonProperty("agent.ai_monitoring.enabled")]
public bool AiMonitoringEnabled => _configuration.AiMonitoringEnabled;

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -16,18 +17,26 @@ public class InstrumentationWatcher : IDisposable

private readonly IInstrumentationService _instrumentationService;
private readonly IWrapperService _wrapperService;
private readonly IConfigurationService _configurationService;

private List<FileSystemWatcher> _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.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ public interface IConfiguration
bool LoggingEnabled { get; }
string LoggingLevel { get; }
IEnumerable<IDictionary<string, string>> IgnoredInstrumentation { get; }

bool DisableFileSystemWatcher { get; }
bool AiMonitoringEnabled { get; }
bool AiMonitoringStreamingEnabled { get; }
bool AiMonitoringRecordContentEnabled { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ public abstract class RejitAddFileBase<TFixture> : NewRelicIntegrationTest<TFixt
where TFixture:AspNetCoreReJitMvcApplicationFixture
{
private readonly AspNetCoreReJitMvcApplicationFixture _fixture;
private readonly bool _disableFileSystemWatcher;

protected RejitAddFileBase(TFixture fixture, ITestOutputHelper output) : base(fixture)
protected RejitAddFileBase(TFixture fixture, ITestOutputHelper output, bool disableFileSystemWatcher) : base(fixture)
{
_fixture = fixture;
_disableFileSystemWatcher = disableFileSystemWatcher;

_fixture.TestLogger = output;
_fixture.Actions(
Expand All @@ -37,6 +39,7 @@ protected RejitAddFileBase(TFixture fixture, ITestOutputHelper output) : base(fi
var configModifier = new NewRelicConfigModifier(_fixture.DestinationNewRelicConfigFilePath);
configModifier.SetLogLevel("finest");
configModifier.AutoInstrumentBrowserMonitoring(false);
configModifier.SetDisableFileSystemWatcher(disableFileSystemWatcher);
},
exerciseApplication: () =>
{
Expand All @@ -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());

Expand All @@ -84,18 +96,26 @@ public void Test()
}
}

public class RejitAddFile : RejitAddFileBase<AspNetCoreReJitMvcApplicationFixture>
public class RejitAddFileWithFileWatcherEnabled : RejitAddFileBase<AspNetCoreReJitMvcApplicationFixture>
{
public RejitAddFileWithFileWatcherEnabled(AspNetCoreReJitMvcApplicationFixture fixture, ITestOutputHelper output)
: base(fixture, output, false)
{
}
}

public class RejitAddFileWithFileWatcherDisabled : RejitAddFileBase<AspNetCoreReJitMvcApplicationFixture>
{
public RejitAddFile(AspNetCoreReJitMvcApplicationFixture fixture, ITestOutputHelper output)
: base(fixture, output)
public RejitAddFileWithFileWatcherDisabled(AspNetCoreReJitMvcApplicationFixture fixture, ITestOutputHelper output)
: base(fixture, output, true)
{
}
}

public class RejitAddFileWithTieredCompilation : RejitAddFileBase<AspNetCoreReJitMvcApplicationFixtureWithTieredCompilation>
{
public RejitAddFileWithTieredCompilation(AspNetCoreReJitMvcApplicationFixtureWithTieredCompilation fixture, ITestOutputHelper output)
: base(fixture, output)
: base(fixture, output, false)
{
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,25 @@ namespace NewRelic.Agent.IntegrationTests.ReJit.NetFramework
/// Files: Integration.Testing.AddXmlFileTest.xml
/// </summary>
[NetFrameworkTest]
public class RejitAddFile : NewRelicIntegrationTest<AspNetFrameworkReJitMvcApplicationFixture>
public abstract class RejitAddFileBase<TFixture> : NewRelicIntegrationTest<TFixture>
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(
setupConfiguration: () =>
{
var configModifier = new NewRelicConfigModifier(_fixture.DestinationNewRelicConfigFilePath);
configModifier.AutoInstrumentBrowserMonitoring(false);
configModifier.SetDisableFileSystemWatcher(disableFileSystemWatcher);
},
exerciseApplication: () =>
{
Expand All @@ -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());

Expand All @@ -81,4 +94,20 @@ public void Test()
);
}
}

public class RejitAddFileWithFileWatcherEnabled : RejitAddFileBase<AspNetFrameworkReJitMvcApplicationFixture>
{
public RejitAddFileWithFileWatcherEnabled(AspNetFrameworkReJitMvcApplicationFixture fixture, ITestOutputHelper output)
: base(fixture, output, false)
{
}
}

public class RejitAddFileWithFileWatcherDisabled : RejitAddFileBase<AspNetFrameworkReJitMvcApplicationFixture>
{
public RejitAddFileWithFileWatcherDisabled(AspNetFrameworkReJitMvcApplicationFixture fixture, ITestOutputHelper output)
: base(fixture, output, true)
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,8 @@ public class ExhaustiveTestConfiguration : IConfiguration
new Dictionary<string, string> { { "assemblyName", "AssemblyToIgnore2" }, { "className", "ClassNameToIgnore" } }
};

public bool DisableFileSystemWatcher => false;

public TimeSpan MetricsHarvestCycle => TimeSpan.FromMinutes(1);

public TimeSpan TransactionTracesHarvestCycle => TimeSpan.FromMinutes(1);
Expand Down

0 comments on commit befc792

Please sign in to comment.