【问题标题】:Config Transformation on NLog does not workNLog 上的配置转换不起作用
【发布时间】:2014-03-16 14:34:26
【问题描述】:

我有一个 Web 项目(ASP.NET MVC 4 项目),其中有许多配置存储在 Web.ConfigNLog.config 文件中。

我有几个发布配置文件 PublishProfile1PublishProfile2 等。当使用发布配置文件将我的 Web 项目部署到服务器时,我想更改一些配置部署后的两个配置文件(Web.config 中的一些应用设置和 NLog.config 中的一些值)。

我已按照 here 的步骤进行操作,它非常适合更改 Web.Config 中的设置(例如,Web.PublishProfile1.Config 中的转换受到尊重)。

这是我的 NLog.PublishProfile1.Config 转换文件:

<nlog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" xmlns="http://www.nlog-project.org/schemas/NLog.xsd">
  <nlog  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <targets >
      <target xsi:type="File"
              name="tracelog"
              fileName="NEW_VALUE_HERE" layout="${longdate} [${threadname}::${threadid}] ${pad:padding=5:inner=${level:uppercase=true}} ${logger} - ${message}"
              xdt:Transform="Replace"  xdt:Locator="Match(name)" />
    </targets>
  </nlog>
</nlog>

问题是我在 NLog.PublishProfile1.config 中有相同的转换,但这些转换在部署后也没有应用。

有没有人知道为什么这种转换对 NLog.config 不起作用但对发布配置文件上的 Web.config 工作正常?

【问题讨论】:

  • 当你运行它时会发生什么?转换是否运行并将转换后的 Nlog.config 放置在输出目录中?

标签: asp.net-mvc xslt deployment web-config nlog


【解决方案1】:

要解决这个问题,我必须:

1) 避免使用nlog.config

2) 在web.config 内创建nlog 部分并将nlog.config 的内容移动到web.config 以便能够对一个文件使用web.config 转换功能。如需进一步说明,请查看:NLog configuration instructions

3) 从nlog 节点中删除xmlns 属性。在web.config 转换期间似乎有一个错误会弄乱一切。您可以安全地删除以下节点:

xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4) 我找不到在 nlog/targets 节点下仅转换单个目标的方法。要更改记录器的连接字符串,我必须复制整个 xml 节点,在父节点上使用 xdt:Transform="Replace",如下所示:

<nlog
      throwExceptions="true"
      internalLogLevel="Trace"
      internalLogFile="..\..\..\Logs\nlog-app.log" 
      xdt:Transform="Replace">
<!--(copy and paste all nlog configuration here)-->
</nlog>

【讨论】:

  • 您可以使用xdt:Locator="Match(name)"轻松处理单个目标
  • 将 nlog 移动到 web.config 是一个次优的解决方案。 nlog.config 的重点是能够在不强制重新加载应用程序的情况下即时调整日志配置,这无疑是更改 web.config 的作用。
  • 我发现我必须将这些节点添加到我的转换文件中,而不是删除 XMLNS 节点(这会导致我的 Web 配置错误/导致转换失败)。希望你不介意,但我会编辑你的答案并添加一些细节..
  • 可能对未来的读者有帮助:当您删除 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 时(当您不使用 NLog.config 而是使用 web.config 时不需要),您的 xml 文件中会出现错误。不使用命名空间时,只需将xsi:type 属性更改为type 即可,一切正常。
  • 我不必删除xmlns:xsi=,而只需删除xmlns=。感谢您的帮助@Mário
【解决方案2】:

我在没有将所有配置移动到 web.config 或 app.config 的情况下管理它。 (什么都没有,和web/app.config中的nlog连在一起)。

1) 使用这篇文章:applying msbuild config transformations to any config file 我已经创建了所有必要的转换并添加了转换任务。

2)然后我检查了是否有其他任务可以做类似的事情。在我的例子中,有一个是由 SlowCheetah(VS 扩展自动添加转换)创建的。我已经删除了它 - 一切都变好了。 (SlowCheetah 可以在下次构建时恢复其设置,因此最好将其删除或抑制其转换任务)

3) 我的转换文件如下所示:

<?xml version="1.0"?>
<!-- For more information on using app.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
<nlog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" xmlns="http://www.nlog-project.org/schemas/NLog.xsd">
  <targets>
    <target xsi:type="Database" name="DbLogging"
          connectionString=".\SQLEXPRESS;Initial Catalog=xxxxx;User ID=xxxx;Pwd=xxxx;" xdt:Transform="SetAttributes(connectionString)" xdt:Locator="Match(name)">
    </target>
  </targets>
  <rules>
    <logger name="*" minlevel="Debug" writeTo="DbLogging" />
    <logger name="Namespace.*" minlevel="Debug" writeTo="DbLogging" xdt:Transform="SetAttributes(writeTo)" xdt:Locator="Match(name)" />
  </rules>
</nlog>

【讨论】:

  • 这是我正在使用的解决方案;为每个配置创建 NLog 配置文件是一种很好的做法,但您可以通过将 Condition="Exists('NLog.$(Configuration).config')" 添加到 .csproj 中的新 TransformXml 元素来防止构建错误。请记住,这可能会在后续构建中导致不需要的行为,因为您的基本 NLog.config 文件将被每个构建上的转换覆盖。还没有找到解决办法。
  • 抱歉,我不明白您评论的第一部分。如果我们自己创造转换,为什么我们需要条件。我还没有找到防止主要 NLog.config 文件不断变化的方法
  • 万一忘记为当前配置添加配置文件。在这种情况下,我想你可能会想要抛出一个错误。好点子!
  • 这只适用于我的构建,但不适用于发布。您对如何解决发布有任何想法吗?
  • 很遗憾,我没有在发布时尝试过,但如果您提供有关该问题的更多信息,我们将能够解决它
【解决方案3】:

看来我在这方面已经很晚了,但我发现 NLog.config 文件必须具有以下内容:

<?xml version="1.0" encoding="utf-8"?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd">
...
...
</nlog>

并且 NLogTransform.config 文件(或它可能具有的任何名称)具有以下内容:

<?xml version="1.0"?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
...
...
</nlog>

这里是一些测试 NLog 转换的示例代码:

var tmpConfigFile = new FileInfo("C:\\NLogs\\NLog.config");
var transformFile = new FileInfo("C:\\Transforms\\NLogTransform.config");

if (transformFile.Exists) {
    var xmlTransformableDocument = new XmlTransformableDocument();
    xmlTransformableDocument.Load(tmpConfigFile.FullName);
    var xmlTransformation = new XmlTransformation(transformFile.FullName);
    xmlTransformation.Apply(xmlTransformableDocument);
    xmlTransformableDocument.Save(tmpConfigFile.FullName);
}

【讨论】:

  • 你节省了一天:只需在转换 nlog.config 文件中添加 xmlns="nlog-project.org/schemas/NLog.xsd" 行,就可以立即开始工作,而所有其他教程显示人们取出那条线
【解决方案4】:

我通过在转换配置中为 nlog 部分包含在 web.config 中定义的 xmlns:xsi 命名空间来实现此功能。

<nlog xmlns:xsi="...">
    <variable name="..." value="..." xdt:Transform="Replace" xdt:Locator="Match(name)" />
</nlog>

