[
https://issues.apache.org/jira/browse/LOG4NET-615?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Daniel Lidström updated LOG4NET-615:
------------------------------------
Description:
Hello
I'm trying to create a structured logging format and have a conversion pattern
with a custom converter like this:
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%2thread] %-5level [%property\\{NDC}]
%username - type=%message_checksum %message%newline" />
<converter>
<name value="message_checksum" />
<type value="TestBed.MessageChecksumConverter" />
</converter>
</layout>
The interesting part of course is the message_checksum. For example, I am
logging like this:
Log.Debug("some debugging message");
Log.Info(new \{ Id = 1, Name = "the name" });
Log.InfoFormat("Logging msg \{0}", 1);
Log.InfoFormat("Logging msg \{0}", 2);
Log.InfoFormat("Logging msg \{0}", 3);
I would like the output to be something like this
2018-10-26 11:06:44,564 [ 1] DEBUG [(null)] XXX - type=f6d5 some debugging
message
2018-10-26 11:06:44,638 [ 1] INFO [(null)] XXX - type=e0e3 \{ Id = 1, Name =
the name }
2018-10-26 11:06:44,648 [ 1] INFO [(null)] XXX - type=32a6 Logging msg 1
2018-10-26 11:06:44,656 [ 1] INFO [(null)] XXX - type=32a6 Logging msg 2
2018-10-26 11:06:44,663 [ 1] INFO [(null)] XXX - type=32a6 Logging msg 3
As you can see, I am getting the type=32a6 for the last 3 logging messages.
This allows me to search for all of those, regardless of the parameters given.
For example, I can now search and group the number of errors by their unique
type and know which error is most common in our system.
To implement this, I did the following:
public class MessageChecksumConverter : PatternLayoutConverter
{
private static readonly TraceSource Source = new
TraceSource(nameof(MessageChecksumConverter));
private static readonly MD5 ChecksumGenerator = MD5.Create();
protected override void Convert(TextWriter writer, LoggingEvent
loggingEvent)
{
var output = TryGetHash(loggingEvent);
writer.Write(output);
}
private string TryGetHash(LoggingEvent loggingEvent)
{
string output = string.Empty;
try
{
byte[] hash;
var fmt = loggingEvent.MessageObject as SystemStringFormat;
if (fmt != null)
{
// read fmt.m_format and use that as input for hash
var systemStringFormatType = typeof(SystemStringFormat);
var fieldInfo =
systemStringFormatType.GetField("m_format",
BindingFlags.NonPublic | BindingFlags.Instance);
var formatString = fieldInfo?.GetValue(fmt) as string;
hash =
ChecksumGenerator.ComputeHash(Encoding.ASCII.GetBytes(formatString ??
string.Empty));
}
else
{
var str = (loggingEvent.ExceptionObject ??
loggingEvent.MessageObject).ToString();
hash = ChecksumGenerator.ComputeHash(Encoding.ASCII.GetBytes(str));
}
var builder = new StringBuilder();
foreach (var b in hash.Take(2))
{
builder.Append(b.ToString("x2"));
}
output = builder.ToString();
}
catch (Exception ex)
{
// can be found if log4net debugging is enabled
Source.TraceError(ex.ToString());
}
return output;
}
}
Sorry for the bad formatting (blame Atlassian).
I am reading SystemStringFormat.m_format by using reflection. That gives me the
string template used when logging and it is the one I think is appropriate when
outputting the type of the log message.
Now to my feature request: please expose the internals of SystemStringFormat so
that I can do this in a safe way.
What do you think?
Regards,
Daniel Lidström
was:
Hello
I'm trying to create a structured logging format and have a conversion pattern
with a custom converter like this:
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%2thread] %-5level [%property\\{NDC}]
%username - type=%message_checksum %message%newline" />
<converter>
<name value="message_checksum" />
<type value="TestBed.MessageChecksumConverter" />
</converter>
</layout>
The interesting part of course is the message_checksum. For example, I am
logging like this:
Log.Debug("some debugging message");
Log.Info(new \{ Id = 1, Name = "the name" });
Log.InfoFormat("Logging msg \{0}", 1);
Log.InfoFormat("Logging msg \{0}", 2);
Log.InfoFormat("Logging msg \{0}", 3);
I would like the output to be something like this
2018-10-26 11:06:44,564 [ 1] DEBUG [(null)] XXX - type=f6d5 some debugging
message
2018-10-26 11:06:44,638 [ 1] INFO [(null)] XXX - type=e0e3 \{ Id = 1, Name =
the name }
2018-10-26 11:06:44,648 [ 1] INFO [(null)] XXX - type=32a6 Logging msg 1
2018-10-26 11:06:44,656 [ 1] INFO [(null)] XXX - type=32a6 Logging msg 2
2018-10-26 11:06:44,663 [ 1] INFO [(null)] XXX - type=32a6 Logging msg 3
As you can see, I am getting the type=32a6 for the last 3 logging messages.
This allows me to search for all of those, regardless of the parameters given.
For example, I can now search and group the number of errors by their unique
type and know which error is most common in our system.
To implement this, I did the following:
public class MessageChecksumConverter : PatternLayoutConverter
{
private static readonly TraceSource Source = new
TraceSource(nameof(MessageChecksumConverter));
private static readonly MD5 ChecksumGenerator = MD5.Create();
protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
{
var output = TryGetHash(loggingEvent);
writer.Write(output);
}
private string TryGetHash(LoggingEvent loggingEvent)
{
string output = string.Empty;
try
{
byte[] hash;
var fmt = loggingEvent.MessageObject as SystemStringFormat;
if (fmt != null)
{
// read fmt.m_format and use that as input for hash
var systemStringFormatType = typeof(SystemStringFormat);
var fieldInfo =
systemStringFormatType.GetField("m_format", BindingFlags.NonPublic |
BindingFlags.Instance);
var formatString = fieldInfo?.GetValue(fmt) as string;
hash = ChecksumGenerator.ComputeHash(Encoding.ASCII.GetBytes(formatString ??
string.Empty));
}
else
{
var str = (loggingEvent.ExceptionObject ??
loggingEvent.MessageObject).ToString();
hash = ChecksumGenerator.ComputeHash(Encoding.ASCII.GetBytes(str));
}
var builder = new StringBuilder();
foreach (var b in hash.Take(2))
{
builder.Append(b.ToString("x2"));
}
output = builder.ToString();
}
catch (Exception ex)
{
// can be found if log4net debugging is enabled
Source.TraceError(ex.ToString());
}
return output;
}
}
Sorry for the bad formatting (blame Atlassian).
I am reading SystemStringFormat.m_format by using reflection. That gives me the
string template used when logging and it is the one I think is appropriate when
outputting the type of the log message.
Now to my feature request: please expose the internals of SystemStringFormat so
that I can do this in a safe way.
What do you think?
Regards,
Daniel Lidström
> Expose members in SystemStringFormat
> ------------------------------------
>
> Key: LOG4NET-615
> URL: https://issues.apache.org/jira/browse/LOG4NET-615
> Project: Log4net
> Issue Type: Wish
> Components: Layouts
> Affects Versions: 2.0.8
> Reporter: Daniel Lidström
> Priority: Trivial
>
> Hello
>
> I'm trying to create a structured logging format and have a conversion
> pattern with a custom converter like this:
>
> <layout type="log4net.Layout.PatternLayout">
> <conversionPattern value="%date [%2thread] %-5level
> [%property\\{NDC}] %username - type=%message_checksum %message%newline" />
> <converter>
> <name value="message_checksum" />
> <type value="TestBed.MessageChecksumConverter" />
> </converter>
> </layout>
>
> The interesting part of course is the message_checksum. For example, I am
> logging like this:
>
> Log.Debug("some debugging message");
> Log.Info(new \{ Id = 1, Name = "the name" });
> Log.InfoFormat("Logging msg \{0}", 1);
> Log.InfoFormat("Logging msg \{0}", 2);
> Log.InfoFormat("Logging msg \{0}", 3);
>
> I would like the output to be something like this
>
> 2018-10-26 11:06:44,564 [ 1] DEBUG [(null)] XXX - type=f6d5 some debugging
> message
> 2018-10-26 11:06:44,638 [ 1] INFO [(null)] XXX - type=e0e3 \{ Id = 1, Name =
> the name }
> 2018-10-26 11:06:44,648 [ 1] INFO [(null)] XXX - type=32a6 Logging msg 1
> 2018-10-26 11:06:44,656 [ 1] INFO [(null)] XXX - type=32a6 Logging msg 2
> 2018-10-26 11:06:44,663 [ 1] INFO [(null)] XXX - type=32a6 Logging msg 3
>
> As you can see, I am getting the type=32a6 for the last 3 logging messages.
> This allows me to search for all of those, regardless of the parameters given.
> For example, I can now search and group the number of errors by their unique
> type and know which error is most common in our system.
>
> To implement this, I did the following:
> public class MessageChecksumConverter : PatternLayoutConverter
> {
> private static readonly TraceSource Source = new
> TraceSource(nameof(MessageChecksumConverter));
> private static readonly MD5 ChecksumGenerator = MD5.Create();
> protected override void Convert(TextWriter writer, LoggingEvent
> loggingEvent)
> {
> var output = TryGetHash(loggingEvent);
> writer.Write(output);
> }
> private string TryGetHash(LoggingEvent loggingEvent)
> {
> string output = string.Empty;
> try
> {
> byte[] hash;
> var fmt = loggingEvent.MessageObject as SystemStringFormat;
> if (fmt != null)
> {
> // read fmt.m_format and use that as input for hash
> var systemStringFormatType = typeof(SystemStringFormat);
> var fieldInfo =
> systemStringFormatType.GetField("m_format",
> BindingFlags.NonPublic | BindingFlags.Instance);
> var formatString = fieldInfo?.GetValue(fmt) as string;
> hash =
> ChecksumGenerator.ComputeHash(Encoding.ASCII.GetBytes(formatString ??
> string.Empty));
> }
> else
> {
> var str = (loggingEvent.ExceptionObject ??
> loggingEvent.MessageObject).ToString();
> hash =
> ChecksumGenerator.ComputeHash(Encoding.ASCII.GetBytes(str));
> }
>
> var builder = new StringBuilder();
> foreach (var b in hash.Take(2))
> {
> builder.Append(b.ToString("x2"));
> }
>
> output = builder.ToString();
> }
> catch (Exception ex)
> {
> // can be found if log4net debugging is enabled
> Source.TraceError(ex.ToString());
> }
> return output;
> }
> }
> Sorry for the bad formatting (blame Atlassian).
> I am reading SystemStringFormat.m_format by using reflection. That gives me
> the string template used when logging and it is the one I think is
> appropriate when outputting the type of the log message.
>
> Now to my feature request: please expose the internals of SystemStringFormat
> so that I can do this in a safe way.
> What do you think?
>
> Regards,
> Daniel Lidström
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)