diff --git a/FullAgent.sln b/FullAgent.sln index 17ffc591b1..ae543447d4 100644 --- a/FullAgent.sln +++ b/FullAgent.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29613.14 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32319.34 MinimumVisualStudioVersion = 15.0.26228.04 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core", "src\Agent\NewRelic\Agent\Core\Core.csproj", "{D6E22195-EE69-4320-B08B-E68229FB69AB}" EndProject @@ -201,9 +201,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Home", "src\Agent\NewRelic\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CosmosDb", "src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\CosmosDb\CosmosDb.csproj", "{E10BF2F9-D5CA-4330-8169-ED30D861697E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Logging", "src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\Logging\Logging.csproj", "{E696F7DF-D99F-4BD4-B757-531B5F5ECB36}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MicrosoftExtensionsLogging", "src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\MicrosoftExtensionsLogging\MicrosoftExtensionsLogging.csproj", "{710C7C7A-CD27-4F94-B2D3-9804BD848D57}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MicrosoftExtensionsLogging", "src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\MicrosoftExtensionsLogging\MicrosoftExtensionsLogging.csproj", "{710C7C7A-CD27-4F94-B2D3-9804BD848D57}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SerilogLogging", "src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\SerilogLogging\SerilogLogging.csproj", "{0C3E92D7-F16C-4575-9CBB-EB7349A4C5E2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Log4NetLogging", "src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\Log4NetLogging\Log4NetLogging.csproj", "{2E6CF650-CB50-453D-830A-D00F0540FC2C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -419,14 +421,18 @@ Global {E10BF2F9-D5CA-4330-8169-ED30D861697E}.Debug|Any CPU.Build.0 = Debug|Any CPU {E10BF2F9-D5CA-4330-8169-ED30D861697E}.Release|Any CPU.ActiveCfg = Release|Any CPU {E10BF2F9-D5CA-4330-8169-ED30D861697E}.Release|Any CPU.Build.0 = Release|Any CPU - {E696F7DF-D99F-4BD4-B757-531B5F5ECB36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E696F7DF-D99F-4BD4-B757-531B5F5ECB36}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E696F7DF-D99F-4BD4-B757-531B5F5ECB36}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E696F7DF-D99F-4BD4-B757-531B5F5ECB36}.Release|Any CPU.Build.0 = Release|Any CPU {710C7C7A-CD27-4F94-B2D3-9804BD848D57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {710C7C7A-CD27-4F94-B2D3-9804BD848D57}.Debug|Any CPU.Build.0 = Debug|Any CPU {710C7C7A-CD27-4F94-B2D3-9804BD848D57}.Release|Any CPU.ActiveCfg = Release|Any CPU {710C7C7A-CD27-4F94-B2D3-9804BD848D57}.Release|Any CPU.Build.0 = Release|Any CPU + {0C3E92D7-F16C-4575-9CBB-EB7349A4C5E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C3E92D7-F16C-4575-9CBB-EB7349A4C5E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C3E92D7-F16C-4575-9CBB-EB7349A4C5E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C3E92D7-F16C-4575-9CBB-EB7349A4C5E2}.Release|Any CPU.Build.0 = Release|Any CPU + {2E6CF650-CB50-453D-830A-D00F0540FC2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E6CF650-CB50-453D-830A-D00F0540FC2C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E6CF650-CB50-453D-830A-D00F0540FC2C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E6CF650-CB50-453D-830A-D00F0540FC2C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -492,8 +498,9 @@ Global {E487774C-2805-4642-B173-63D8F2D05D39} = {F617061F-24DF-4C57-8147-84CAB336DD4E} {5CF47B2E-9370-4FD8-B9BD-0D95D3EA167C} = {E3DAC9C6-AE41-4B37-A253-C621E568590E} {E10BF2F9-D5CA-4330-8169-ED30D861697E} = {5E86E10A-C38F-48CB-ADE9-67B22BB2F50A} - {E696F7DF-D99F-4BD4-B757-531B5F5ECB36} = {5E86E10A-C38F-48CB-ADE9-67B22BB2F50A} {710C7C7A-CD27-4F94-B2D3-9804BD848D57} = {5E86E10A-C38F-48CB-ADE9-67B22BB2F50A} + {0C3E92D7-F16C-4575-9CBB-EB7349A4C5E2} = {5E86E10A-C38F-48CB-ADE9-67B22BB2F50A} + {2E6CF650-CB50-453D-830A-D00F0540FC2C} = {5E86E10A-C38F-48CB-ADE9-67B22BB2F50A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.2\lib\NET35 diff --git a/src/Agent/MsiInstaller/Installer/Product.wxs b/src/Agent/MsiInstaller/Installer/Product.wxs index cda000b967..bf8c06cf75 100644 --- a/src/Agent/MsiInstaller/Installer/Product.wxs +++ b/src/Agent/MsiInstaller/Installer/Product.wxs @@ -454,8 +454,11 @@ SPDX-License-Identifier: Apache-2.0 - - + + + + + @@ -492,12 +495,15 @@ SPDX-License-Identifier: Apache-2.0 - - + + + + + @@ -585,8 +591,11 @@ SPDX-License-Identifier: Apache-2.0 - - + + + + + @@ -612,12 +621,15 @@ SPDX-License-Identifier: Apache-2.0 - - + + + + + diff --git a/src/Agent/NewRelic/Agent/Core/Utilities/ExtensionsLoader.cs b/src/Agent/NewRelic/Agent/Core/Utilities/ExtensionsLoader.cs index 1e68de823c..b4c9da350d 100644 --- a/src/Agent/NewRelic/Agent/Core/Utilities/ExtensionsLoader.cs +++ b/src/Agent/NewRelic/Agent/Core/Utilities/ExtensionsLoader.cs @@ -62,6 +62,10 @@ public static void Initialize(string installPathExtensionsDirectory) { "OpenConnectionTracer", Path.Combine(_installPathExtensionsDirectory, "NewRelic.Providers.Wrapper.Sql.dll") }, { "OpenConnectionWrapper", Path.Combine(_installPathExtensionsDirectory, "NewRelic.Providers.Wrapper.Sql.dll") }, + //The NewRelic.Providers.Wrapper.SerilogLogging.dll depends on the Serilog.dll; therefore, it should + //only be loaded by the agent when Serilog is used otherwise assembly load exception will occur. + { "SerilogCreateLoggerWrapper", Path.Combine(_installPathExtensionsDirectory, "NewRelic.Providers.Wrapper.SerilogLogging.dll") }, + { "SerilogDispatchWrapper", Path.Combine(_installPathExtensionsDirectory, "NewRelic.Providers.Wrapper.SerilogLogging.dll") } }; var nonAutoReflectedAssemblies = _dynamicLoadWrapperAssemblies.Values.Distinct().ToList(); diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Log4NetLogging/Instrumentation.xml b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Log4NetLogging/Instrumentation.xml new file mode 100644 index 0000000000..43854629da --- /dev/null +++ b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Log4NetLogging/Instrumentation.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Logging/Logging.csproj b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Log4NetLogging/Log4NetLogging.csproj similarity index 78% rename from src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Logging/Logging.csproj rename to src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Log4NetLogging/Log4NetLogging.csproj index 8271a0ca97..8529a3a45b 100644 --- a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Logging/Logging.csproj +++ b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Log4NetLogging/Log4NetLogging.csproj @@ -1,9 +1,9 @@ net45;netstandard2.0 - NewRelic.Providers.Wrapper.Logging - NewRelic.Providers.Wrapper.Logging - Logging Wrapper Provider for New Relic .NET Agent + NewRelic.Providers.Wrapper.Log4NetLogging + NewRelic.Providers.Wrapper.Log4NetLogging + Log4net Wrapper Provider for New Relic .NET Agent diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Logging/Log4netWrapper.cs b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Log4NetLogging/Log4netWrapper.cs similarity index 100% rename from src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Logging/Log4netWrapper.cs rename to src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Log4NetLogging/Log4netWrapper.cs diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Logging/SerilogWrapper.cs b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Logging/SerilogWrapper.cs deleted file mode 100644 index 4a8aea1b04..0000000000 --- a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Logging/SerilogWrapper.cs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -using System; -using System.Collections; -using NewRelic.Agent.Api; -using NewRelic.Agent.Api.Experimental; -using NewRelic.Agent.Extensions.Logging; -using NewRelic.Agent.Extensions.Providers.Wrapper; -using NewRelic.Reflection; - -namespace NewRelic.Providers.Wrapper.Logging -{ - public class SerilogWrapper : IWrapper - { - private const string AssemblyName = "Serilog"; - private const string TypeName = "Serilog.Events.ScalarValue"; - - private static Func _getLogLevel; - private static Func _getTimestamp; - private static Func _getProperties; - private static Func _createScalarValue; - - public bool IsTransactionRequired => false; - - private const string WrapperName = "serilog"; - private const string DispatchName = "Dispatch"; - - public CanWrapResponse CanWrap(InstrumentedMethodInfo methodInfo) - { - if (!LogProviders.RegisteredLogProvider[(int)LogProvider.Serilog]) - { - return new CanWrapResponse(WrapperName.Equals(methodInfo.RequestedWrapperName)); - } - - return new CanWrapResponse(false); - } - - public AfterWrappedMethodDelegate BeforeWrappedMethod(InstrumentedMethodCall instrumentedMethodCall, IAgent agent, ITransaction transaction) - { - // This block works around an issue we are seeing in Serilog where Dispatch is called up to 3 times for each log message - // When looking at a stack trace for the problem, the you will see up to 3 Dispatch methods one after the other - // This detects the duplicates and noops. - var frame7 = new System.Diagnostics.StackFrame(7, false).GetMethod().Name; - string potentialDispatchFrame; - if (frame7 != DispatchName) - { - // Frame 7 is not Dispatch. This means that an extra frame was in the stack called "UnsafeInvokeInternal" at frame 6 - // Look at frame 9 for duplicates instead of at frame 8 - potentialDispatchFrame = new System.Diagnostics.StackFrame(9, false).GetMethod().Name; - } - else - { - // Frame 7 is Dispatch, no extra frames - // Look at frame 8 for duplicates - potentialDispatchFrame = new System.Diagnostics.StackFrame(8, false).GetMethod().Name; - } - - if (potentialDispatchFrame == DispatchName) - { - return Delegates.NoOp; - } - - var logEvent = instrumentedMethodCall.MethodCall.MethodArguments[0]; - - RecordLogMessage(logEvent, agent); - - DecorateLogMessage(logEvent, agent); - - return Delegates.NoOp; - } - - private void RecordLogMessage(object logEvent, IAgent agent) - { - var getLogLevelFunc = _getLogLevel ??= VisibilityBypasser.Instance.GeneratePropertyAccessor(logEvent.GetType(), "Level"); - - var getTimestampFunc = _getTimestamp ??= VisibilityBypasser.Instance.GeneratePropertyAccessor(logEvent.GetType(), "Timestamp"); - Func getDateTimeFunc = (logEvent) => getTimestampFunc(logEvent).UtcDateTime; - - Func getMessageFunc = (logEvent) => ((dynamic)logEvent).RenderMessage(); - - // This will either add the log message to the transaction or directly to the aggregator - var xapi = agent.GetExperimentalApi(); - xapi.RecordLogMessage(WrapperName, logEvent, getDateTimeFunc, getLogLevelFunc, getMessageFunc, agent.TraceMetadata.SpanId, agent.TraceMetadata.TraceId); - } - - private void DecorateLogMessage(object logEvent, IAgent agent) - { - if (!agent.Configuration.LogDecoratorEnabled) - { - return; - } - - // has to be the field since property is IReadOnlyDictionary - var getProperties = _getProperties ??= VisibilityBypasser.Instance.GenerateFieldReadAccessor(logEvent.GetType(), "_properties"); - var propertiesDictionary = getProperties(logEvent); - if (propertiesDictionary == null) - { - return; - } - - // capture the constructor of the ScalarValue class. - var createScalarValue = _createScalarValue ??= VisibilityBypasser.Instance.GenerateTypeFactory(AssemblyName, TypeName); - - // uses the foratted metadata to make a single entry - var formattedMetadata = LoggingHelpers.GetFormattedLinkingMetadata(agent); - - // uses underscores to support other frameworks that do not allow hyphens (Serilog) - propertiesDictionary["NR_LINKING"] = createScalarValue(formattedMetadata); - } - } -} diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/MicrosoftExtensionsLogging/MicrosoftExtensionsLogging.csproj b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/MicrosoftExtensionsLogging/MicrosoftExtensionsLogging.csproj index 9c83cd7278..ed1782cf77 100644 --- a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/MicrosoftExtensionsLogging/MicrosoftExtensionsLogging.csproj +++ b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/MicrosoftExtensionsLogging/MicrosoftExtensionsLogging.csproj @@ -4,7 +4,7 @@ netstandard2.0 NewRelic.Providers.Wrapper.MicrosoftExtensionsLogging NewRelic.Providers.Wrapper.MicrosoftExtensionsLogging - Logging Wrapper Provider for New Relic .NET Agent + Microsoft.Extensions.Logging Wrapper Provider for New Relic .NET Agent diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Logging/Instrumentation.xml b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/Instrumentation.xml similarity index 72% rename from src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Logging/Instrumentation.xml rename to src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/Instrumentation.xml index 9bd7632c54..268b2f8b9b 100644 --- a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Logging/Instrumentation.xml +++ b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/Instrumentation.xml @@ -5,14 +5,7 @@ SPDX-License-Identifier: Apache-2.0 --> - - - - - - - - + @@ -23,6 +16,11 @@ SPDX-License-Identifier: Apache-2.0 - + + + + + + diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/NewRelicSerilogSink.cs b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/NewRelicSerilogSink.cs new file mode 100644 index 0000000000..e88135a31b --- /dev/null +++ b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/NewRelicSerilogSink.cs @@ -0,0 +1,45 @@ +// Copyright 2020 New Relic, Inc. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +using System; +using NewRelic.Agent.Api; +using NewRelic.Agent.Api.Experimental; +using NewRelic.Agent.Extensions.Logging; +using Serilog.Core; +using Serilog.Events; + +namespace NewRelic.Providers.Wrapper.SerilogLogging +{ + public class NewRelicSerilogSink : ILogEventSink + { + readonly IAgent _agent; + + public NewRelicSerilogSink(IAgent agent) + { + _agent = agent; + } + + public void Emit(LogEvent logEvent) + { + //This check is to prevent forwarding duplicate logs when Microsoft.Extensions.Logging is used. + if (!LogProviders.RegisteredLogProvider[(int)LogProvider.Serilog]) + { + RecordLogMessage(logEvent); + } + } + + private void RecordLogMessage(LogEvent logEvent) + { + Func getLogLevelFunc = l => logEvent.Level; + + Func getDateTimeFunc = l => logEvent.Timestamp.UtcDateTime; + + Func getMessageFunc = l => logEvent.RenderMessage(); + + // This will either add the log message to the transaction or directly to the aggregator + + var xapi = _agent.GetExperimentalApi(); + xapi.RecordLogMessage("serilog", logEvent, getDateTimeFunc, getLogLevelFunc, getMessageFunc, _agent.TraceMetadata.SpanId, _agent.TraceMetadata.TraceId); + } + } +} diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/SerilogCreateLoggerWrapper.cs b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/SerilogCreateLoggerWrapper.cs new file mode 100644 index 0000000000..7e615a6aec --- /dev/null +++ b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/SerilogCreateLoggerWrapper.cs @@ -0,0 +1,37 @@ +// Copyright 2020 New Relic, Inc. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +using NewRelic.Agent.Api; +using NewRelic.Agent.Extensions.Logging; +using NewRelic.Agent.Extensions.Providers.Wrapper; +using Serilog; + +namespace NewRelic.Providers.Wrapper.SerilogLogging +{ + public class SerilogCreateLoggerWrapper : IWrapper + { + public bool IsTransactionRequired => false; + + private const string WrapperName = "SerilogCreateLoggerWrapper"; + + public CanWrapResponse CanWrap(InstrumentedMethodInfo methodInfo) + { + if (!LogProviders.RegisteredLogProvider[(int)LogProvider.Serilog]) + { + return new CanWrapResponse(WrapperName.Equals(methodInfo.RequestedWrapperName)); + } + + return new CanWrapResponse(false); + } + + public AfterWrappedMethodDelegate BeforeWrappedMethod(InstrumentedMethodCall instrumentedMethodCall, IAgent agent, ITransaction transaction) + { + + var loggerConfiguration = instrumentedMethodCall.MethodCall.InvocationTarget as LoggerConfiguration; + + loggerConfiguration.WriteTo.Sink(new NewRelicSerilogSink(agent)); + + return Delegates.NoOp; + } + } +} diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/SerilogDispatchWrapper.cs b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/SerilogDispatchWrapper.cs new file mode 100644 index 0000000000..0521e28622 --- /dev/null +++ b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/SerilogDispatchWrapper.cs @@ -0,0 +1,68 @@ +// Copyright 2020 New Relic, Inc. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +using System; +using System.Collections; +using NewRelic.Agent.Api; +using NewRelic.Agent.Extensions.Logging; +using NewRelic.Agent.Extensions.Providers.Wrapper; +using NewRelic.Reflection; + +namespace NewRelic.Providers.Wrapper.SerilogLogging +{ + public class SerilogDispatchWrapper : IWrapper + { + private const string AssemblyName = "Serilog"; + private const string TypeName = "Serilog.Events.ScalarValue"; + private const string NrLinkingString = "NR_LINKING"; + + private static Func _getProperties; + private static Func _createScalarValue; + + public bool IsTransactionRequired => false; + + private const string WrapperName = "SerilogDispatchWrapper"; + + public CanWrapResponse CanWrap(InstrumentedMethodInfo methodInfo) + { + if (!LogProviders.RegisteredLogProvider[(int)LogProvider.Serilog]) + { + return new CanWrapResponse(WrapperName.Equals(methodInfo.RequestedWrapperName)); + } + + return new CanWrapResponse(false); + } + + public AfterWrappedMethodDelegate BeforeWrappedMethod(InstrumentedMethodCall instrumentedMethodCall, IAgent agent, ITransaction transaction) + { + if (agent.Configuration.LogDecoratorEnabled) + { + var logEvent = instrumentedMethodCall.MethodCall.MethodArguments[0]; + + DecorateLogMessage(logEvent, agent); + } + + return Delegates.NoOp; + } + + private void DecorateLogMessage(object logEvent, IAgent agent) + { + // has to be the field since property is IReadOnlyDictionary + var getProperties = _getProperties ??= VisibilityBypasser.Instance.GenerateFieldReadAccessor(logEvent.GetType(), "_properties"); + var propertiesDictionary = getProperties(logEvent); + if (propertiesDictionary == null || propertiesDictionary.Contains(NrLinkingString)) + { + return; + } + + // capture the constructor of the ScalarValue class. + var createScalarValue = _createScalarValue ??= VisibilityBypasser.Instance.GenerateTypeFactory(AssemblyName, TypeName); + + // uses the foratted metadata to make a single entry + var formattedMetadata = LoggingHelpers.GetFormattedLinkingMetadata(agent); + + // uses underscores to support other frameworks that do not allow hyphens (Serilog) + propertiesDictionary[NrLinkingString] = createScalarValue(formattedMetadata); + } + } +} diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/SerilogLogging.csproj b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/SerilogLogging.csproj new file mode 100644 index 0000000000..71e65b1abe --- /dev/null +++ b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/SerilogLogging/SerilogLogging.csproj @@ -0,0 +1,30 @@ + + + net45;netstandard2.0 + NewRelic.Providers.Wrapper.SerilogLogging + NewRelic.Providers.Wrapper.SerilogLogging + Serilog Wrapper Provider for New Relic .NET Agent + + + + + + + PreserveNewest + + + + + + + + + + + + + + + + +