Skip to content

Commit

Permalink
test: Add .NET 7 Unit Test Build Targets (#1778)
Browse files Browse the repository at this point in the history
  • Loading branch information
tippmar-nr authored Jul 19, 2023
1 parent 561897d commit 974335c
Show file tree
Hide file tree
Showing 45 changed files with 311 additions and 199 deletions.
2 changes: 1 addition & 1 deletion src/Agent/NewRelic/Agent/Core/DataTransport/GrpcWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public bool CreateChannel(string host, int port, bool ssl, Metadata headers, int

var uriBuilder = new UriBuilder
{
Scheme = "https",
Scheme = ssl ? "https" : "http",
Host = host,
Port = port
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,24 +76,24 @@ public static void RegisterServices(IContainer container)

// Other
container.Register<ICpuSampleTransformer, CpuSampleTransformer>();
container.Register<AgentInstallConfiguration.IsWindowsDelegate>(AgentInstallConfiguration.GetIsWindows);
container.RegisterInstance<AgentInstallConfiguration.IsWindowsDelegate>(AgentInstallConfiguration.GetIsWindows);
container.Register<IMemorySampleTransformer, MemorySampleTransformer>();
container.Register<IThreadStatsSampleTransformer, ThreadStatsSampleTransformer>();
container.Register<IEnvironment, SystemInterfaces.Environment>();
container.Register<IAgent, Agent>();
container.Register<CpuSampler, CpuSampler>();
container.Register<MemorySampler, MemorySampler>();
container.Register<Func<ISampledEventListener<ThreadpoolThroughputEventsSample>>>(() => new ThreadEventsListener());
container.RegisterInstance<Func<ISampledEventListener<ThreadpoolThroughputEventsSample>>>(() => new ThreadEventsListener());
container.Register<ThreadStatsSampler, ThreadStatsSampler>();
container.Register<IGcSampleTransformer, GcSampleTransformer>();
#if NETFRAMEWORK
container.Register<Func<string, IPerformanceCounterCategoryProxy>>(PerformanceCounterProxyFactory.DefaultCreatePerformanceCounterCategoryProxy);
container.Register<Func<string, string, string, IPerformanceCounterProxy>>(PerformanceCounterProxyFactory.DefaultCreatePerformanceCounterProxy);
container.RegisterInstance<Func<string, IPerformanceCounterCategoryProxy>>(PerformanceCounterProxyFactory.DefaultCreatePerformanceCounterCategoryProxy);
container.RegisterInstance<Func<string, string, string, IPerformanceCounterProxy>>(PerformanceCounterProxyFactory.DefaultCreatePerformanceCounterProxy);
container.Register<IPerformanceCounterProxyFactory, PerformanceCounterProxyFactory>();
container.Register<GcSampler, GcSampler>();
#else
container.Register<Func<ISampledEventListener<Dictionary<GCSampleType, float>>>>(() => new GCEventsListener());
container.Register<Func<GCSamplerNetCore.SamplerIsApplicableToFrameworkResult>>(GCSamplerNetCore.FXsamplerIsApplicableToFrameworkDefault);
container.RegisterInstance<Func<ISampledEventListener<Dictionary<GCSampleType, float>>>>(() => new GCEventsListener());
container.RegisterInstance<Func<GCSamplerNetCore.SamplerIsApplicableToFrameworkResult>>(GCSamplerNetCore.FXsamplerIsApplicableToFrameworkDefault);
container.Register<GCSamplerNetCore, GCSamplerNetCore>();
#endif

Expand All @@ -116,7 +116,7 @@ public static void RegisterServices(IContainer container)
container.Register<IMetricAggregator, MetricAggregator>();
container.Register<IAllMetricStatsCollection, MetricWireModel>();
container.Register<IAllMetricStatsCollection, TransactionMetricStatsCollection>();
container.Register<Func<MetricWireModel, MetricWireModel, MetricWireModel>>(MetricWireModel.Merge);
container.RegisterInstance<Func<MetricWireModel, MetricWireModel, MetricWireModel>>(MetricWireModel.Merge);
container.Register<ITransactionTraceAggregator, TransactionTraceAggregator>();
container.Register<ITransactionEventAggregator, TransactionEventAggregator>();
container.Register<ISqlTraceAggregator, SqlTraceAggregator>();
Expand Down Expand Up @@ -157,7 +157,7 @@ public static void RegisterServices(IContainer container)
container.Register<ITransactionCollector, SlowestTransactionCollector>();
container.Register<ITransactionCollector, SyntheticsTransactionCollector>();
container.Register<ITransactionCollector, KeyTransactionCollector>();
container.Register<IEnumerable<ITransactionCollector>>(transactionCollectors);
container.RegisterInstance<IEnumerable<ITransactionCollector>>(transactionCollectors);

container.Register<ITransactionAttributeMaker, TransactionAttributeMaker>();
container.Register<IErrorTraceMaker, ErrorTraceMaker>();
Expand All @@ -180,7 +180,7 @@ public static void RegisterServices(IContainer container)
container.Register<ILabelsService, LabelsService>();

container.Register<ITransactionService, TransactionService>();
container.Register<Func<IAttributeFilter, IAttributeDefinitions>>((filter) => new AttributeDefinitions(filter));
container.RegisterInstance<Func<IAttributeFilter, IAttributeDefinitions>>((filter) => new AttributeDefinitions(filter));
container.Register<IAttributeDefinitionService, AttributeDefinitionService>();
container.Register<CommandService, CommandService>();
container.Register<ConfigurationTracker, ConfigurationTracker>();
Expand Down
207 changes: 124 additions & 83 deletions src/Agent/NewRelic/Agent/Core/DependencyInjection/CoreContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,93 +4,134 @@
#if NETSTANDARD2_0
using System;
using System.Collections.Generic;
using NewRelic.Agent.Core.Logging;

using System.Linq;
using System.Text;
using Autofac;
using NewRelic.Core.Logging;

namespace NewRelic.Agent.Core.DependencyInjection
{
public class CoreContainer : IContainer
{

private readonly ContainerBuilder builder;
private Autofac.IContainer container;

public CoreContainer()
{
this.builder = new ContainerBuilder();
}

public void Build()
{
this.container = builder.Build();
}

public void Dispose()
{
}

public void Register<TInterface, TConcrete>()
where TInterface : class
where TConcrete : class, TInterface
{
builder.RegisterType<TConcrete>().As<TInterface>().SingleInstance();
}

public void Register<TInterface1, TInterface2, TConcrete>()
where TInterface1 : class
where TInterface2 : class
where TConcrete : class, TInterface1, TInterface2
{
builder.RegisterType<TConcrete>().As<TInterface1, TInterface2>().SingleInstance();
}

public void Register<TInterface>(TInterface instance)
where TInterface : class
{
builder.RegisterInstance<TInterface>(instance).As<TInterface>().SingleInstance();
}

public void RegisterFactory<TInterface>(Func<TInterface> func)
where TInterface : class
{
builder.Register(c => func.Invoke()).As<TInterface>();
}

public void ReplaceRegistration<TInterface>(TInterface instance)
where TInterface : class
{
throw new NotImplementedException();
}

public T Resolve<T>()
{
Check(typeof(T));
return container.Resolve<T>();
}

public IEnumerable<T> ResolveAll<T>()
{
Check(typeof(T));
try
{
return container.Resolve<IEnumerable<T>>();
} catch (Exception ex)
{
Log.Error($"Error during ResolveAll of {typeof(T)}");
throw ex;
}
}
private void Check(Type type)
{
if (container == null)
{
throw new Exception("Resolve invoked with uninitialized container for " + type);
}
}
}
public class CoreContainer : IContainer
{

private readonly ContainerBuilder _builder;
private Autofac.IContainer _container;

// use the scope instead of the container to resolve instances. This allows us to replace registrations in a new scope for unit testing
private ILifetimeScope _scope;
private bool _disposedValue;
private readonly Dictionary<Type, object> _registrationsToReplace = new Dictionary<Type, object>();

public CoreContainer()
{
_builder = new ContainerBuilder();
}

public void Build()
{
_container = _builder.Build();
_scope = _container.BeginLifetimeScope();
}

public void ReplaceRegistrations()
{
// create a new nested scope, registering the requested replacement instances.
_scope = _scope.BeginLifetimeScope(ReplaceRegistrations);

_registrationsToReplace.Clear();
}

private void ReplaceRegistrations(ContainerBuilder builder)
{
foreach (var kvp in _registrationsToReplace)
{
builder.RegisterInstance(kvp.Value).As(kvp.Key);
}
}


public void Register<TInterface, TConcrete>()
where TInterface : class
where TConcrete : class, TInterface
{
_builder.RegisterType<TConcrete>().As<TInterface>().InstancePerLifetimeScope();
}

public void Register<TInterface1, TInterface2, TConcrete>()
where TInterface1 : class
where TInterface2 : class
where TConcrete : class, TInterface1, TInterface2
{
_builder.RegisterType<TConcrete>().As<TInterface1, TInterface2>().InstancePerLifetimeScope();
}

public void RegisterInstance<TInterface>(TInterface instance)
where TInterface : class
{
_builder.RegisterInstance<TInterface>(instance).As<TInterface>().SingleInstance();
}

public void RegisterFactory<TInterface>(Func<TInterface> func)
where TInterface : class
{
_builder.Register(c => func.Invoke()).As<TInterface>();
}

public void ReplaceInstanceRegistration<TInterface>(TInterface instance)
where TInterface : class
{
// Add this replacement registration to a list, registration actually occurs in ReplaceRegistrations()
_registrationsToReplace.Add(typeof(TInterface), instance);
}

public T Resolve<T>()
{
Check(typeof(T));
return _scope.Resolve<T>();
}

public IEnumerable<T> ResolveAll<T>()
{
Check(typeof(T));
try
{
return _scope.Resolve<IEnumerable<T>>();
}
catch (Exception ex)
{
Log.Error($"Error during ResolveAll of {typeof(T)}: {ex}");
throw;
}
}
private void Check(Type type)
{
if (_scope == null)
{
throw new Exception("Resolve invoked with uninitialized container for " + type);
}
}

protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
_scope?.Dispose();
_container?.Dispose();

_scope = null;
_container = null;
}

_disposedValue = true;
}
}

public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,23 @@ void Register<TInterface1, TInterface2, TConcrete>()
where TInterface2 : class
where TConcrete : class, TInterface1, TInterface2;

void Register<TInterface>(TInterface instance)
void RegisterInstance<TInterface>(TInterface instance)
where TInterface : class;

void RegisterFactory<TInterface>(Func<TInterface> func)
where TInterface : class;

void ReplaceRegistration<TInterface>(TInterface instance)
void ReplaceInstanceRegistration<TInterface>(TInterface instance)
where TInterface : class;

T Resolve<T>();

IEnumerable<T> ResolveAll<T>();

void Build();

#if NETSTANDARD
void ReplaceRegistrations();
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void Register<TInterface1, TInterface2, TConcrete>()
.Named(typeof(TInterface1).FullName + "," + typeof(TInterface2).FullName + "-" + typeof(TConcrete).FullName));
}

