我有一个ASP.Net Core 2.1网站,该网站使用Azure SQL数据库作为Microsoft Identity组件。
我将Logs表添加到该数据库,并使用SQL Server Sink将Serilog添加到我的网站。
当我在本地运行网站但仍连接到Azure SQL数据库时,可以在Logs
表中看到我的日志条目。但是,将网站部署到Azure App Service时,不再在数据库的Logs
表中获得任何日志条目。
请记住,在已部署的版本中,我可以正常连接并使用Azure SQL数据库存储我的MS Identity,并且可以很好地创建新用户和编辑现有用户。因此,我知道我的App Service应用程序设置中的连接字符串是正确的。
我查看了Serilog MSSQL Github,将其配置建议与我自己的配置建议进行了比较,但找不到任何突出的内容。
我让此设置在我部署到另一个Azure App Service的ASP.Net Core API上正常工作。该服务使用不同的数据库,但是它在同一SQL Server资源上。
当我开始这个问题时,我很幸运地查看了推荐的SO帖子列表。
当我第一次设置用户帐户时,我在数据库上运行了以下SQL;
EXEC sp_addrolemember N'db_datareader', N'myuser'
EXEC sp_addrolemember N'db_datawriter', N'myuser'
EXEC sp_addrolemember N'db_ddladmin', N'myuser'
而且,正如我所说,用户帐户可以更新并在AspNetUsers表中添加用户数据。因此,这似乎不是用户帐户问题。
我已验证Azure应用程序服务DEV部署插槽(我正在测试的一个),应用程序设置,连接字符串中的连接字符串与我在本地DEV UserSecrets中具有的字符串完全相同。另外,再次部署到Azure时,我可以读取/写入同一数据库中的AspNet *表。
这是我设置Serilog的Program.cs类;
public class Program
{
public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.AddUserSecrets<Startup>()
.AddEnvironmentVariables()
.Build();
public static void Main(string[] args)
{
var connectionString = Configuration.GetConnectionString("MyConnectionString");
const string tableName = "Logs";
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.Enrich.WithThreadId()
.WriteTo.MSSqlServer(connectionString, tableName)
.CreateLogger();
// TODO Enable to debug any startup Serilog issues. Make sure to comment out for PROD
//Serilog.Debugging.SelfLog.Enable(msg =>
//{
// Debug.Print(msg);
// Debugger.Break();
//});
try
{
Log.Information("Starting Application");
CreateWebHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseSerilog();
}
}
我在Azure中部署的将日志写入Azure SQL的API与该网站之间的唯一区别是,在较旧的API中,我拥有
public static IWebHost BuildWebHost(string[] args)
在program.cs中,而较新的网站具有
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
所以...任何想法都将不胜感激。
[UPDATE 1/23/19]
我将连接字符串直接添加到
var connectionString
而不是从Program.cs中获取
Configuration.GetConnectionString("MyConnectionString")
,它开始记录到数据库。
因此看来,问题出在Program.cs能够从Azure App Service部署插槽的“应用程序设置”,“连接字符串”部分读取连接字符串。
此连接字符串已从Startup.cs中正确读取,并且自从我首次创建网站以来一直有效。
因此,Azure无法从Program.cs的部署插槽“应用程序设置” /“连接字符串”中读取值是否存在一些已知问题?
答案 0 :(得分:2)
由于Azure似乎存在问题,因此在调用CreateWebHostBuilder之前它不会向Web应用程序提供应用程序设置,这是一个直接的解决方法(假设在源代码中对连接字符串进行硬编码是不可行的选项)是将Serilog配置为在Startup.cs中使用SqlServer而不是Program.cs。
如果重要的是记录在应用程序启动期间发生的初始事件,则可以在Program.cs中临时配置Serilog以写入文件。
Program.cs:
<!DOCTYPE html>
<html lang="en" ng-app="module">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div style="height: 100%" ng-controller="controller" ng-init="init()">
<div id="wrapper">
<div id="scroller">
<div class="card" ng-repeat="i in list">{{i}}</div>
<div id="loading" class="loading">Loading...</div>
</div>
</div>
</div>
</body>
<script src="angular.min.js"></script>
<script src="main.js"></script>
</html>
Startup.cs:
html, body{
margin: 0;
padding: 0;
height: 100%;
}
body{
background-color: #eee;
}
#wrapper{
height:calc(100% - 1px);
}
.card{
background-color: #fff;
height: 80px;
line-height: 80px;
text-align: center;
margin-bottom: 15px;
}
.loading{
height: 80px;
background-color: #e6e6e6;
line-height: 80px;
text-align: center;
}