Skip to content

Commit e40e282

Browse files
committed
Changed strategy preventing "Feedback Loop" on log events / trace listeners.
1 parent 59a32ed commit e40e282

13 files changed

Lines changed: 130 additions & 141 deletions

File tree

Source/NuLog.Samples/CustomizeSamples/S2_3_AddingMetaData/ColorConsoleTarget.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,12 @@ public override void Log(LogEvent logEvent)
6464

6565
try
6666
{
67+
// Feedback loop prevention
68+
var silent = logEvent != null && logEvent.Silent;
69+
6770
// Set the colors to our custom colors
68-
Console.BackgroundColor = GetConsoleColor(logEvent, BackgroundColorMeta, ColorConfig.BackgroundColor);
69-
Console.ForegroundColor = GetConsoleColor(logEvent, ForegroundColorMeta, ColorConfig.ForegroundColor);
71+
Console.BackgroundColor = GetConsoleColor(logEvent, BackgroundColorMeta, ColorConfig.BackgroundColor, silent);
72+
Console.ForegroundColor = GetConsoleColor(logEvent, ForegroundColorMeta, ColorConfig.ForegroundColor, silent);
7073

7174
// Write out our message
7275
Console.Out.Write(Layout.FormatLogEvent(logEvent));
@@ -81,7 +84,7 @@ public override void Log(LogEvent logEvent)
8184
}
8285

8386
// Figures the console color we need based on the meta data of the log event, and the passed default color
84-
private static ConsoleColor GetConsoleColor(LogEvent logEvent, string metaDataKey, ConsoleColor defaultColor)
87+
private static ConsoleColor GetConsoleColor(LogEvent logEvent, string metaDataKey, ConsoleColor defaultColor, bool silent)
8588
{
8689
// Try and return the console color from the metea data
8790
if (logEvent.MetaData != null && logEvent.MetaData.ContainsKey(metaDataKey))
@@ -92,7 +95,9 @@ private static ConsoleColor GetConsoleColor(LogEvent logEvent, string metaDataKe
9295
}
9396
catch
9497
{
95-
Trace.WriteLine(String.Format(ConsoleColorParseFailedMessage, metaDataKey));
98+
// Prevent feedback loops:
99+
if(!silent)
100+
Trace.WriteLine(String.Format(ConsoleColorParseFailedMessage, metaDataKey));
96101
}
97102
}
98103

Source/NuLog.Samples/CustomizeSamples/S2_4_ShuttingDownTheTarget/ColorConsoleTarget.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,12 @@ public override void Log(LogEvent logEvent)
6464

6565
try
6666
{
67+
// Feedback loop prevention
68+
var silent = logEvent != null && logEvent.Silent;
69+
6770
// Set the colors to our custom colors
68-
Console.BackgroundColor = GetConsoleColor(logEvent, BackgroundColorMeta, ColorConfig.BackgroundColor);
69-
Console.ForegroundColor = GetConsoleColor(logEvent, ForegroundColorMeta, ColorConfig.ForegroundColor);
71+
Console.BackgroundColor = GetConsoleColor(logEvent, BackgroundColorMeta, ColorConfig.BackgroundColor, silent);
72+
Console.ForegroundColor = GetConsoleColor(logEvent, ForegroundColorMeta, ColorConfig.ForegroundColor, silent);
7073

7174
// Write out our message
7275
Console.Out.Write(Layout.FormatLogEvent(logEvent));
@@ -81,7 +84,7 @@ public override void Log(LogEvent logEvent)
8184
}
8285

