file target keepFileOpen=true is holding the log file opened in some exclusive mode. Is there another option for good performance, where NLog file target opens logging file in Shared Read mode?
My scenario is this:
NLog file target to ~/App_Data/Logs/log with keepFileOpen=true
A logviewer MVC controller tries to display last 1000 characters of App_Data/Logs/log but can't because any File.Open attempts, even when using FileMode.Read, FileShare.Read, fails with
IOException: The process cannot access the file "D:\wwwroot\webapplication1\App_Data\Logs\log" because it is being used by another process.]
System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) +893
System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost) +1217
System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share) +123
System.Web.HttpResponse.TransmitFile(String filename, Int64 offset, Int64 length) +136
ASP.logview_aspx.__Render__control1(HtmlTextWriter __w, Control parameterContainer) +590
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +117
System.Web.UI.Page.Render(HtmlTextWriter writer) +39
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +79
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +8753
keepFileOpen=false can be used, but is there a high performance way to still read from the log file, or should I submit a Feature Request for this? (Surprised others haven't mentioned this problem)
NLog doesn't lock the file in exclusive mode when having keepFileOpen=true. The problem is that TransmitFile requires no one has the file opened in write-mode:
https://github.com/Microsoft/referencesource/blob/master/System.Web/HttpResponse.cs#L2816
Try to find a different method for reading the file.
Ok I thought I had tried a different way, but still used FileShare.Read. Using the following works now:
c#
Response.Clear();
string filePath = Server.MapPath("~/App_Data/Logs/log");
using(var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
fs.CopyTo(Response.OutputStream);
}
Response.End();
And that works. Thanks. I figured I was doing something wrong.
@ericnewton76 Glad you were able to figure it out yourself. As your first attempt was just repeating the error of TransmitFile