如何解决NLog从我的计算机写入所有目标,但无法写入应用程序服务器上的数据库目标
快速总结,然后深入细节
(NLog版本4.7.2)ASP.NET Core 2.2 Web应用程序正确地从本地计算机记录到文件和数据库目标。一旦将其部署到暂存应用程序服务器,文件日志记录就会继续,但是数据库日志记录将不起作用,并且内部日志中不会出现任何错误。使用在.NET Core 2.2上运行的NLog创建了一个控制台应用程序,它可以从本地计算机以及将Web应用程序部署到的同一服务器上正确地登录到文件和数据库。
问题和详细信息
我最近经历了一个日志记录解决方案,并将其添加到正在构建的应用程序中,这是一个相对轻松的过程。设置文件/数据库目标很容易,我可以毫无问题地将日志从应用程序写入开发和登台数据库。
该应用程序是.NET CORE 2.2 Web应用程序,它使用NLog 4.7.2-在下面进行设置。
nlog配置
<?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"
autoReload="true"
throwConfigExceptions="true"
internalLogLevel="Debug"
internalLogFile="c:\temp\internal-nlog.txt">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Extensions.Logging"/>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- the targets to write to -->
<targets>
<!-- write logs to file -->
<target xsi:type="File" name="allfile" fileName="c:\temp\nlog-all-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />
<!-- another file log,only own logs. Uses some ASP.NET core renderers -->
<target xsi:type="File" name="ownFile-web" fileName="c:\temp\nlog-own-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
<!-- write to the void aka just remove -->
<target xsi:type="Null" name="blackhole" />
<!--<target name="databaseLogger" xsi:type="Database"
dbProvider="sqlserver"
dbHost="${configsetting:name=AppSettings.NlogConnection.DbHost}"
dbDatabase="${configsetting:name=AppSettings.NlogConnection.Database}"
dbUserName="${configsetting:name=AppSettings.NlogConnection.User}"
dbPassword="${configsetting:name=AppSettings.NlogConnection.Password}">-->
<target name="databaseLogger" xsi:type="Database"
dbProvider="sqlserver"
dbHost="${configsetting:AppSettings.NlogConnection.DbHost}"
dbDatabase="${configsetting:AppSettings.NlogConnection.Database}"
dbUserName="${configsetting:AppSettings.NlogConnection.User}"
dbPassword="${configsetting:AppSettings.NlogConnection.Password}" >
<!--<target name="databaseLogger" xsi:type="Database" connectionString="${configsetting:AppSettings.NlogConnection.AppLogsConnectionString}">-->
<commandText>
insert into dbo.Log (
CorrelationId,Application,ObjectID,Logged,Level,Message,Logger,CallSite,Exception
) values (
@CorrelationId,@Application,@ObjectID,@Logged,@Level,@Message,@Logger,@Callsite,@Exception
);
</commandText>
<parameter name="@correlationId" layout="${aspnet-traceidentifier}" />
<parameter name="@application" layout="${configsetting:AppSettings.NlogConnection.AppName}" />
<parameter name="@ObjectID" layout="${aspnet-user-identity}" />
<!--https://github.com/NLog/NLog/issues/2772-->
<parameter name="@logged" layout="${date}" />
<parameter name="@level" layout="${level}" />
<parameter name="@message" layout="${message}" />
<parameter name="@logger" layout="${logger}" />
<parameter name="@callSite" layout="${callsite:filename=false}" />
<parameter name="@exception" layout="${exception:toString}" />
</target>
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--Skip non-critical Microsoft logs and so log only own logs-->
<!-- Microsoft logger will automatically catch and log all automated warn,error & fatal messages (such as uncaught exceptions) -->
<logger name="Microsoft.*" levels="Warn,Error,Fatal" writeTo="databaseLogger"></logger>
<logger name="Microsoft.*" minLevel="Trace" final="true" />
<!-- BlackHole without writeTo -->
<!--<logger name="Microsoft.*" minLevel="Trace" writeTo="" final="true" />-->
<!-- BlackHole with writeTo -->
<!--<logger name="Microsoft.*" minLevel="Trace" writeTo="blackhole" final="true" />-->
<!-- BlackHole without writeTo -->
<!--All logs,including from Microsoft unless suppressed (which I do,above)-->
<logger name="*" minlevel="Trace" writeTo="allfile" />
<logger name="*" minlevel="${configsetting:AppSettings.NlogConnection.LogLevel" writeTo="databaseLogger" />
<logger name="*" minlevel="Trace" writeTo="ownFile-web" />
</rules>
</nlog>
appsettings.json中的相关代码段
"NlogConnection": {
"LogLevel": "Trace","AppName": "NetCoreApp","DbProvider": "sqlserver","DbHost": "dev-sql01","Database": "AppLogs","User": "NLog","Password": "***********"
}
Program.cs
using System;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using NLog.Web;
using Microsoft.Extensions.Logging;
namespace Website
{
public class Program
{
public static void Main(string[] args)
{
// NLog: setup the logger first to catch all errors
var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
try
{
// These messages are found in the nlog-all-{today} text file
logger.Debug("init main");
CreateWebHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
//NLog: catch setup errors
logger.Error(ex,"Stopped program because of exception");
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit
NLog.LogManager.Shutdown();
}
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
// The Logging configuration specified in appsettings.json overrides any call to SetMinimumLevel.
logging.SetMinimumLevel(LogLevel.Trace);
})
.UseNLog(); // NLog: setup NLog for Dependency injection
}
}
我的本地开发机器安装了IIS 10.0 Express。此设置完全可以正常工作。我将文件记录到我的temp
目录中,从记录器语句创建了数据库行,一切都很好。我可以交换到暂存SQL Server的另一个连接字符串,也可以在其中写入日志。
将其发布到我们的Windows服务器之一(Dev或暂存-从我所看到的配置来看,它们的配置都相同)后,我得到了文件日志记录,但没有数据库日志记录。创建的文件也没有显示错误,并且我能够从应用程序服务器ping SQL服务器。
服务器正在运行Windows Server 2012 R2和IIS 8.5。
当尝试运行Web应用程序时,内部日志将(并非总是)显示以下异常消息-但控制台应用程序却无法获得类似的信息。
2020-08-21 12:33:17.7505 Error DatabaseTarget(Name=databaseLogger): Error when writing to database. Exception: System.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider,error: 40 - Could not open a connection to SQL Server) ---> System.ComponentModel.Win32Exception (2): The system cannot find the file specified
at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity,SqlConnectionString connectionOptions,SqlCredential credential,Object providerInfo,String newPassword,SecureString newSecurePassword,Boolean redirectedUserInstance,SqlConnectionString userConnectionOptions,SessionData reconnectSessionData,Boolean applyTransientFaultHandling,String accessToken)
at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options,DbConnectionPoolKey poolKey,Object poolGroupProviderInfo,DbConnectionPool pool,DbConnection owningConnection,DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool,DbConnection owningObject,DbConnectionOptions options,DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject,DbConnectionOptions userOptions,DbConnectionInternal oldConnection)
at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject,DbConnectionInternal oldConnection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject,UInt32 waitForMultipleObjectsTimeout,Boolean allowCreate,Boolean onlyOneCheckConnection,DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject,TaskCompletionSource`1 retry,DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection,DbConnectionInternal oldConnection,DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection,DbConnectionFactory connectionFactory,DbConnectionOptions userOptions)
at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.Open()
at NLog.Targets.DatabaseTarget.OpenConnection(String connectionString,LogEventInfo logEventInfo)
at NLog.Targets.DatabaseTarget.EnsureConnectionOpen(String connectionString,LogEventInfo logEventInfo)
at NLog.Targets.DatabaseTarget.WriteLogEventToDatabase(LogEventInfo logEvent,String connectionString)
ClientConnectionId:00000000-0000-0000-0000-000000000000
Error Number:2,State:0,Class:20
我尝试过的
为缩小范围,我按照说明here创建了一个简单的控制台应用程序,该应用程序使用NLog写入文件。它可以在我的本地开发机器上运行,因此我将其发布为可执行文件并将其放在服务器上,并确保我在服务器上记录了文件。
然后,我向数据库中添加了一个新表,编辑了nlog.config
(如下所示)以添加数据库目标,然后发现它在我的本地计算机上按预期工作。插入开发和暂存SQL Server信息都可以同时记录文件和数据库。
<?xml version="1.0" encoding="utf-8" ?>
<!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogFile="c:\temp\console-example-internal.log"
internalLogLevel="Info" >
<!-- the targets to write to -->
<targets>
<!-- write logs to file -->
<target xsi:type="File" name="target1" fileName="c:\temp\console-example.log"
layout="${date}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}" />
<target xsi:type="Console" name="target2"
layout="${date}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}" />
<target name="databaseLogger" xsi:type="Database"
dbProvider="sqlserver"
dbHost="dev-sql01"
dbDatabase="AppLogs"
dbUserName="NLog"
dbPassword="********************">
<commandText>
insert into dbo.ConsoleLog (
Logged,Exception
) values (
@Logged,@Exception
);
</commandText>
<parameter name="@logged" layout="${date}" />
<parameter name="@level" layout="${level}" />
<parameter name="@message" layout="${message}" />
<parameter name="@logger" layout="${logger}" />
<parameter name="@callSite" layout="${callsite:filename=false}" />
<parameter name="@exception" layout="${exception:toString}" />
</target>
</targets>
<!-- rules to map from logger name to target -->
<rules>
<logger name="*" minlevel="Trace" writeTo="target1,target2,databaseLogger" />
</rules>
</nlog>
然后我再次发布了具有新目标的应用程序(我知道我可以只更新服务器上的nlog.config
,但我想做到更彻底),并且通过控制台应用程序,我可以进行文件记录和数据库记录正确。
关闭思想和我的问题
目前,我不确定要调查哪个领域。似乎这里的奇怪组件是服务器上的IIS,但以这种速率,我不确定版本是否存在某种不兼容,与服务器以某种怪异方式配置的组件,或与Web应用程序代码相关的组件可能是造成问题的原因。
是否有明显的东西可以引起问题的原因?
解决方法
在我的项目中,我从 nlog.config
切换到通过 appsettings.*.json
配置它并观察到与您相同的错误 - 也仅在应用服务器上。我删除了 nlog.config
,但我的发布设置是在发布前不删除文件,因此文件保留了下来。
解决方案是确保删除所有位置的 nlog.config
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。