8386
// Figures the console color we need based on the meta data of the log event, and the passed default color
84-
private static ConsoleColor GetConsoleColor(LogEvent logEvent, string metaDataKey, ConsoleColor defaultColor)
87+
private static ConsoleColor GetConsoleColor(LogEvent logEvent, string metaDataKey, ConsoleColor defaultColor, bool silent)
8588
{
8689
// Try and return the console color from the metea data
8790
if (logEvent.MetaData != null && logEvent.MetaData.ContainsKey(metaDataKey))
@@ -92,7 +95,8 @@ private static ConsoleColor GetConsoleColor(LogEvent logEvent, string metaDataKe
9295
}
9396
catch
9497
{
95-
Trace.WriteLine(String.Format(ConsoleColorParseFailedMessage, metaDataKey));
98+
if(!silent)
99+
Trace.WriteLine(String.Format(ConsoleColorParseFailedMessage, metaDataKey));
96100
}
97101
}
98102

Source/NuLog.Samples/CustomizeSamples/S2_5_AsynchronousLoggingInTheTarget/ColorConsoleTarget.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,12 @@ public override void Log(LogEvent logEvent)
6666

6767
try
6868
{
69+
// Feedback loop prevention
70+
bool silent = logEvent != null && logEvent.Silent;
71+
6972
// Set the colors to our custom colors
70-
Console.BackgroundColor = GetConsoleColor(logEvent, BackgroundColorMeta, ColorConfig.BackgroundColor);
71-
Console.ForegroundColor = GetConsoleColor(logEvent, ForegroundColorMeta, ColorConfig.ForegroundColor);
73+
Console.BackgroundColor = GetConsoleColor(logEvent, BackgroundColorMeta, ColorConfig.BackgroundColor, silent);
74+
Console.ForegroundColor = GetConsoleColor(logEvent, ForegroundColorMeta, ColorConfig.ForegroundColor, silent);
7275

7376
// Write out our message
7477
Console.Out.Write(Layout.FormatLogEvent(logEvent));
@@ -101,8 +104,8 @@ protected override void ProcessLogQueue(ConcurrentQueue<LogEvent> logQueue, LogE
101104
if (logQueue.TryDequeue(out logEvent))
102105
{
103106
// Figure out what our colors should be
104-
newBackground = GetConsoleColor(logEvent, BackgroundColorMeta, ColorConfig.BackgroundColor);
105-
newForeground = GetConsoleColor(logEvent, ForegroundColorMeta, ColorConfig.ForegroundColor);
107+
newBackground = GetConsoleColor(logEvent, BackgroundColorMeta, ColorConfig.BackgroundColor, logEvent.Silent);
108+
newForeground = GetConsoleColor(logEvent, ForegroundColorMeta, ColorConfig.ForegroundColor, logEvent.Silent);
106109
formattedLogEvent = Layout.FormatLogEvent(logEvent);
107110

108111
lock (_colorLock)
@@ -139,7 +142,7 @@ protected override void ProcessLogQueue(ConcurrentQueue<LogEvent> logQueue, LogE
139142
}
140143

141144
// Figures the console color we need based on the meta data of the log event, and the passed default color
142-
private static ConsoleColor GetConsoleColor(LogEvent logEvent, string metaDataKey, ConsoleColor defaultColor)
145+
private static ConsoleColor GetConsoleColor(LogEvent logEvent, string metaDataKey, ConsoleColor defaultColor, bool silent)
143146
{
144147
// Try and return the console color from the metea data
145148
if (logEvent.MetaData != null && logEvent.MetaData.ContainsKey(metaDataKey))
@@ -150,7 +153,8 @@ private static ConsoleColor GetConsoleColor(LogEvent logEvent, string metaDataKe
150153
}
151154
catch
152155
{
153-
Trace.WriteLine(String.Format(ConsoleColorParseFailedMessage, metaDataKey));
156+
if(!silent)
157+
Trace.WriteLine(String.Format(ConsoleColorParseFailedMessage, metaDataKey));
154158
}
155159
}
156160

Source/NuLog.Samples/CustomizeSamples/S3_1_ExtendingTheLogger/ColorConsoleTarget.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,12 @@ public override void Log(LogEvent logEvent)
6464

6565
try
6666
{
67+
// Feedback loop prevention
68+
bool silent = logEvent != null && logEvent.Silent;
69+
6770
// Set the colors to our custom colors
68-
Console.BackgroundColor = GetConsoleColor(logEvent, BackgroundColorMeta, ColorConfig.BackgroundColor);
69-
Console.ForegroundColor = GetConsoleColor(logEvent, ForegroundColorMeta, ColorConfig.ForegroundColor);
71+
Console.BackgroundColor = GetConsoleColor(logEvent, BackgroundColorMeta, ColorConfig.BackgroundColor, silent);
72+
Console.ForegroundColor = GetConsoleColor(logEvent, ForegroundColorMeta, ColorConfig.ForegroundColor, silent);
7073

7174
// Write out our message
7275
Console.Out.Write(Layout.FormatLogEvent(logEvent));
@@ -81,7 +84,7 @@ public override void Log(LogEvent logEvent)
8184
}
8285

8386
// Figures the console color we need based on the meta data of the log event, and the passed default color
84-
private static ConsoleColor GetConsoleColor(LogEvent logEvent, string metaDataKey, ConsoleColor defaultColor)
87+
private static ConsoleColor GetConsoleColor(LogEvent logEvent, string metaDataKey, ConsoleColor defaultColor, bool silent)
8588
{
8689
// Try and return the console color from the metea data
8790
if (logEvent.MetaData != null && logEvent.MetaData.ContainsKey(metaDataKey))
@@ -92,7 +95,9 @@ private static ConsoleColor GetConsoleColor(LogEvent logEvent, string metaDataKe
9295
}
9396
catch
9497
{
95-
Trace.WriteLine(String.Format(ConsoleColorParseFailedMessage, metaDataKey));
98+
// Feedback Loop Prevention
99+
if(!silent)
100+
Trace.WriteLine(String.Format(ConsoleColorParseFailedMessage, metaDataKey));
96101
}
97102
}
98103

Source/NuLog.Samples/CustomizeSamples/S8_1_CustomExtender/CustomExtenderSample.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public override void ExecuteSample()
3535
// This should be caught by our extender and written to
3636
// console because of the rules in our configuration.
3737
Trace.WriteLine("Hello, World!");
38+
Debug.WriteLine("Hello, Debug!");
3839
}
3940

4041
}

Source/NuLog.Samples/CustomizeSamples/S8_1_CustomExtender/NuLog.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
},
1818
{
1919
"include": [ "*" ],
20-
"exclude": [ "tracelistener" ],
2120
"writeTo": [ "trace" ]
2221
}
2322
],