public void Register<TInterface>(TInterface instance) where TInterface : class
public void RegisterInstance<TInterface>(TInterface instance) where TInterface : class
{
_windsorContainer.Register(Component.For<TInterface>().Instance(instance));
}
Expand All @@ -71,7 +71,7 @@ public void RegisterFactory<TInterface>(Func<TInterface> func)
_windsorContainer.Register(Component.For<TInterface>().UsingFactoryMethod(func));
}

public void ReplaceRegistration<TInterface>(TInterface instance)
public void ReplaceInstanceRegistration<TInterface>(TInterface instance)
where TInterface : class
{
var guid = Guid.NewGuid().ToString();
Expand Down
5 changes: 4 additions & 1 deletion src/Agent/NewRelic/Agent/Core/Errors/ExceptionFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ public static string FormatStackTrace(Exception exception, bool stripErrorMessag
var message = stripErrorMessage ? ErrorData.StripExceptionMessagesMessage : exception.Message;
var formattedInnerException = FormatInnerStackTrace(exception.InnerException, stripErrorMessage);
var formattedStackTrace = exception.StackTrace != null ? System.Environment.NewLine + exception.StackTrace : null;

#if NETSTANDARD2_0
if (!string.IsNullOrEmpty(formattedInnerException))
formattedInnerException = System.Environment.NewLine + formattedInnerException;
#endif
var result = $"{type}: {message}{formattedInnerException}{formattedStackTrace}";

return result;
Expand Down
2 changes: 1 addition & 1 deletion src/Agent/NewRelic/Agent/Core/Metrics/MetricNameService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public string NormalizeUrl(string url)
{
if (_configuration.WebTransactionsApdex.TryGetValue(transactionName, out double apdexT))
{
return TimeSpan.FromSeconds(Convert.ToSingle(apdexT));
return TimeSpan.FromSeconds(apdexT);
}
return null;
}
Expand Down
4 changes: 3 additions & 1 deletion src/Agent/NewRelic/Agent/Core/Samplers/ThreadStatsSampler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ public override void Dispose()
{
base.Dispose();
_listener?.StopListening();
_listener?.Dispose();
#if NETFRAMEWORK // calling .Dispose() in .NET 7 explodes. No idea why.
_listener?.Dispose();
#endif
_listener = null;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Agent/NewRelic/Agent/Core/Segments/Segment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public void End()
{
// This order is to ensure the segment end time is correct, but also not mark the segment as IsDone so that CleanUp ignores it.
var endTime = _transactionSegmentState.GetRelativeTime();
Agent.Instance.StackExchangeRedisCache?.Harvest(this);
Agent.Instance?.StackExchangeRedisCache?.Harvest(this);
RelativeEndTime = endTime;

Finish();
Expand Down
2 changes: 1 addition & 1 deletion src/Agent/NewRelic/Agent/Core/Transactions/Transaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,7 @@ public void Ignore()
if (Log.IsFinestEnabled)
{
var transactionName = CandidateTransactionName.CurrentTransactionName;
var transactionMetricName = Agent._transactionMetricNameMaker.GetTransactionMetricName(transactionName);
var transactionMetricName = Agent?._transactionMetricNameMaker?.GetTransactionMetricName(transactionName);
var stackTrace = new StackTrace();
Log.Finest($"Transaction \"{transactionMetricName}\" is being ignored from {stackTrace}");
}
Expand Down
Loading

0 comments on commit 974335c

Please sign in to comment.