log4net:在数据库中将两条消息记录在一行中?

发布于 2024-07-21 05:46:11 字数 341 浏览 6 评论 0原文

我正在尝试将特定方法的输入和输出记录到数据库中。 我想将这些信息放在单独的列中。 我研究了 PatternLayout,它似乎只满足单个 %message 参数,这意味着如果您这样做:

log.Debug("This is a message");

那么 log4net 会将“这是一条消息”视为要记录的消息。 我想做一些类似的事情:

log.Debug(request, response);

使用 log4net 可以吗? 请记住,我的目标是在单独的列中包含“请求”和“响应”。

I'm trying to log the input and output of a particular method to the database. I'd like to have this information in separate columns. I've investigated the PatternLayout and it seems that it only caters for a single %message parameter, meaning that if you do:

log.Debug("This is a message");

then log4net sees "This is a message" as the message to be logged. I want to do something like:

log.Debug(request, response);

Is this possible using log4net? Keep in mind that my goal is to have "request" and "response" in separate columns.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

别再吹冷风 2024-07-28 05:46:11

您的 PatternConverter 方法是朝着正确方向迈出的一步,尽管使用静态输入和输出属性使其变得有点不稳定(线程安全方面)。

这里的技巧是要意识到 logger.Debug(...) 上的消息参数是对象,并且您可以传入任何您喜欢的内容。

您可以定义自定义消息类型

public class InputOutput
{
    public string Input {get;set;}
    public string Output {get;set;}
}

,然后让您的转换器读取任一属性,

public class InputPatternConverter : PatternConverter
{
    protected override void Convert(System.IO.TextWriter writer, object state)
    {
        var msg = ((LoggingEvent)state).MessageObject as InputOutput;
        if (msg != null)
            writer.Write(msg.Input);
    }
}

public class OutputPatternConverter : PatternConverter
{
    protected override void Convert(System.IO.TextWriter writer, object state)
    {
        var msg = ((LoggingEvent)state).MessageObject as InputOutput;
        if (msg != null)
            writer.Write(msg.Output);
    }
}

然后日志记录变得更加清晰,

logger.Debug(new InputOutput { Input = ..., Output = ...});

您的配置将是相同的。

不过,一个技巧是子类化 PatternLayout 并在该类的构造函数中添加转换器。 这样你也可以削减你的配置。 这不会导致您丢失 %message 令牌,除了 PatternLayout 支持的所有令牌之外,您的 %input 和 %output 令牌也会出现。 因此,您实际上可以拥有这样的模式:

"%date %message %newline%newline %input %newline%newline %output

这是自定义模式布局的快速实现:

public class InputOutputPatternLayout : PatternLayout
{
    public InputOutputPatternLayout()
    {
        AddConverter("input", typeof(InputPatternConverter));
        AddConverter("output", typeof(OutputPatternConverter));
    }
}

Your PatternConverter way is a step in the right direction, though the use of the static Input and Output properties makes it all a bit shaky (thread-safety wise).

The trick here is to realize that the message parameter on logger.Debug(...) is object and that you can pass in whatever you like.

You could define a custom message type

public class InputOutput
{
    public string Input {get;set;}
    public string Output {get;set;}
}

and then let your converters read either property

public class InputPatternConverter : PatternConverter
{
    protected override void Convert(System.IO.TextWriter writer, object state)
    {
        var msg = ((LoggingEvent)state).MessageObject as InputOutput;
        if (msg != null)
            writer.Write(msg.Input);
    }
}

public class OutputPatternConverter : PatternConverter
{
    protected override void Convert(System.IO.TextWriter writer, object state)
    {
        var msg = ((LoggingEvent)state).MessageObject as InputOutput;
        if (msg != null)
            writer.Write(msg.Output);
    }
}

the logging then becomes much cleaner

logger.Debug(new InputOutput { Input = ..., Output = ...});

your config would be the same.

A tip though is to subclass the PatternLayout and add the converters in the constructor of that class. That way you can also trim down your config. This will not cause you to loose the %message token, your %input and %output tokens will come in addition to all the tokens that PatternLayout supports. So you could actually have a pattern like this:

"%date %message %newline%newline %input %newline%newline %output

Here's a quick implementation of a custom pattern layout:

public class InputOutputPatternLayout : PatternLayout
{
    public InputOutputPatternLayout()
    {
        AddConverter("input", typeof(InputPatternConverter));
        AddConverter("output", typeof(OutputPatternConverter));
    }
}
儭儭莪哋寶赑 2024-07-28 05:46:11

我想出了一种使用自定义 PatternConverters

public class InputPatternConverter : PatternConverter
{
    private static string _input;

    public static string Input
    {
        get { return _input; }
        set { _input = value; }
    }

    protected override void Convert(System.IO.TextWriter writer, object state)
    {
        writer.Write(Input);
    }
}

public class OutputPatternConverter : PatternConverter
{
    private static string _output;

    public static string Output
    {
        get { return _output; }
        set { _output = value; }
    }

    protected override void Convert(System.IO.TextWriter writer, object state)
    {
        writer.Write(Output);
    }
}

Appender 规范来执行此操作的方法:

<appender name="ADONetAppender" type="log4net.Appender.AdoNetAppender">
  <bufferSize value="1" />
  <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  <connectionString value="data source=servername;initial catalog=database;Integrated Security=SSPI;" />
  <commandText value="INSERT INTO RequestLog ([input], [output]) VALUES (@input, @output)" />
  <parameter>
    <parameterName value="@input" />
    <dbType value="String" />
    <size value="4000" />
    <layout type="log4net.Layout.PatternLayout">
      <converter>
        <name value="input" />
        <type value="InputPatternConverter, ApplicationName" />
      </converter>
      <conversionPattern value="%input" />
    </layout>
  </parameter>
  <parameter>
    <parameterName value="@output" />
    <dbType value="String" />
    <size value="4000" />
    <layout type="log4net.Layout.PatternLayout">
      <converter>
        <name value="output" />
        <type value="OutputPatternConverter, ApplicationName" />
      </converter>
      <conversionPattern value="%output" />
    </layout>
  </parameter>
</appender>

使用以下方式调用它:

InputPatternConverter.Input = inputString;
OutputPatternConverter.Output = outputString;

XmlConfigurator.Configure();
ILog logger = LogManager.GetLogger(typeof(ApplicationClassName));
logger.Debug("");

I've come up with one way to do this using custom PatternConverters

public class InputPatternConverter : PatternConverter
{
    private static string _input;

    public static string Input
    {
        get { return _input; }
        set { _input = value; }
    }

    protected override void Convert(System.IO.TextWriter writer, object state)
    {
        writer.Write(Input);
    }
}

public class OutputPatternConverter : PatternConverter
{
    private static string _output;

    public static string Output
    {
        get { return _output; }
        set { _output = value; }
    }

    protected override void Convert(System.IO.TextWriter writer, object state)
    {
        writer.Write(Output);
    }
}

Appender Specification:

<appender name="ADONetAppender" type="log4net.Appender.AdoNetAppender">
  <bufferSize value="1" />
  <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  <connectionString value="data source=servername;initial catalog=database;Integrated Security=SSPI;" />
  <commandText value="INSERT INTO RequestLog ([input], [output]) VALUES (@input, @output)" />
  <parameter>
    <parameterName value="@input" />
    <dbType value="String" />
    <size value="4000" />
    <layout type="log4net.Layout.PatternLayout">
      <converter>
        <name value="input" />
        <type value="InputPatternConverter, ApplicationName" />
      </converter>
      <conversionPattern value="%input" />
    </layout>
  </parameter>
  <parameter>
    <parameterName value="@output" />
    <dbType value="String" />
    <size value="4000" />
    <layout type="log4net.Layout.PatternLayout">
      <converter>
        <name value="output" />
        <type value="OutputPatternConverter, ApplicationName" />
      </converter>
      <conversionPattern value="%output" />
    </layout>
  </parameter>
</appender>

Call it using:

InputPatternConverter.Input = inputString;
OutputPatternConverter.Output = outputString;

XmlConfigurator.Configure();
ILog logger = LogManager.GetLogger(typeof(ApplicationClassName));
logger.Debug("");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文