Source/NuLog.Samples/CustomizeSamples/S8_1_CustomExtender/TraceListenerExtender.cs

Lines changed: 42 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,6 @@ internal class InternalTraceListener : TraceListener
4343
private string[] _tags;
4444
private StringBuilder _stringBuilder;
4545

46-
// Bits to help prevent a "feedback" loop, just in case one of our
47-
// listening targets writes to trace
48-
private static readonly IDictionary<string, object> _dontTraceMeta
49-
= new Dictionary<string, object> { { TraceTarget.DontTraceMeta, true } };
50-
private string _guid;
51-
5246
#endregion
5347

5448
/// <summary>
@@ -59,28 +53,12 @@ private static readonly IDictionary<string, object> _dontTraceMeta
5953
public InternalTraceListener(TraceListenerExtender extender)
6054
: base()
6155
{
62-
// Prepare our GUID and string builder
63-
_guid = String.Format("TL-{0}", Guid.NewGuid().ToString());
56+
// Prepare the String Builder
6457
_stringBuilder = new StringBuilder();
6558

6659
// We want to get the tags from the config
67-
// We also want to add the guid to the tag list
68-
// to maximize the chance that the GUID will be
69-
// in the resulting message
70-
if (extender != null
71-
&& extender.TraceListenerConfig != null
72-
&& extender.TraceListenerConfig.TraceTags != null)
73-
{
74-
// We have been provided other tags, merge them with our GUID
75-
var tagList = extender.TraceListenerConfig.TraceTags.ToList();
76-
tagList.Add(_guid);
77-
_tags = tagList.ToArray();
78-
}
79-
else
80-
{
81-
// We don't have any other tags, just include our GUID
82-
_tags = new string[] { _guid };
83-
}
60+
if (extender != null && extender.TraceListenerConfig != null)
61+
_tags = extender.TraceListenerConfig.TraceTags;
8462
}
8563

