Log4net的XML appender没有创建根元素。

3

我正在使用Log4net (v2.0.50727)编写C# webservice。它被配置为创建两个appender。第一个是一般的debug文件,我会监控它以确保服务正常运行;第二个是报告,我会在不同的时间间隔手动转发给客户(可能会自动化)。

<log4net>
  <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
    <file value="..\logs\Service.log.xml"/>
    <appendToFile value="true"/>
    <rollingStyle value="Size"/>
    <maxSizeRollBackups value="20"/>
    <maximumFileSize value="10000KB"/>
    <staticLogFileName value="true"/>
    <preserveLogFileNameExtension value="true" />
    <layout type="log4net.Layout.XmlLayoutSchemaLog4j">
      <conversionPattern value="%utcdate [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
    </layout>
  </appender>
  <appender name="CustomerReportAppender" type="log4net.Appender.RollingFileAppender">
      <file value="..\logs\Customer.Report.xml"/>
      <appendToFile value="true"/>
      <rollingStyle value="Size"/>
      <maxSizeRollBackups value="20"/>
      <maximumFileSize value="10000KB"/>
      <staticLogFileName value="true"/>
      <preserveLogFileNameExtension value="true" />
      <layout type="log4net.Layout.XmlLayoutSchemaLog4j">
        <conversionPattern value="%utcdate [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
      </layout>
  </appender>
  <root>
    <level value="DEBUG"/>
    <appender-ref ref="RollingFileAppender"/>
  </root>
  <logger name="CustomerReport">
    <level value="ALL" />
    <appender-ref ref="CustomerReportAppender" />
  </logger>
</log4net>

两个文件的日志记录都有效。问题是,如果我向客户发送Customer.Report.xml文件,它在Excel中无法打开,因为它不是有效的XML文件。该文件由多行事件元素组成 -

<event logger="CustomerReport" timestamp="1453717399436" level="INFO" thread="8">
<message>Customer Info</message>
<properties>
<data name="UserName" value="IIS APPPOOL\Customer Service" />
<data name="log4jmachinename" value="MyServer" />
<data name="log4japp" value="/LM/W3SVC/3/ROOT-2-130981905203581113" />
<data name="HostName" value="MyServer" />
</properties>
</event>

我猜Excel报错是因为它没有一个根元素。如果我将整个文件包裹在 - 中,问题就会解决。
<Report>
....
</Report>

Excel可以正常加载它。是否可能让Log4net为我生成这个?或者能否使Excel处理它?谢谢。


您可以将页眉和页脚元素添加到布局中(请注意,由于XmlLayoutSchemaLog4j没有此属性,因此忽略了转换模式) - 或者您有多种选项来更好地控制该过程,例如自定义appender或自定义布局。 - stuartd
Log4net 无法自行处理此问题,因为 RollingFileAppender 没有确定的结束。它不可能知道何时关闭根 XML 标记。如果您的用户可以接受(您确实会收到这些病毒警告),则可以通过使用 VBA 从 Excel 处理此问题,或者您需要使用一些自定义代码进行干预。 - Fred Kleuver
1个回答

1

PowerShell是一种快速解决此类问题的好工具。

不确定这是否是您正在寻找的答案类型,但它可以以中间方式解决您的问题。您已经提到您目前正在手动执行此操作,但将来可能会自动化-PowerShell也是一个很好的方法。

因此,下面的脚本将要求您选择文件,然后自动将其XML内容放入您指定的根元素中:

[CmdletBinding()]
Param(
    [Parameter(ValueFromPipeline=$true)]
    [ValidateScript({Test-Path $_ -PathType Container})]
    [string]
    $InitialDirectory,

    [ValidateNotNullOrEmpty()]
    [string]
    $RootElementName = 'Report'
)

[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null

$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.InitialDirectory = $InitialDirectory
$OpenFileDialog.Filter = "XML (*.xml)| *.xml"
$OpenFileDialog.ShowDialog() | Out-Null

$FileName = $OpenFileDialog.FileName
$FileContent = Get-Content $FileName

$FileContentXml = [Xml]$FileContent

[XML.XMLDocument]$XMLDocument = New-Object System.XML.XMLDocument
[XML.XMLElement]$XMLRoot = $XMLDocument.CreateElement($RootElementName)
$XMLRoot.InnerXml = $FileContentXml.OuterXml
$XMLDocument.AppendChild($XMLRoot)

$XMLDocument.Save($FileName)

您可以将此脚本保存在新文件中,例如D:\Add-RootXmlElement.ps1,然后可以通过命令提示符运行它:

@powershell D:\Add-RootXmlElement.ps1 -InitialDirectory "D:\Logs" -RootElementName "Report"

根据需要在Param块中调整默认值,以便将来节省一些输入。

这解决了您的问题吗?

编辑:

当然,如果您想自动化此过程并且在调用脚本时知道文件名,则只需省略整个$InitialDirectory$OpenFileDialog部分,并将$FileName目录设置为要向其添加根元素的日志文件的路径即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接