首页 > 解决方案 > 如何将 eventLog.Properties 转换为 XML?

问题描述

我想通过存储过程将 Serilog 消息存储到数据库中。我创建了新的接收器。

    namespace Copacking.Web.Logging
    {
        class StoredProcedureSink : ILogEventSink
        {
            private readonly string connectionString;
            public StoredProcedureSink(string connectionString) {
                this.connectionString = connectionString;
            }

            public void Emit(LogEvent logEvent)
            {
var xml = new XElement("properties");

            foreach (KeyValuePair<string, LogEventPropertyValue> property in logEvent.Properties)
            {
                xml.Add(new XElement("property", new XAttribute("Key", property.Key), property.Value));
            }

                using (var conn = new SqlConnection(connectionString))
                using (var command = new SqlCommand("dbo.usp_insertLog", conn){ CommandType = CommandType.StoredProcedure })
                {
                    conn.Open();
                    command.Parameters.Add(new SqlParameter("@message", logEvent.RenderMessage()));
                    command.Parameters.Add(new SqlParameter("@messageTemplate", logEvent.MessageTemplate.Text));
                    command.Parameters.Add(new SqlParameter("@level", logEvent.Level.ToString()));
                    command.Parameters.Add(new SqlParameter("@timestamp", logEvent.Timestamp));
                    command.Parameters.Add(new SqlParameter("@exception", logEvent.Exception.ToString()));
                    command.Parameters.Add(new SqlParameter("@properties", xml.ToString()));
                    command.ExecuteNonQuery();
                }
            }

        }

    } 

它有效,但我得到

 <properties>
  <property Key="SourceContext">"..."</property>
  <property Key="RequestId">"..."</property>
  <property Key="RequestPath">"..."</property>
  <property Key="RequestHeader">[("Connection": "Keep-Alive"), ("Accept": "text/html, application/xhtml+xml, image/jxr, */*"), ("Accept-Encoding": "..."), ("Accept-Language": "..."), ("Host": "..."), ("User-Agent": "..."), ("MS-ASPNETCORE-TOKEN": "..."), ("MS-ASPNETCORE-WINAUTHTOKEN": "..."), ("X-Original-Proto": "..."), ("X-Original-For": "...")]</property>
  <property Key="ActivityId">"..."</property>
  <property Key="UserName">"..."</property>
</properties>

代替

<properties>
  <property key="SourceContext">...</property>
  <property key="RequestId">...</property>
  <property key="RequestPath">...</property>
  <property key="RequestHeader">
    <dictionary>
      <item key="Connection">...</item>
      <item key="Accept">...</item>
      <item key="Accept-Encoding">...</item>
      <item key="Accept-Language">...</item>
      <item key="Host">...</item>
      <item key="User-Agent">...</item>
      <item key="MS-ASPNETCORE-TOKEN">...</item>
      <item key="MS-ASPNETCORE-WINAUTHTOKEN">...</item>
      <item key="X-Original-Proto">...</item>
      <item key="X-Original-For">...</item>
    </dictionary>
  </property>
  <property key="ActivityId">...</property>
  <property key="UserName">...</property>
</properties>

任何想法如何更改代码?也许实现一些递归?!

标签: xmlcollectionsserilog

解决方案


我想通了一点解决办法。我复制了以下课程

  • 列选项
  • 标准柱
  • XmlPropertyFormatter

来自 serilog nuget 包https://github.com/serilog/serilog-sinks-mssqlserver 并调用

command.Parameters.Add(new SqlParameter("@properties", ConvertPropertiesToXmlStructure(logEvent.Properties)));

我不能直接使用 nuget 包中的类,因为XmlPropertyFormatter是内部的,因此只能在包内调用。


推荐阅读