8664
/// <summary>
@@ -93,42 +71,38 @@ public override void Write(string message)
9371
{
9472
// Make sure that we have a message
9573
if(String.IsNullOrEmpty(message) == false)
96-
// Check for a feedback loop
97-
if (message.Contains(_guid) == false)
74+
lock (WriteLock)
9875
{
99-
lock (WriteLock)
76+
// If the message has no newline, just queue it up
77+
if (!message.Contains(Environment.NewLine))
10078
{
101-
// If the message has no newline, just queue it up
102-
if (!message.Contains(Environment.NewLine))
79+
_stringBuilder.Append(message);
80+
}
81+
// The message contains at least one newline, split it up
82+
else
83+
{
84+
// Setup
85+
bool endsNewline = message.EndsWith(Environment.NewLine);
86+
var parts = message.Split(Split);
87+
88+
// Append, and write the first part
89+
// unless it is the only part and we have no newline at the end
90+
_stringBuilder.Append(parts[0]);
91+
if (parts.Length > 1 || endsNewline)
10392
{
104-
_stringBuilder.Append(message);
93+
WriteLine(_stringBuilder.ToString());
94+
_stringBuilder.Clear();
10595
}
106-
// The message contains at least one newline, split it up
107-
else
96+
97+
// Write out each of the child parts if there are more, queuing the last bit if
98+
// it isn't followed by a newline
99+
if (parts.Length > 1)
108100
{
109-
// Setup
110-
bool endsNewline = message.EndsWith(Environment.NewLine);
111-
var parts = message.Split(Split);
112-
113-
// Append, and write the first part
114-
// unless it is the only part and we have no newline at the end
115-
_stringBuilder.Append(parts[0]);
116-
if (parts.Length > 1 || endsNewline)
117-
{
118-
WriteLine(_stringBuilder.ToString());
119-
_stringBuilder.Clear();
120-
}
121-
122-
// Write out each of the child parts if there are more, queuing the last bit if
123-
// it isn't followed by a newline
124-
if (parts.Length > 1)
125-
{
126-
for (int index = 1; index < (endsNewline ? parts.Length : parts.Length - 1); index++)
127-
WriteLine(parts[index]);
128-
129-
if (endsNewline == false)
130-
_stringBuilder.Append(parts[parts.Length - 1]);
131-
}
101+
for (int index = 1; index < (endsNewline ? parts.Length : parts.Length - 1); index++)
102+
WriteLine(parts[index]);
103+
104+
if (endsNewline == false)
105+
_stringBuilder.Append(parts[parts.Length - 1]);
132106
}
133107
}
134108
}
@@ -142,17 +116,17 @@ public override void WriteLine(string message)
142116
{
143117
// Ignore this request if the message is empty
144118
if (String.IsNullOrEmpty(message) == false)
145-
// Check for a feedback loop
146-
if (message.Contains(_guid) == false)
119+
lock (WriteLock)
147120
{
148-
lock (WriteLock)
121+
// Write the contents of the buffer out, followed by the message
122+
_logger.LogNow(new LogEvent
149123
{
150-
// Write the contents of the buffer out, followed by the message
151-
// We include the meta data recognized by NuLog.Targets.TraceTarget as a flag to not trace
152-
// We include the GUID in the message, and as a tag here to also help prevent a feedback loop
153-
_logger.LogNow(String.Format("{0}: {1}{2}", _guid, _stringBuilder.ToString(), message), _dontTraceMeta, _tags);
154-
_stringBuilder.Clear();
155-
}
124+
Message = String.Format("{0}{1}", _stringBuilder.ToString(), message),
125+
Tags = _tags,
126+
// Help prevent feedback loops:
127+
Silent = true
128+
});
129+
_stringBuilder.Clear();
156130
}
157131
}
158132

