Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change, It's now possible to configure number of inner exceptions to be sent #14

Merged
merged 2 commits into from Nov 14, 2018
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

Change, It's now possible to configure number of inner exceptions to …

…be sent

Sometimes you need more than the default number of inner exceptions.
This is now possible to configurate.

<numberOfInnerExceptions value="4"/>

Default value is not changed, it's still one.
  • Loading branch information
ChiliMonanta
ChiliMonanta committed Dec 19, 2017
commit 1961574964c9518f5f1582193d5dd56771202c59
@@ -23,6 +23,7 @@ Add the following code in your web.config to configure LogglyAppender in your ap
<tag value="your-custom-tag" />
<logicalThreadContextKeys value="lkey1,lkey2" /> <!-- optional -->
<globalContextKeys value="gkey1,gkey2" /> <!-- optional -->
<numberOfInnerExceptions value value="4"/> <!-- optional -->
</appender>
</log4net>
```
@@ -47,6 +48,10 @@ By default, library uses Loggly /bulk end point (https://www.loggly.com/docs/htt
<logMode value="inputs" />
```
Set number of inner exceptions that should be sent to loggly, if you don't want the default value.
```
<numberOfInnerExceptions value value="4"/>
```
Add the following entry in your AssemblyInfo.cs
```
@@ -15,6 +15,7 @@
<tag value="log4net-test" />
<logicalThreadContextKeys value="LogicalThread1,InnerLogicalThreadContext" />
<globalContextKeys value="GlobalContextPropertySample" />
<numberOfInnerExceptions value="4"/>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
@@ -77,7 +77,7 @@ static void Main(string[] argArray)
});

newThread2.Start();

//Test self referencing
var parent = new Person { Name = "John Smith" };
var child1 = new Person { Name = "Bob Smith", Parent = parent };
@@ -91,6 +91,36 @@ static void Main(string[] argArray)
log.Info(new TestObject());
log.Info(null);

try
{
try
{
try
{
try
{
throw new Exception("1");
}
catch (Exception e)
{
throw new Exception("2", e);
}
}
catch (Exception e)
{
throw new Exception("3", e);
}
}
catch (Exception e)
{
throw new Exception("4", e);
}
}
catch (Exception e)
{
log.Error("Exception", e);
}

Console.ReadKey();
}
}
@@ -7,7 +7,7 @@
using log4net.Core;
using log4net.loggly;
using log4net.Repository;
using log4net_loggly.UnitTests.Models;
using Models;
using Moq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@@ -304,6 +304,58 @@ public void ShouldSerializeTheException()
stacktrace.Should().NotBeNull("because the exception has a stacktrace");
}

[Theory]
[InlineData(0, 0, 1)]
[InlineData(1, 1, 1)]
[InlineData(2, 1, 1)]
[InlineData(2, 2, 2)]
[InlineData(2, 2, 3)]
[InlineData(3, 3, 3)]
[InlineData(5, 5, 5)]
[InlineData(5, 5, 10)]
public void ShouldSerializeInnerExceptions(int configurationNumberOfInnerExceptions, int expectedNumberOfException, int innerExceptionsToCreate)
{
Exception ex = GetArgumentException(innerExceptionsToCreate + 1);

var evt = new LoggingEvent(
GetType(),
Mock.Of<ILoggerRepository>(),
_fixture.Create("loggerName"),
_fixture.Create<Level>(),
_fixture.Create("message"),
ex);
var instance = _fixture.Create<LogglyFormatter>();
_fixture.Freeze<Mock<ILogglyAppenderConfig>>().SetupGet(x => x.NumberOfInnerExceptions).Returns(configurationNumberOfInnerExceptions);

var result = instance.ToJson(evt);
dynamic json = JObject.Parse(result);

var exception = json.exception;

((object)exception).Should().NotBeNull("because an exception was specified in the event");

// Validate first level
var message = (string)exception.exceptionMessage;
var type = (string)exception.exceptionType;
var stacktrace = (string)exception.stacktrace;
AssertException(message, type, stacktrace, 0);

// Validate inner exceptions
var count = 0;
var innerException = exception.innerException;
while (innerException != null)
{
count++;
message = (string)innerException.innerExceptionMessage;
type = (string)innerException.innerExceptionType;
stacktrace = (string)innerException.innerStacktrace;
AssertException(message, type, stacktrace, count);
innerException = innerException.innerException;
}

count.Should().Be(expectedNumberOfException, "Expects all stacktraces");
}

[Fact]
public void ShouldSerializeThreadContextProperties()
{
@@ -355,6 +407,60 @@ public void ShouldSetMessagePropertyWhenMessageObjectIsString()

message.Should().StartWith("message", "because the MessageObject property value is used");
}

private static ArgumentException GetArgumentException(int numberOfExceptions)
{
try
{
if (--numberOfExceptions > 0)
{
try
{
GetNestedArgumentException(numberOfExceptions);
}
catch (ArgumentException e)
{
throw new ArgumentException("Exception 0", e);
}
}
else
{
throw new ArgumentException("Exception 0");
}
}
catch (ArgumentException e)
{
return e;
}
return null;
}

private static void GetNestedArgumentException(int numberOfExceptions, int deep = 0)
{
deep++;
if (--numberOfExceptions > 0)
{
try
{
GetNestedArgumentException(numberOfExceptions, deep);
}
catch (ArgumentException e)
{
throw new ArgumentException($"Exception {deep}", e);
}
}
else
{
throw new ArgumentException($"Exception {deep}");
}
}

private static void AssertException(string message, string type, string stacktrace, int stackLevel)
{
message.Should().Be($"Exception {stackLevel}", "because an argument exception has a default message");
type.Should().Be(typeof(ArgumentException).FullName, "because we logged an argument exception");
stacktrace.Should().NotBeNull("because the exception has a stacktrace");
}
}
}
}
@@ -11,5 +11,6 @@ public interface ILogglyAppenderConfig
string LogicalThreadContextKeys { get; set; }
string GlobalContextKeys { get; set; }
int BufferSize { get; set; }
int NumberOfInnerExceptions { get; set; }
}
}
@@ -26,6 +26,7 @@ public class LogglyAppender : AppenderSkeleton
public string LogicalThreadContextKeys { set { Config.LogicalThreadContextKeys = value; } }
public string GlobalContextKeys { set { Config.GlobalContextKeys = value; } }
public int BufferSize { set { Config.BufferSize = value; } }
public int NumberOfInnerExceptions { set { Config.NumberOfInnerExceptions = value; } }

private LogglyAsyncHandler LogglyAsync;

@@ -44,6 +44,9 @@ public string LogMode
public string GlobalContextKeys { get; set; }

public int BufferSize { get; set; }

public int NumberOfInnerExceptions { get; set; }

public LogglyAppenderConfig()
{
UserAgent = "loggly-log4net-appender";
@@ -53,6 +56,7 @@ public LogglyAppenderConfig()
LogicalThreadContextKeys = null;
GlobalContextKeys = null;
BufferSize = 500;
NumberOfInnerExceptions = 1;
}
}
}
@@ -80,20 +80,29 @@ private object GetExceptionInfo(LoggingEvent loggingEvent)
exceptionInfo.exceptionType = loggingEvent.ExceptionObject.GetType().FullName;
exceptionInfo.exceptionMessage = loggingEvent.ExceptionObject.Message;
exceptionInfo.stacktrace = loggingEvent.ExceptionObject.StackTrace;
exceptionInfo.innerException =
GetInnerExceptions(loggingEvent.ExceptionObject.InnerException, Config.NumberOfInnerExceptions);

return exceptionInfo;
}

//most of the times dotnet exceptions contain important messages in the inner exceptions
if (loggingEvent.ExceptionObject.InnerException != null)
/// <summary>
/// Return nested exceptions
/// </summary>
/// <param name="innerException">The inner exception</param>
/// <param name="deep">The number of inner exceptions that should be included.</param>
/// <returns></returns>
private object GetInnerExceptions(Exception innerException, int deep)
{
if (innerException == null || deep <= 0) return null;
dynamic ex = new
{
dynamic innerException = new
{
innerExceptionType = loggingEvent.ExceptionObject.InnerException.GetType().FullName,
innerExceptionMessage = loggingEvent.ExceptionObject.InnerException.Message,
innerStacktrace = loggingEvent.ExceptionObject.InnerException.StackTrace
};
exceptionInfo.innerException = innerException;
}

return exceptionInfo;
innerExceptionType = innerException.GetType().FullName,
innerExceptionMessage = innerException.Message,
innerStacktrace = innerException.StackTrace,
innerException = --deep > 0 ? GetInnerExceptions(innerException.InnerException, deep) : null
};
return ex;
}

/// <summary>
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.