Skip to content

Commit 51080df

Browse files
authored
feat: Use Serilog instead of log4net for internal logging. (#1661)
1 parent 0882d47 commit 51080df

35 files changed

+1090
-1113
lines changed

src/Agent/NewRelic/Agent/Core/AgentInitializer.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ private static class CallOnce
2626
{
2727
static CallOnce()
2828
{
29-
// we must ensure that we hook up to ProcessExit and DomainUnload *before* log4net. Otherwise we can't log anything during OnExit.
29+
// we must ensure that we hook up to ProcessExit and DomainUnload *before* log initialization. Otherwise we can't log anything during OnExit.
3030
AppDomain.CurrentDomain.ProcessExit += (sender, args) => OnExit(sender, args);
3131
AppDomain.CurrentDomain.DomainUnload += (sender, args) => OnExit(sender, args);
3232
LoggerBootstrapper.Initialize();

src/Agent/NewRelic/Agent/Core/Config/Configuration.cs

-57
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,6 @@
99
// ------------------------------------------------------------------------------
1010
namespace NewRelic.Agent.Core.Config
1111
{
12-
using System;
13-
using System.Diagnostics;
14-
using System.Xml.Serialization;
15-
using System.Collections;
16-
using System.Xml.Schema;
17-
using System.ComponentModel;
1812
using System.Collections.Generic;
1913

2014

@@ -1301,8 +1295,6 @@ public partial class configurationLog
13011295

13021296
private bool auditLogField;
13031297

1304-
private System.Nullable<configurationLogFileLockingModel> fileLockingModelField;
1305-
13061298
/// <summary>
13071299
/// configurationLog class constructor
13081300
/// </summary>
@@ -1381,42 +1373,6 @@ public bool auditLog
13811373
}
13821374
}
13831375

1384-
[System.Xml.Serialization.XmlAttributeAttribute()]
1385-
public configurationLogFileLockingModel fileLockingModel
1386-
{
1387-
get
1388-
{
1389-
if (this.fileLockingModelField.HasValue)
1390-
{
1391-
return this.fileLockingModelField.Value;
1392-
}
1393-
else
1394-
{
1395-
return default(configurationLogFileLockingModel);
1396-
}
1397-
}
1398-
set
1399-
{
1400-
this.fileLockingModelField = value;
1401-
}
1402-
}
1403-
1404-
[System.Xml.Serialization.XmlIgnoreAttribute()]
1405-
public bool fileLockingModelSpecified
1406-
{
1407-
get
1408-
{
1409-
return this.fileLockingModelField.HasValue;
1410-
}
1411-
set
1412-
{
1413-
if (value==false)
1414-
{
1415-
this.fileLockingModelField = null;
1416-
}
1417-
}
1418-
}
1419-
14201376
#region Clone method
14211377
/// <summary>
14221378
/// Create a clone of this configurationLog object
@@ -1428,19 +1384,6 @@ public virtual configurationLog Clone()
14281384
#endregion
14291385
}
14301386

1431-
[System.CodeDom.Compiler.GeneratedCodeAttribute("Xsd2Code", "3.6.0.20097")]
1432-
[System.SerializableAttribute()]
1433-
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:newrelic-config")]
1434-
public enum configurationLogFileLockingModel
1435-
{
1436-
1437-
/// <remarks/>
1438-
exclusive,
1439-
1440-
/// <remarks/>
1441-
minimal,
1442-
}
1443-
14441387
[System.CodeDom.Compiler.GeneratedCodeAttribute("Xsd2Code", "3.6.0.20097")]
14451388
[System.SerializableAttribute()]
14461389
[System.ComponentModel.DesignerCategoryAttribute("code")]

src/Agent/NewRelic/Agent/Core/Config/Configuration.xsd

-13
Original file line numberDiff line numberDiff line change
@@ -347,19 +347,6 @@
347347
</xs:annotation>
348348
</xs:attribute>
349349

350-
<xs:attribute name="fileLockingModel">
351-
<xs:annotation>
352-
<xs:documentation>
353-
Controls how agent-produced log files are to be locked. Experimental.
354-
</xs:documentation>
355-
</xs:annotation>
356-
<xs:simpleType>
357-
<xs:restriction base="xs:string">
358-
<xs:enumeration value="exclusive"/>
359-
<xs:enumeration value="minimal"/>
360-
</xs:restriction>
361-
</xs:simpleType>
362-
</xs:attribute>
363350
</xs:complexType>
364351
</xs:element>
365352

src/Agent/NewRelic/Agent/Core/Config/ConfigurationLoader.cs

-16
Original file line numberDiff line numberDiff line change
@@ -586,22 +586,6 @@ private string GetLogFileName()
586586
return "newrelic_agent_" + Strings.SafeFileName(name) + ".log";
587587
}
588588