@@ -221,12 +195,13 @@ public override bool Shutdown(int timeout = DefaultShutdownTimeout, Stopwatch st
221195
if (_traceListener != null)
222196
{
223197
_traceListener.Flush();
198+
_traceListener.Close();
199+
_traceListener.Dispose();
224200
Trace.Listeners.Remove(_traceListener);
225201
_traceListener = null;
226202
}
227-
return true;
203+
return base.Shutdown();
228204
}
229205

230-
231206
}
232207
}

Source/NuLog/Configuration/Targets/ConsoleColorRule.cs

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ public class ConsoleColorRule
2222

2323
#region Constants
2424

25-
private const string CannotParseColorMessage = "Failed to parse console color \"{0}\" because {1}";
26-
2725
private static readonly Type ConsoleColorType = typeof(ConsoleColor);
2826

2927
#endregion
@@ -66,8 +64,8 @@ public ConsoleColorRule(string backgroundColor, string foregroundColor, params s
6664
? tags.ToList()
6765
: new List<string>();
6866

69-
BackgroundColor = GetConsoleColor(backgroundColor);
70-
ForegroundColor = GetConsoleColor(foregroundColor);
67+
BackgroundColor = (ConsoleColor)Enum.Parse(ConsoleColorType, backgroundColor); ;
68+
ForegroundColor = (ConsoleColor)Enum.Parse(ConsoleColorType, foregroundColor); ;
7169
}
7270

7371
/// <summary>
@@ -85,25 +83,5 @@ public ConsoleColorRule(string backgroundColor, string foregroundColor, params s
8583
/// </summary>
8684
public ConsoleColor? BackgroundColor { get; set; }
8785

88-
#region Helpers
89-
90-
// Converts the given string into a ConsoleColor, returns null if it fails
91-
private static ConsoleColor? GetConsoleColor(string consoleColorString)
92-
{
93-
ConsoleColor? result = null;
94-
95-
try
96-
{
97-
result = (ConsoleColor)Enum.Parse(ConsoleColorType, consoleColorString);
98-
}
99-
catch(Exception cause)
100-
{
101-
Trace.WriteLine(String.Format(CannotParseColorMessage, consoleColorString, cause));
102-
}
103-
104-
return result;
105-
}
106-
107-
#endregion
10886
}
10987
}

Source/NuLog/Dispatch/LogEventDispatcher.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,8 @@ private void ExecuteStaticMetaDataProviders(LogEvent logEvent)
442442
}
443443
catch (Exception ex)
444444
{
445-
Trace.WriteLine(String.Format("Failure executing static metadata provider {0}: {1}:\r\n{2}", staticMetaDataProvider.GetType().FullName, ex.Message, ex.StackTrace), TraceConfigCategory);
445+
if(logEvent == null || logEvent.Silent == false)
446+
Trace.WriteLine(String.Format("Failure executing static metadata provider {0}: {1}:\r\n{2}", staticMetaDataProvider.GetType().FullName, ex.Message, ex.StackTrace), TraceConfigCategory);
446447
}
447448
}
448449
}
@@ -504,7 +505,8 @@ public void HandleException(Exception e, LogEvent logEventInfo = null)
504505
if (ExceptionHandler != null)
505506
ExceptionHandler.Invoke(e, message);
506507
else
507-
Trace.WriteLine(message);
508+
if(logEventInfo == null || logEventInfo.Silent == false)
509+
Trace.WriteLine(message);
508510
}
509511

510512
// Helper function for flattening strings into a single string

0 commit comments

Comments
 (0)