起動時に失敗する.netコアアプリをデバッグするために、startup.csファイル内からログを書き込みたいと思います。私は、startup.csファイル以外のアプリの残りの部分で使用できるファイル内でログ設定を行っていますが、startup.csファイル自体からログを書き込む方法がわかりません。
回答:
.Net Core 3.1
残念ながら、ASP.NET Core 3.0では、状況が少し異なります。デフォルトのテンプレートは、HostBuilder
(の代わりにWebHostBuilder
)を使用して、Webアプリケーションに限定されない、いくつかの異なるアプリケーションをホストできる新しい汎用ホストをセットアップします。この新しいホストの一部は、以前はWebホストに存在していた2番目の依存関係注入コンテナの削除でもあります。これは、最終的にはIConfiguration
、Startup
クラス以外の依存関係を注入できないことを意味します。したがって、ConfigureServices
メソッドの実行中はログに記録できません。ただし、ロガーをConfigure
メソッドに挿入してそこに記録することはできます。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILogger<Startup> logger)
{
logger.LogInformation("Configure called");
// …
}
内で絶対にログを記録する必要がある場合は、クラスにロガーを挿入できるレガシーを作成するをConfigureServices
引き続き使用できます。Webホストは将来のある時点で削除される可能性が高いことに注意してください。そのため、にログインしなくても機能する解決策を見つける必要があります。WebHostBuilder
WebHost
Startup
ConfigureServices
.NET Core 2.x
これは、ASP.NET Core 2.0のリリースで大幅に変更されました。ASP.NET Core 2.xでは、ログはホストビルダーで作成されます。つまり、ロギングはデフォルトでDIを介して利用でき、Startup
クラスに注入できます。
public class Startup
{
private readonly ILogger<Startup> _logger;
public IConfiguration Configuration { get; }
public Startup(ILogger<Startup> logger, IConfiguration configuration)
{
_logger = logger;
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
_logger.LogInformation("ConfigureServices called");
// …
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
_logger.LogInformation("Configure called");
// …
}
}
ConfigureServices
実行時にロガーがまだ実際には存在しないため、これは「困難」です。そのため、まだロガーがないため、その時点ではログに記録できません。プラス面としては、ロガーはConfigureServices
すべて同じDIコンテナー(実際には良いことです)であるため、ロガーを内で構成する機能を提供します。–どうしてもログを記録する必要がある場合は、たとえば、情報を個別に(リストなどで)収集し、ロガーが利用可能になったらすぐにログアウトできます。
.NET 3.1
、あなたは現在の中にログインCAN ConfigureServices
方法なしに戻って落ちますWebHostBuilder
。下記の使用の答え:stackoverflow.com/a/61488490/2877982
Startup.cs
ので(依存関係を忘れるとコンパイラエラーが発生します)。したがって、これらのロガーを解決する必要があります。しかし、これは少しハックかもしれません、はい。
オプション1:スタートアップでログ(Serilogなど)を直接使用する
public class Startup
{
public Startup(IHostingEnvironment env)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.RollingFile(Path.Combine(env.ContentRootPath, "Serilog-{Date}.txt"))
.CreateLogger();
Log.Information("Inside Startup ctor");
....
}
public void ConfigureServices(IServiceCollection services)
{
Log.Information("ConfigureServices");
....
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
Log.Information("Configure");
....
}
出力:
asp.net-coreアプリケーションでSerilogをセットアップするには、GitHubのSerilog.AspNetCoreパッケージを確認してください。
Option2:このようにprogram.csのロギングを設定します-
var host = new WebHostBuilder()
.UseKestrel()
.ConfigureServices(s => {
s.AddSingleton<IFormatter, LowercaseFormatter>();
})
.ConfigureLogging(f => f.AddConsole(LogLevel.Debug))
.UseStartup<Startup>()
.Build();
host.Run();
このように起動時のユーザーloggerFactory
public class Startup
{
ILogger _logger;
IFormatter _formatter;
public Startup(ILoggerFactory loggerFactory, IFormatter formatter)
{
_logger = loggerFactory.CreateLogger<Startup>();
_formatter = formatter;
}
public void ConfigureServices(IServiceCollection services)
{
_logger.LogDebug($"Total Services Initially: {services.Count}");
// register services
//services.AddSingleton<IFoo, Foo>();
}
public void Configure(IApplicationBuilder app, IFormatter formatter)
{
// note: can request IFormatter here as well as via constructor
_logger.LogDebug("Configure() started...");
app.Run(async (context) => await context.Response.WriteAsync(_formatter.Format("Hi!")));
_logger.LogDebug("Configure() complete.");
}
}
このリンクで利用可能な完全な詳細
私は、サードパーティのロガーがILoggerインターフェイスで「ロガーバッファー」を実装しないようにするソリューションを使用しています。
public class LoggerBuffered : ILogger
{
class Entry
{
public LogLevel _logLevel;
public EventId _eventId;
public string _message;
}
LogLevel _minLogLevel;
List<Entry> _buffer;
public LoggerBuffered(LogLevel minLogLevel)
{
_minLogLevel = minLogLevel;
_buffer = new List<Entry>();
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return logLevel >= _minLogLevel;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
if (IsEnabled(logLevel)) {
var str = formatter(state, exception);
_buffer.Add(new Entry { _logLevel = logLevel, _eventId = eventId, _message = str });
}
}
public void CopyToLogger (ILogger logger)
{
foreach (var entry in _buffer)
{
logger.Log(entry._logLevel, entry._eventId, entry._message);
}
_buffer.Clear();
}
}
startup.csでの使用は簡単です。もちろん、Configureの呼び出し後にログ出力が表示されます。しかし、何もないよりはましだ。:
public class Startup
{
ILogger _logger;
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
_logger = new LoggerBuffered(LogLevel.Debug);
_logger.LogInformation($"Create Startup {env.ApplicationName} - {env.EnvironmentName}");
}
public void ConfigureServices(IServiceCollection services)
{
_logger.LogInformation("ConfigureServices");
services.AddControllersWithViews();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
(_logger as LoggerBuffered).CopyToLogger(logger);
_logger = logger; // Replace buffered by "real" logger
_logger.LogInformation("Configure");
if (env.IsDevelopment())
.NET Core 3.0の場合、公式ドキュメントには次のように記載されています。https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/? view = aspnetcore-3.0#create-logs-in-startup
Startup.ConfigureServices
メソッドでDIコンテナーのセットアップが完了する前にログを書き込むことはサポートされていません。
Startup
コンストラクターへのロガー注入はサポートされていません。- ロガー注入
Startup.ConfigureServices
方法署名がサポートされていません
しかし、彼らがドキュメントで言うように、ILoggerに依存するサービスを設定することができるので、クラスStartupLoggerを作成した場合:
public class StartupLogger
{
private readonly ILogger _logger;
public StartupLogger(ILogger<StartupLogger> logger)
{
_logger = logger;
}
public void Log(string message)
{
_logger.LogInformation(message);
}
}
次に、Startup.ConfigureServicesでサービスを追加し、DIコンテナーにアクセスするためのサービスプロバイダーを構築する必要があります。
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(provider =>
{
var service = provider.GetRequiredService<ILogger<StartupLogger>>();
return new StartupLogger(service);
});
var logger = services.BuildServiceProvider().GetRequiredService<StartupLogger>();
logger.Log("Startup.ConfigureServices called");
}
編集:これはコンパイラの警告を生成します。StartUpクラスをデバッグするために、これは問題ありませんが、本番環境では使用できません。
Startup.cs(39, 32): [ASP0000] Calling 'BuildServiceProvider' from application code results in an additional copy of singleton services being created. Consider alternatives such as dependency injecting services as parameters to 'Configure'.
.net core 3.1によると、LogFactoryを使用してロガーを直接作成できます。
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConsole();
});
ILogger logger = loggerFactory.CreateLogger<Startup>();
logger.LogInformation("Example log message");
公式の解決策は現在、次のようにローカルのLoggerFactoryをセットアップすることです。
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder.SetMinimumLevel(LogLevel.Information);
builder.AddConsole();
builder.AddEventSourceLogger();
});
var logger = loggerFactory.CreateLogger("Startup");
logger.LogInformation("Hello World");
参照:https : //github.com/dotnet/aspnetcore/issues/9337#issuecomment-539859667
メインコード:
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
CreateDefaultBuilderは、デフォルトのコンソールロガーを設定します。
... ILoggerFactoryを設定してコンソールにログを記録し、出力をデバッグします
スタートアップコード:
using Microsoft.Extensions.Logging;
...
public class Startup
{
private readonly ILogger _logger;
public Startup(IConfiguration configuration, ILoggerFactory logFactory)
{
_logger = logFactory.CreateLogger<Startup>();
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
_logger.LogInformation("hello stackoverflow");
}
ILoggerのインジェクションを機能させることができませんでしたが、おそらくそれがコントローラーではないためです。詳細情報へようこそ!
参照:
上記の答えはどれもうまくいきませんでした。私はNLogを使用しており、新しいServiceCollectionを構築し、任意のサービスコレクションで.CreateBuilder()を呼び出し、ロギングサービスを作成しています。ConfigureServicesの実行中にログファイルに書き込むものはありません。
問題は、ServiceCollectionが構築されるまでロギングが実際には行われず、ConfigureServices中に構築されないことです。
基本的に、起動中に何が起こっているかを構成拡張メソッドでログに記録したい(必要な)だけです。問題が発生しているのは、デバッガーを接続できないPRODだけだからです。
私に有効な解決策は、古い.NET Framework NLogメソッドを使用することでし
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
た。拡張メソッドクラスにその権利を追加し、ConfigureServices以降のログ( "the"ログ)に書き込むことができました。
これが実際に製品コードにリリースするのが良いアイデアかどうかはわかりません(.NET制御のILoggerとこのNLog.ILoggerがいつ競合するかはわかりません)。オン。
私は、ファイルにNlogを含むロガーを静的に作成することによってこれを行うことができ、起動メソッド内でこれを使用します。
private readonly NLog.Logger _logger = new NLog.LogFactory().GetCurrentClassLogger();
System.IO.File.Write()
メソッド以外だと思います。