Skip to content

Commit

Permalink
feat: Use Serilog instead of log4net for internal logging. (#1661)
Browse files Browse the repository at this point in the history
  • Loading branch information
tippmar-nr authored May 30, 2023
1 parent 0882d47 commit 51080df
Show file tree
Hide file tree
Showing 35 changed files with 1,090 additions and 1,113 deletions.
2 changes: 1 addition & 1 deletion src/Agent/NewRelic/Agent/Core/AgentInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ private static class CallOnce
{
static CallOnce()
{
// we must ensure that we hook up to ProcessExit and DomainUnload *before* log4net. Otherwise we can't log anything during OnExit.
// we must ensure that we hook up to ProcessExit and DomainUnload *before* log initialization. Otherwise we can't log anything during OnExit.
AppDomain.CurrentDomain.ProcessExit += (sender, args) => OnExit(sender, args);
AppDomain.CurrentDomain.DomainUnload += (sender, args) => OnExit(sender, args);
LoggerBootstrapper.Initialize();
Expand Down
57 changes: 0 additions & 57 deletions src/Agent/NewRelic/Agent/Core/Config/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,6 @@
// ------------------------------------------------------------------------------
namespace NewRelic.Agent.Core.Config
{
using System;
using System.Diagnostics;
using System.Xml.Serialization;
using System.Collections;
using System.Xml.Schema;
using System.ComponentModel;
using System.Collections.Generic;


Expand Down Expand Up @@ -1301,8 +1295,6 @@ public partial class configurationLog

private bool auditLogField;

private System.Nullable<configurationLogFileLockingModel> fileLockingModelField;

/// <summary>
/// configurationLog class constructor
/// </summary>
Expand Down Expand Up @@ -1381,42 +1373,6 @@ public bool auditLog
}
}

[System.Xml.Serialization.XmlAttributeAttribute()]
public configurationLogFileLockingModel fileLockingModel
{
get
{
if (this.fileLockingModelField.HasValue)
{
return this.fileLockingModelField.Value;
}
else
{
return default(configurationLogFileLockingModel);
}
}
set
{
this.fileLockingModelField = value;
}
}

[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool fileLockingModelSpecified
{
get
{
return this.fileLockingModelField.HasValue;
}
set
{
if (value==false)
{
this.fileLockingModelField = null;
}
}
}

#region Clone method
/// <summary>
/// Create a clone of this configurationLog object
Expand All @@ -1428,19 +1384,6 @@ public virtual configurationLog Clone()
#endregion
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("Xsd2Code", "3.6.0.20097")]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:newrelic-config")]
public enum configurationLogFileLockingModel
{

/// <remarks/>
exclusive,

/// <remarks/>
minimal,
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("Xsd2Code", "3.6.0.20097")]
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
Expand Down
13 changes: 0 additions & 13 deletions src/Agent/NewRelic/Agent/Core/Config/Configuration.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -347,19 +347,6 @@
</xs:annotation>
</xs:attribute>

<xs:attribute name="fileLockingModel">
<xs:annotation>
<xs:documentation>
Controls how agent-produced log files are to be locked. Experimental.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="exclusive"/>
<xs:enumeration value="minimal"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>

Expand Down
16 changes: 0 additions & 16 deletions src/Agent/NewRelic/Agent/Core/Config/ConfigurationLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -586,22 +586,6 @@ private string GetLogFileName()
return "newrelic_agent_" + Strings.SafeFileName(name) + ".log";
}

public bool FileLockingModelSpecified
{
get
{
return fileLockingModelSpecified;
}
}

public configurationLogFileLockingModel FileLockingModel
{
get
{
return fileLockingModel;
}
}

public bool Console
{
get
Expand Down
3 changes: 0 additions & 3 deletions src/Agent/NewRelic/Agent/Core/Config/ILogConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ public interface ILogConfig

string GetFullLogFileName();

bool FileLockingModelSpecified { get; }
configurationLogFileLockingModel FileLockingModel { get; }

bool Console { get; }

bool IsAuditLogEnabled { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,8 @@ private void OnConfigurationDeserialized(ConfigurationDeserializedEvent configur

private static void UpdateLogLevel(configuration localConfiguration)
{
var hierarchy = log4net.LogManager.GetRepository(Assembly.GetCallingAssembly()) as log4net.Repository.Hierarchy.Hierarchy;
var logger = hierarchy.Root;

var logLevel = logger.Hierarchy.LevelMap[localConfiguration.LogConfig.LogLevel];
if (logLevel != null && logLevel != logger.Level)
{
Log.InfoFormat("The log level was updated to {0}", logLevel);
logger.Level = logLevel;
}
Log.InfoFormat("The log level was updated to {0}", localConfiguration.LogConfig.LogLevel);
LoggerBootstrapper.UpdateLoggingLevel(localConfiguration.LogConfig.LogLevel);
}

private void OnServerConfigurationUpdated(ServerConfigurationUpdatedEvent serverConfigurationUpdatedEvent)
Expand Down
32 changes: 22 additions & 10 deletions src/Agent/NewRelic/Agent/Core/Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,14 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="Serilog.Expressions" Version="3.4.1" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="ILRepack" Version="2.0.16" />
<PackageReference Include="log4net" Version="2.0.8" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="SharpZipLib" Version="1.3.3" />
</ItemGroup>
Expand All @@ -56,6 +61,7 @@
<PackageReference Include="Castle.Core" Version="3.3.0" />
<PackageReference Include="Castle.Windsor" Version="3.3.0" />
<PackageReference Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" />
<PackageReference Include="Serilog.Sinks.EventLog" Version="3.1.0" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
Expand All @@ -79,11 +85,6 @@
<Reference Include="System.Configuration" />
</ItemGroup>

<ItemGroup>
<Compile Include="$(RootProjectDirectory)\src\Agent\Shared\SharedLog4NetRepository.cs">
<Link>Properties\SharedLog4NetRepository.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
Expand All @@ -105,8 +106,14 @@
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Castle.Core'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Castle.Windsor'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'ICSharpCode.SharpZipLib'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'log4net'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Newtonsoft.Json'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Expressions'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.Async'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.Console'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.Debug'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.EventLog'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.File'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'System.ValueTuple'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'System.Memory'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'System.Runtime.CompilerServices.Unsafe'" />
Expand All @@ -120,14 +127,19 @@
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Grpc.Net.Common'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Grpc.Net.Client'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Autofac'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'log4net'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Newtonsoft.Json'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Expressions'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.Async'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.Console'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.Debug'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.File'" />
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'ICSharpCode.SharpZipLib'" />
</ItemGroup>

<PropertyGroup>
<ILRepackIncludeCount Condition="'$(TargetFramework)' == 'net462'">15</ILRepackIncludeCount>
<ILRepackIncludeCount Condition="'$(TargetFramework)' == 'netstandard2.0'">11</ILRepackIncludeCount>
<ILRepackIncludeCount Condition="'$(TargetFramework)' == 'net462'">21</ILRepackIncludeCount>
<ILRepackIncludeCount Condition="'$(TargetFramework)' == 'netstandard2.0'">16</ILRepackIncludeCount>
</PropertyGroup>

<Error Text="ILRepack of $(AssemblyName) ($(TargetFramework)) failed. A dependency is missing. Expected $(ILRepackIncludeCount) dependencies but found @(ILRepackInclude-&gt;Count())." Condition="@(ILRepackInclude-&gt;Count()) != $(ILRepackIncludeCount)" />
Expand Down
12 changes: 6 additions & 6 deletions src/Agent/NewRelic/Agent/Core/Labels/LabelsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace NewRelic.Agent.Core.Labels
{
public class LabelsService : ILabelsService
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(LabelsService));
private readonly Serilog.ILogger Log = Serilog.Log.Logger;

private const int MaxLabels = 64;
private const int MaxLength = 255;
Expand Down Expand Up @@ -45,18 +45,18 @@ private IEnumerable<Label> GetLabelsFromConfiguration()
.ToList();

if (labels.Count == MaxLabels)
Log.WarnFormat("Maximum number of labels reached, some may have been dropped.");
Log.Warning("Maximum number of labels reached, some may have been dropped.");

return labels;
}
catch (Exception exception)
{
Log.WarnFormat("Failed to parse labels configuration string: {0}", exception);
Log.Warning("Failed to parse labels configuration string: {0}", exception);
return Enumerable.Empty<Label>();
}
}

private static Label CreateLabelFromString(string typeAndValueString)
private Label CreateLabelFromString(string typeAndValueString)
{
if (typeAndValueString == null)
throw new ArgumentNullException("typeAndValueString");
Expand Down Expand Up @@ -87,11 +87,11 @@ private static Label CreateLabelFromString(string typeAndValueString)
return new Label(typeTruncated, valueTruncated);
}

private static string Truncate(string value)
private string Truncate(string value)
{
var result = value.TruncateUnicodeStringByLength(MaxLength);
if (result.Length != value.Length)
Log.WarnFormat("Truncated label key from {0} to {1}", value, result);
Log.Warning("Truncated label key from {0} to {1}", value, result);

return result;
}
Expand Down
26 changes: 22 additions & 4 deletions src/Agent/NewRelic/Agent/Core/Logging/AuditLog.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,37 @@
// Copyright 2020 New Relic, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

using System;
using Serilog;
using ILogger = Serilog.ILogger;

namespace NewRelic.Agent.Core.Logging
{
public static class AuditLog
{
private static readonly log4net.ILog Logger = log4net.LogManager.GetLogger(typeof(AuditLog));
// a lazy ILogger instance that injects an "Audit" property
private static Lazy<ILogger> _lazyAuditLogger = new Lazy<ILogger>(() =>
Serilog.Log.Logger.ForContext(LogLevelExtensions.AuditLevel, LogLevelExtensions.AuditLevel));

/// <summary>
/// Logs <paramref name="message"/> at the AUDIT level, a custom log level that is not well-defined in popular logging providers like log4net. This log level should be used only as dictated by the security team to satisfy auditing requirements.
/// Logs <paramref name="message"/> at the AUDIT level. This log level should be used only as dictated by the security team to satisfy auditing requirements.
/// </summary>
public static void Log(string message)
{
var auditLogLevel = LoggerBootstrapper.GetAuditLevel();
Logger.Logger.Log(typeof(AuditLog), auditLogLevel, message, null);
// use Fatal log level to ensure audit log messages never get filtered due to level restrictions
_lazyAuditLogger.Value.Fatal(message);
}

internal static LoggerConfiguration IncludeOnlyAuditLog(this LoggerConfiguration loggerConfiguration)
{
return loggerConfiguration.Filter.ByIncludingOnly($"{LogLevelExtensions.AuditLevel} is not null");

//return loggerConfiguration.Filter.ByIncludingOnly(logEvent =>
// logEvent.Properties.ContainsKey(LogLevelExtensions.AuditLevel));
}
internal static LoggerConfiguration ExcludeAuditLog(this LoggerConfiguration loggerConfiguration)
{
return loggerConfiguration.Filter.ByIncludingOnly($"{LogLevelExtensions.AuditLevel} is null");
}
}
}
45 changes: 45 additions & 0 deletions src/Agent/NewRelic/Agent/Core/Logging/InMemorySink.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2020 New Relic, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

using System;
using Serilog.Core;
using Serilog.Events;
using System.Collections.Concurrent;
using System.Collections.Generic;

namespace NewRelic.Agent.Core.Logging
{
public class InMemorySink : ILogEventSink, IDisposable
{
private readonly ConcurrentQueue<LogEvent> _logEvents;

public InMemorySink()
{
_logEvents = new ConcurrentQueue<LogEvent>();
}

public void Emit(LogEvent logEvent)
{
_logEvents.Enqueue(logEvent);
}

public IEnumerable<LogEvent> LogEvents
{
get
{
return _logEvents;
}
}

public void Clear()
{
while (_logEvents.TryDequeue(out _))
{ }
}

public void Dispose()
{
Clear();
}
}
}
Loading

0 comments on commit 51080df

Please sign in to comment.