If I use newly introduced InProcess
hosting model in ASP.NET Core 2.2
as follows:
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
Serilog
does not write log to file. but if I remove <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
from .csproj
everything works as expected.
My Serilog
configuration in the Program
class as follows:
public class Program
{
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information() // Set the minimun log level
.WriteTo.File("Logs\\log-.txt", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 7) // this is for logging into file system
.CreateLogger();
try
{
Log.Information("Starting web host");
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>()
.ConfigureLogging(logging => { logging.ClearProviders(); }) // clearing all other logging providers
.UseSerilog(); // Using serilog
}
Any thought from the expert please!
Create a Console Application project in Visual Studio. Install Serilog and its dependencies. Create and configure the Serilog global logger. Integrate the logger into the C# Console Application.
Serilog is a third-party, open-source library that integrates nicely with ASP.NET Core and allows developers to easily log-structured event data to the console, to files, and various kinds of log targets.
For example, if you are using Serilog you should configure Log. Logger and LibLog will use it. Also you can disable logging by setting LogProvider. IsDisabled to true . "
In order to proceed with database logging with Serilog in ASP.NET Core, the first step required is to install Serilog. Sinks. MSSqlServer package from NuGet. In the “Write To” subsection, we can set up the database connection string, along with the name of the table we want to create for logs.
As suggested in the comments on your question itself, when running using the InProcess
hosting model, the current directory for the application is different to the OutOfProcess
hosting model. For InProcess
, this directory is the location of IIS itself - e.g. C:\Program Files\IIS Express
, which means that your log files are being written to C:\Program Files\IIS Express\Logs\log-.txt
(assuming that the relevant permissions are set).
A workaround for this is detailed in this GitHub issue, which provides a helper class (CurrentDirectoryHelpers
) for setting the correct current directory. The SetCurrentDirectory
static method uses PInvoke, determining whether or not the application is running from within IIS and if it is, it sets the current directory according to the full application path. Using this approach looks like this:
public class Program
{
public static void Main(string[] args)
{
CurrentDirectoryHelpers.SetCurrentDirectory();
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information() // Set the minimun log level
.WriteTo.File("Logs\\log-.txt", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 7) // this is for logging into file system
.CreateLogger();
...
}
}
Here's CurrentDirectoryHelpers
for completeness:
using System;
namespace SampleApp
{
internal class CurrentDirectoryHelpers
{
internal const string AspNetCoreModuleDll = "aspnetcorev2_inprocess.dll";
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[System.Runtime.InteropServices.DllImport(AspNetCoreModuleDll)]
private static extern int http_get_application_properties(ref IISConfigurationData iiConfigData);
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
private struct IISConfigurationData
{
public IntPtr pNativeApplication;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.BStr)]
public string pwzFullApplicationPath;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.BStr)]
public string pwzVirtualApplicationPath;
public bool fWindowsAuthEnabled;
public bool fBasicAuthEnabled;
public bool fAnonymousAuthEnable;
}
public static void SetCurrentDirectory()
{
try
{
// Check if physical path was provided by ANCM
var sitePhysicalPath = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_PHYSICAL_PATH");
if (string.IsNullOrEmpty(sitePhysicalPath))
{
// Skip if not running ANCM InProcess
if (GetModuleHandle(AspNetCoreModuleDll) == IntPtr.Zero)
{
return;
}
IISConfigurationData configurationData = default(IISConfigurationData);
if (http_get_application_properties(ref configurationData) != 0)
{
return;
}
sitePhysicalPath = configurationData.pwzFullApplicationPath;
}
Environment.CurrentDirectory = sitePhysicalPath;
}
catch
{
// ignore
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With