在前一篇博文(增加文件日志功能遇到的挫折)中,我們遇到了這樣一個問題:雖然有一些.NET日志組件(比如Serilog, NLog)已經開始支持.NET Core,但目前只支持控制臺輸出日志,不支持將日志寫入文件;這就意味著我們在Linux上運行的示例ASP.NET 5站點無法將日志寫入文件,給排查問題造成很大的麻煩,比如現在示例站點經常掛掉的問題。
面對這個問題我們沒有善罷甘休,不想因為這個問題影響.NET跨平臺之旅的步伐,我們要解決它,而且希望先用簡單的方法解決,不想從頭實現一個日志組件。
在上一篇博文發布后,一位同事給出了這樣一個提示:既然Serilog記錄日志時是直接將日志信息寫入控制臺的輸出流( .WriteTo.TextWriter(Console.Out) ),那么應該也可以用它寫入文件的寫入流,都是Stream嘛。
好主意!可行!但有一個前提是corefx中的文件操作類庫要支持Linux,也就是System.IO.FileSystem實現了跨平臺。
那.NET Core中的文件操作類庫是否已經跨平臺了呢?我們的文件日志問題是否可以通過它解決呢?碼一下,就會知道。
于是將Startup.cs中的 .WriteTo.TextWriter(Console.Out) 改為下面的代碼:
.WriteTo.TextWriter(new StreamWriter(logFilePath))
運行 dnx kestrel 命令卻出現下面的錯誤:
DNXCore,Version=v5.0 error CS1503: Argument 1: cannot convert from 'string' to 'System.IO.Stream'
出現這個錯誤是因為corefx中實現的StreamWriter的構造函數不支持文件路徑作為參數,.NET Framework中是支持的。所以需要修改一下代碼,將FileStream類型的參數傳遞給StreamWriter的構造函數,代碼如下:
.WriteTo.TextWriter(new StreamWriter(new FileStream(logFilePath, FileMode.OpenOrCreate)))
這樣改了之后,站點成功啟動。
Logging to /data/git/AboutUs/logs/log.txt Hosting environment: Production Now listening on: http://*:8001 Application started. Press Ctrl+C to shut down.
然后用瀏覽器訪問一下站點,并用tail命令看一下日志是否成功寫入到了日志文件中?
# tail log.txt 11/22/2015 14:08:58 +08:00 [Debug] The view '"Intro"' was found. 11/22/2015 14:08:58 +08:00 [Information] Executing ViewResult, running view at path "/Views/About/Intro.cshtml". 11/22/2015 14:08:58 +08:00 [Information] User profile is available. Using '"/root/.aspnet/DataProtection-Keys"' as key repository; keys will not be encrypted at rest. 11/22/2015 14:09:01 +08:00 [Debug] Data Source=xxx 11/22/2015 14:09:03 +08:00 [Information] Microsoft.Data.Entity.Storage.DbCommandLogData 11/22/2015 14:09:03 +08:00 [Debug] Data Source=xxx 11/22/2015 14:09:03 +08:00 [Information] Executed action "CNBlogs.AboutUs.Web.AboutController.Intro" in 0.6192ms 11/22/2015 14:09:03 +08:00 [Information] Request finished in 0.6196ms 200 text/html; charset=utf-8 11/22/2015 14:09:16 +08:00 [Error] Connection id "4" disconnected. 11/22/2015 14:09:16 +08:00 [Error] Connection id "3" disconnected.
成功!在Linux上記錄ASP.NET 5站點的運行日志到文件的問題就這么臨時解決了。
順便分享一下目前Startup.cs中的最新代碼:
using System; using System.IO; using System.Linq; using Microsoft.AspNet.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Data.Entity; using CNBlogs.AboutUs.Data; using Microsoft.Dnx.Runtime; using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Extensions.Configuration; using System.Data.SqlClient; using Microsoft.Extensions.Logging; using Serilog; namespace CNBlogs.AboutUs.Web { public class Startup { public Startup(IApplicationEnvironment appEnv) { IConfigurationBuilder builder = new ConfigurationBuilder() .SetBasePath(appEnv.ApplicationBasePath) .AddJsonFile("config.json", false); Configuration = builder.Build(); var logFilePath = Path.Combine(appEnv.ApplicationBasePath,"logs/log.txt"); Console.WriteLine("Logging to "+ logFilePath); Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.TextWriter(new StreamWriter( new FileStream(logFilePath, FileMode.OpenOrCreate))) .CreateLogger(); } public IConfiguration Configuration { get; set; } public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { loggerFactory .AddSerilog() .AddConsole(); app.UseDeveloperExceptionPage(); app.UseMvcWithDefaultRoute(); app.UseStaticFiles(); app.UseRuntimeInfoPage(); } public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddEntityFramework() .AddSqlServer() .AddDbContext<EfDbContext>(options => { options.UseSqlServer(Configuration["data:ConnectionString"]); }); services.AddTransient<ITabNavRepository, TabNavRepository>(); } } }
文章列表