【讨论】:

    【解决方案5】:

    我最终更改了所有发布配置文件(.pubxml 文件)。 作为示例,我已将以下内容添加到我的测试发布配置文件中:

    <Target Name="NLogTransform" AfterTargets="PipelineCopyAllFilesToOneFolderForMsdeploy">
    <Message Text="NLog file transform according to NLog.WebDeploy - TEST.config" Importance="high" />
    <TransformXml Source="NLog.config"
                  Transform="NLog.WebDeploy - TEST.config"
                  Destination="$(_PackageTempDir)\NLog.config" />
    </Target>
    

    请注意,这仅适用于发布使用 MsDeploy(又名 Web 部署)的配置文件。要在本地文件夹上发布,请使用此目标 CopyAllFilesToSingleFolderForPackage

    【讨论】:

      【解决方案6】:

      接受的答案对我不起作用。

      我想在本地进行内部日志记录,但不是在生产环境中。 事实证明,您需要在根配置节点中包含命名空间。

      什么对我有用: 网络配置:

      <configuration>
        <configSections>
          <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
        </configSections>
      
        <nlog autoReload="true" internalLogLevel="Trace" internalLogFile="internalLog.txt" xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
        <!--nlog config stuff-->
        </nlog>
      </configuration>
      

      web.config.Release

      <?xml version="1.0"?>
        <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" xmlns:nlg="http://www.nlog-project.org/schemas/NLog.xsd">
         <nlg:nlog xdt:Transform="RemoveAttributes(internalLogLevel,internalLogFile)" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">>
         </nlg:nlog>
        </configuration>
      

      在这里找到解决方案: https://www.jayway.com/2011/11/14/web-config-transformations-and-xml-namespaces/

      【讨论】:

        【解决方案7】:

        更新 - 将“key”属性添加到配置和转换文件以及“Transform”和“Locator”属性到转换文件中更改的行在独立的 NLog.config 文件中工作,如下所示:

        <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              autoReload="true"
              throwExceptions="false">
            <targets async="true">
              <target name="MyLogFile"
                      xsi:type="File"
                      keepFileOpen="false"
                      fileName="C:/File/Logs/Example.${shortdate}.log"
                      archiveFileName="C:/File/Logs/Example.${shortdate}.{#}.log"
                      archiveEvery="Day"
                      archiveNumbering="Rolling"
                      maxArchiveFiles="30"
                      layout="${Date:universalTime=false:format=o}, ${logger}, ${Level}, ${Message:jsonEncode=true} ${onexception:${newline}'Exception\: ${Exception:format=tostring:jsonEncode=true}', 'StackTrace\:${stacktrace:topFrames=12:jsonEncode=true}'}">
              </target>
            </targets>
            <rules>
                <logger key="logRule" name="*" minlevel="Trace" writeTo="MyLogFile" />
            </rules>
        </nlog>
        

        转换文件:

        <?xml version="1.0" encoding="utf-8"?>
        <nlog xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"
          xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          autoReload="true"
          throwExceptions="false">
          <rules>
            <logger key="logRule" name="*" minlevel="Info" writeTo="MyLogFile" xdt:Transform="Replace" xdt:Locator="Match(key)" />
          </rules>
        </nlog>
        

        【讨论】:

          【解决方案8】:

          我也有这个问题,但在一个 ASP.NET MVC 5 项目中。我没有任何AfterBuild 事件,只在csproj 文件中为NLog.config 文件添加了一行:

          <TransformOnBuild>true</TransformOnBuild>
          

          看起来这告诉 msbuild.exe 在构建时进行转换。 我的设置是两个文件 NLog.Debug.configNLog.Release.config 用于基于构建配置 (/p:Configuration="Release") 的转换。

          <Content Include="NLog.config">
            <CopyToOutputDirectory>Always</CopyToOutputDirectory>
            <TransformOnBuild>true</TransformOnBuild>
          </Content>
          <None Include="NLog.Debug.config">
            <DependentUpon>NLog.config</DependentUpon>
            <IsTransformFile>True</IsTransformFile>
          </None>
          <None Include="NLog.Release.config">
            <DependentUpon>NLog.config</DependentUpon>
            <IsTransformFile>True</IsTransformFile>
          </None>
          

          【讨论】:

          • 有趣的是,这在 Visual Studio 2015 中似乎对我有用,即使 Visual Studio 在标记下划线并告诉我它不起作用。
          【解决方案9】:

          当 nlog 位于 web.config 时的工作示例 - 最大限度地使用变量以最小化所需的转换

          <?xml version="1.0" encoding="utf-8"?>
          <configuration>
            <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
              <variable name="SystemName" value="MyApp" />
              <variable name="LogPath" value="c:\log\${SystemName}" />
              <variable name="Layout" value="${longdate}|${level:upperCase=true}|t${threadid}|${logger}| ${message} ${exception:format=message,stacktrace}|${event-properties:item=ir-objects}" />
          
              <targets>
                <wrapper-target xsi:type="AsyncWrapper" name="file-info">
                  <target xsi:type="File" createDirs="true" fileName="${LogPath}\${SystemName}.web.info.log" archiveAboveSize="31457280" archiveNumbering="Sequence" maxArchiveFiles="5" archiveEvery="Day" layout="${Layout}" />
                </wrapper-target>
          
              </targets>
          
              <rules>
                <logger name="*" minlevel="Info" writeTo="file-info" />
              </rules>
            </nlog>
          </configuration>
          

          转换文件:

          <?xml version="1.0" encoding="utf-8"?>
          <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" xmlns:nlog="http://www.nlog-project.org/schemas/NLog.xsd">
            <nlog:nlog>
              <nlog:variable name="LogPath" value="D:\logs\uat\${SystemName}"  xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
            </nlog:nlog>
          </configuration>
          

          诀窍是命名所有 nlog 元素 - nlogvariable

          【讨论】:

            【解决方案10】:

            我一直在使用带有 SlowCheetah NuGet 包的构建时间 web.config 转换和内置部署时间转换。对于NLog.config 文件,每个构建环境都有NLog.*.config 文件。以前,这些文件中的每一个都有完整的NLog.config 内容,并且在部署中有一个任务是用特定的NLog.*.config 覆盖NLog.config,然后删除所有NLog.*.config

            今天决定将这些文件改为可转换的,类似于从web.template.configweb.template.*.config 生成web.config 的方式(在ProjectName.wpp.targets 文件的帮助下),但不会在构建时替换NLog.config时间(不想在我的 localhost 运行中有服务器的日志文件路径)。

            这是我如何让它工作的——在ProjectName.wpp.targets 文件中,我使用OnAfterCopyAllFilesToSingleFolderForPackage“事件”将NLog.config 文件转换为临时中间目录(随后用于发布)。这是完整的ProjectName.wpp.targets 文件:

            <?xml version="1.0" encoding="utf-8"?>
            <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
            
              <!-- Make sure Web.config will be there even for package/publish -->
              <Target Name="CopyWebTemplateConfig" BeforeTargets="PrepareForBuild">
                <Copy SourceFiles="Web.template.config"
                      DestinationFiles="Web.config"/>
              </Target>
            
              <PropertyGroup>
                <PrepareForRunDependsOn>
                  $(PrepareForRunDependsOn);
                  UpdateWebConfigBeforeRun;
                </PrepareForRunDependsOn>
              </PropertyGroup>
            
              <PropertyGroup>
                <OnAfterCopyAllFilesToSingleFolderForPackage>
                  $(OnAfterCopyAllFilesToSingleFolderForPackage);
                  UpdateNLogConfigBeforePublish;
                </OnAfterCopyAllFilesToSingleFolderForPackage>
              </PropertyGroup>
            
              <!-- This target will run right before you run your app in Visual Studio -->
              <Target Name="UpdateWebConfigBeforeRun">
                <Message Text="Configuration: $(Configuration): Web.template.$(Configuration).config"/>
                <TransformXml Source="Web.template.config"
                          Transform="Web.template.$(Configuration).config"
                          Destination="Web.config" />
              </Target>
            
              <Target Name="UpdateNLogConfigBeforePublish">
                <Message Text="Configuration: $(Configuration): NLog.$(Configuration).config"/>
                <TransformXml Source="NLog.config"
                          Transform="NLog.$(Configuration).config"
                          Destination="$(IntermediateOutputPath)\Package\PackageTmp\NLog.config" />
              </Target>
            
              <!-- Exclude the config template files from the created package -->
              <Target Name="ExcludeCustomConfigTransformFiles" BeforeTargets="ExcludeFilesFromPackage">
                <ItemGroup>
                  <ExcludeFromPackageFiles Include="Web.template.config;Web.template.*.config"/>
                  <ExcludeFromPackageFiles Include="NLog.*.config"/>
                </ItemGroup>
                <Message Text="ExcludeFromPackageFiles: @(ExcludeFromPackageFiles)" Importance="high"/>
              </Target>
            </Project>
            

            NLog.*.config 文件然后使用标准转换,例如:

            <?xml version="1.0" encoding="utf-8"?>
            
            <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"
                  internalLogFile="c:\temp\ProjectName.ENV.nlog.txt"
                  xdt:Transform="SetAttributes(internalLogFile)">
            
                <variable name="envName" value="ENV"
                          xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
            
                <targets>
                    <target name="exceptionsMail" to="ENV.email@some.email.domain"
                            xdt:Transform="SetAttributes(to)" xdt:Locator="Match(name)" />
                </targets>
            
                <rules>
                    <logger name="Exceptions" minlevel="Error" writeTo="exceptionsMail"
                            xdt:Transform="Insert" />
                </rules>
            </nlog>
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-02-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2023-01-11
              相关资源
              最近更新 更多