589-
public bool FileLockingModelSpecified
590-
{
591-
get
592-
{
593-
return fileLockingModelSpecified;
594-
}
595-
}
596-
597-
public configurationLogFileLockingModel FileLockingModel
598-
{
599-
get
600-
{
601-
return fileLockingModel;
602-
}
603-
}
604-
605589
public bool Console
606590
{
607591
get

src/Agent/NewRelic/Agent/Core/Config/ILogConfig.cs

-3
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ public interface ILogConfig
99

1010
string GetFullLogFileName();
1111

12-
bool FileLockingModelSpecified { get; }
13-
configurationLogFileLockingModel FileLockingModel { get; }
14-
1512
bool Console { get; }
1613

1714
bool IsAuditLogEnabled { get; }

src/Agent/NewRelic/Agent/Core/Configuration/ConfigurationService.cs

+2-9
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,8 @@ private void OnConfigurationDeserialized(ConfigurationDeserializedEvent configur
6363

6464
private static void UpdateLogLevel(configuration localConfiguration)
6565
{
66-
var hierarchy = log4net.LogManager.GetRepository(Assembly.GetCallingAssembly()) as log4net.Repository.Hierarchy.Hierarchy;
67-
var logger = hierarchy.Root;
68-
69-
var logLevel = logger.Hierarchy.LevelMap[localConfiguration.LogConfig.LogLevel];
70-
if (logLevel != null && logLevel != logger.Level)
71-
{
72-
Log.InfoFormat("The log level was updated to {0}", logLevel);
73-
logger.Level = logLevel;
74-
}
66+
Log.InfoFormat("The log level was updated to {0}", localConfiguration.LogConfig.LogLevel);
67+
LoggerBootstrapper.UpdateLoggingLevel(localConfiguration.LogConfig.LogLevel);
7568
}
7669

7770
private void OnServerConfigurationUpdated(ServerConfigurationUpdatedEvent serverConfigurationUpdatedEvent)

src/Agent/NewRelic/Agent/Core/Core.csproj

+22-10
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,14 @@
3737
<PrivateAssets>all</PrivateAssets>
3838
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
3939
</PackageReference>
40+
<PackageReference Include="Serilog" Version="2.12.0" />
41+
<PackageReference Include="Serilog.Expressions" Version="3.4.1" />
42+
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
43+
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
44+
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
45+
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
4046
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
4147
<PackageReference Include="ILRepack" Version="2.0.16" />
42-
<PackageReference Include="log4net" Version="2.0.8" />
4348
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
4449
<PackageReference Include="SharpZipLib" Version="1.3.3" />
4550
</ItemGroup>
@@ -56,6 +61,7 @@
5661
<PackageReference Include="Castle.Core" Version="3.3.0" />
5762
<PackageReference Include="Castle.Windsor" Version="3.3.0" />
5863
<PackageReference Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" />
64+
<PackageReference Include="Serilog.Sinks.EventLog" Version="3.1.0" />
5965
</ItemGroup>
6066

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

82-
<ItemGroup>
83-
<Compile Include="$(RootProjectDirectory)\src\Agent\Shared\SharedLog4NetRepository.cs">
84-
<Link>Properties\SharedLog4NetRepository.cs</Link>
85-
</Compile>
86-
</ItemGroup>
8788
<ItemGroup>
8889
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
8990
</ItemGroup>
@@ -105,8 +106,14 @@
105106
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Castle.Core'" />
106107
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Castle.Windsor'" />
107108
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'ICSharpCode.SharpZipLib'" />
108-
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'log4net'" />
109109
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Newtonsoft.Json'" />
110+
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog'" />
111+
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Expressions'" />
112+
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.Async'" />
113+
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.Console'" />
114+
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.Debug'" />
115+
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.EventLog'" />
116+
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.File'" />
110117
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'System.ValueTuple'" />
111118
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'System.Memory'" />
112119
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'System.Runtime.CompilerServices.Unsafe'" />
@@ -120,14 +127,19 @@
120127
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Grpc.Net.Common'" />
121128
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Grpc.Net.Client'" />
122129
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Autofac'" />
123-
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'log4net'" />
124130
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Newtonsoft.Json'" />
131+
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog'" />
132+
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Expressions'" />
133+
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.Async'" />
134+
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.Console'" />
135+
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.Debug'" />
136+
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'Serilog.Sinks.File'" />
125137
<ILRepackInclude Include="@(PossibleRefsForILRepack)" Condition="'%(FileName)' == 'ICSharpCode.SharpZipLib'" />
126138
</ItemGroup>
127139

128140
<PropertyGroup>
129-
<ILRepackIncludeCount Condition="'$(TargetFramework)' == 'net462'">15</ILRepackIncludeCount>
130-
<ILRepackIncludeCount Condition="'$(TargetFramework)' == 'netstandard2.0'">11</ILRepackIncludeCount>
141+
<ILRepackIncludeCount Condition="'$(TargetFramework)' == 'net462'">21</ILRepackIncludeCount>
142+
<ILRepackIncludeCount Condition="'$(TargetFramework)' == 'netstandard2.0'">16</ILRepackIncludeCount>
131143
</PropertyGroup>
132144

133145
<Error Text="ILRepack of $(AssemblyName) ($(TargetFramework)) failed. A dependency is missing. Expected $(ILRepackIncludeCount) dependencies but found @(ILRepackInclude-&gt;Count())." Condition="@(ILRepackInclude-&gt;Count()) != $(ILRepackIncludeCount)" />

src/Agent/NewRelic/Agent/Core/Labels/LabelsService.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace NewRelic.Agent.Core.Labels
1212
{
1313
public class LabelsService : ILabelsService
1414
{
15-
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(LabelsService));
15+
private readonly Serilog.ILogger Log = Serilog.Log.Logger;
1616

1717
private const int MaxLabels = 64;
1818
private const int MaxLength = 255;
@@ -45,18 +45,18 @@ private IEnumerable<Label> GetLabelsFromConfiguration()
4545
.ToList();
4646

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

5050
return labels;
5151
}
5252
catch (Exception exception)
5353
{
54-
Log.WarnFormat("Failed to parse labels configuration string: {0}", exception);
54+
Log.Warning("Failed to parse labels configuration string: {0}", exception);
5555
return Enumerable.Empty<Label>();
5656
}
5757
}
5858

59-
private static Label CreateLabelFromString(string typeAndValueString)
59+
private Label CreateLabelFromString(string typeAndValueString)
6060
{
6161
if (typeAndValueString == null)
6262
throw new ArgumentNullException("typeAndValueString");
@@ -87,11 +87,11 @@ private static Label CreateLabelFromString(string typeAndValueString)
8787
return new Label(typeTruncated, valueTruncated);
8888
}
8989

90-
private static string Truncate(string value)
90+
private string Truncate(string value)
9191
{
9292
var result = value.TruncateUnicodeStringByLength(MaxLength);
9393
if (result.Length != value.Length)
94-
Log.WarnFormat("Truncated label key from {0} to {1}", value, result);
94+
Log.Warning("Truncated label key from {0} to {1}", value, result);
9595

9696
return result;
9797
}
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,37 @@
11
// Copyright 2020 New Relic, Inc. All rights reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
using System;
5+
using Serilog;
6+
using ILogger = Serilog.ILogger;
7+
48
namespace NewRelic.Agent.Core.Logging
59
{
610
public static class AuditLog
711
{
8-
private static readonly log4net.ILog Logger = log4net.LogManager.GetLogger(typeof(AuditLog));
12+
// a lazy ILogger instance that injects an "Audit" property
13+
private static Lazy<ILogger> _lazyAuditLogger = new Lazy<ILogger>(() =>
14+
Serilog.Log.Logger.ForContext(LogLevelExtensions.AuditLevel, LogLevelExtensions.AuditLevel));
915

1016
/// <summary>
11-
/// 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.
17+
/// 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.
1218
/// </summary>
1319
public static void Log(string message)
1420
{
15-
var auditLogLevel = LoggerBootstrapper.GetAuditLevel();
16-
Logger.Logger.Log(typeof(AuditLog), auditLogLevel, message, null);
21+
// use Fatal log level to ensure audit log messages never get filtered due to level restrictions
22+
_lazyAuditLogger.Value.Fatal(message);
23+
}
24+
25+
internal static LoggerConfiguration IncludeOnlyAuditLog(this LoggerConfiguration loggerConfiguration)
26+
{
27+
return loggerConfiguration.Filter.ByIncludingOnly($"{LogLevelExtensions.AuditLevel} is not null");
28+
29+
//return loggerConfiguration.Filter.ByIncludingOnly(logEvent =>
30+
// logEvent.Properties.ContainsKey(LogLevelExtensions.AuditLevel));
31+
}
32+
internal static LoggerConfiguration ExcludeAuditLog(this LoggerConfiguration loggerConfiguration)
33+
{
34+
return loggerConfiguration.Filter.ByIncludingOnly($"{LogLevelExtensions.AuditLevel} is null");
1735
}
1836
}
1937
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2020 New Relic, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using System;
5+
using Serilog.Core;
6+
using Serilog.Events;
7+
using System.Collections.Concurrent;
8+
using System.Collections.Generic;
9+
10+
namespace NewRelic.Agent.Core.Logging
11+
{
12+
public class InMemorySink : ILogEventSink, IDisposable
13+
{
14+
private readonly ConcurrentQueue<LogEvent> _logEvents;
15+
16+
public InMemorySink()
17+
{
18+
_logEvents = new ConcurrentQueue<LogEvent>();
19+
}
20+
21+
public void Emit(LogEvent logEvent)
22+
{
23+
_logEvents.Enqueue(logEvent);
24+
}
25+
26+
public IEnumerable<LogEvent> LogEvents
27+
{
28+
get
29+
{
30+
return _logEvents;
31+
}
32+
}
33+
34+
public void Clear()
35+
{
36+
while (_logEvents.TryDequeue(out _))
37+
{ }
38+
}
39+
40+
public void Dispose()
41+
{
42+
Clear();
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)