Coder Social home page Coder Social logo

nlog / nlog.web Goto Github PK

View Code? Open in Web Editor NEW
314.0 23.0 168.0 3.83 MB

NLog integration for ASP.NET & ASP.NET Core 2-8

Home Page: https://nlog-project.org

License: BSD 3-Clause "New" or "Revised" License

C# 99.79% PowerShell 0.21%
nlog asp-net asp-net-core asp-net-core-mvc csharp dotnet netstandard20 netcore logger logging

nlog.web's Introduction

NLog

NLog.Web (ASP.NET & ASP.NET Core)

NuGet Release

NuGet Release

Build status

These packages are extensions to NLog, and provides targets and layout-renderes specific to ASP.NET (Core), MVC and IIS.

Getting started with NLog

Config

Troubleshooting

Releases

For updates and releases, check CHANGELOG.MD or Releases

ASP.NET Core

The NLog.Web.AspNetCore-package supports the platforms:

  • For ASP.NET Core - .NET 5, 6, 7 and 8
  • For ASP.NET Core - .NET Core 3.1
  • For ASP.NET Core 2.1 .NET Standard 2.0 for .NET 4.6.1

ℹī¸ Missing the trace and debug logs? Check your appsettings.json

Use the NLog.Web.AspNetCore package

ASP.NET (non-core)

The NLog.Web-package works with classic ASP.NET MVC

  <!-- enable ASP.NET layout renderers -->
  <extensions>
    <add assembly="NLog.Web"/>
  </extensions>

HTTP module (ASP.NET non-core)

There is a ASP.NET ASP.NET HttpModule that enables NLog to hook BeginRequest and EndRequest events easily.

The NLogHttpModule needs a registration in the web.config:

<system.webServer> 
	<modules runAllManagedModulesForAllRequests="true"> 
		<add name="NLog" type="NLog.Web.NLogHttpModule, NLog.Web" />
	</modules>
</system.webServer>

Contributions

Contributions are highly appreciated! Please make sure if works for ASP.NET and ASP.NET Core if possible and make sure it is covered by unit tests.

License

BSD

nlog.web's People

Contributors

304notmodified avatar abakumov-v avatar alexangas avatar bakgerman avatar blaikic avatar czd890 avatar dafanasiev avatar damienbod avatar defee avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar drewbrasher avatar epignosisx avatar giorgi avatar grokky1 avatar johnkors avatar kichristensen avatar mcliment avatar page-not-found avatar petemounce avatar repo-ranger[bot] avatar s-sreenath avatar sm-g avatar snakefoot avatar thomasardal avatar timabell avatar vegar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nlog.web's Issues

Update docs for Nlog.Web 4.3

we need to document all the new layout renderers introducted in NLog.web 4.3 in the wiki (https://github.com/NLog/NLog/wiki/Layout-Renderers#nlogweb-package-) (under "NLog.Web package").

The new layout renderers (are already in master): v4.2.1-aspnet4...master

see #54

all new:

  • AspNetCookieLayoutRenderer
  • AspNetCoreHostLayoutRenderer
  • AspNetMvcActionRenderer
  • AspNetMvcControllerRenderer
  • AspNetMvcLayoutRendererBase
  • AspNetQueryStringLayoutRenderer
  • AspNetRequestHttpMethodRenderer
  • AspNetRequestReferrerRenderer
  • AspNetRequestUrlRenderer
  • AspNetRequestuseragent

AspNetLayoutRendererBase being scanned, but not invoked

I have the following class:

[LayoutRenderer("request-session-id")]
public class RequestSessionIdLayoutRenderer : AspNetLayoutRendererBase
{
    protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent)
    {
       builder.Append("Some value");
    }
}

Which is being registered in Configure() like this:

ConfigurationItemFactory.Default.LayoutRenderers.RegisterDefinition("request-session-id", typeof(RequestSessionIdLayoutRenderer));

And being used like this:

<extensions>
  <add assembly="My.WebApi"/>
</extensions>

<parameter name="@sessionid" layout="${request-session-id}" />

In the trace log I can see the assembly being scanned and the class being found.
However it never executes DoAppend() and the variable will never be filled.

I've tried NLog 4.4.1 and the latest 5.0.0 beta.

AspNetCore: AspNetUserIdentityLayoutRenderer throws an exception when retrieving Identity.Name

Error can be observed only with throwExceptions="true". In this case, exception is thrown and Kestrel shuts down connection.

Target configuration:

<target xsi:type="File" name="appFileTarget" fileName="${basedir}/logs/log-${shortdate}.log"
        layout="${longdate}|${uppercase:${level}}|${aspnet-user-identity}|${logger}|${message} ${exception}" />

Packages:

"NLog": "4.4.1",
"NLog.Web.AspNetCore": "4.2.4",
"NLog.Extensions.Logging": "1.0.0-rtm-alpha5",

SDK:

"sdk": {
  "version": "1.0.0-preview2-1-003177"
}

Stack Trace of innermost exception:

System.ObjectDisposedException: Safe handle has been closed
   at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success)
   at System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success)
   at Microsoft.Win32.Win32Native.GetTokenInformation(SafeAccessTokenHandle TokenHandle, UInt32 TokenInformationClass, SafeLocalAllocHandle TokenInformation, UInt32 TokenInformationLength, UInt32& ReturnLength)
   at System.Security.Principal.WindowsIdentity.GetTokenInformation(SafeAccessTokenHandle tokenHandle, TokenInformationClass tokenInformationClass)
   at System.Security.Principal.WindowsIdentity.get_User()
   at System.Security.Principal.WindowsIdentity.GetName()
   at System.Security.Principal.WindowsIdentity.get_Name()
   at NLog.Web.LayoutRenderers.AspNetUserIdentityLayoutRenderer.DoAppend(StringBuilder builder, LogEventInfo logEvent)
   at NLog.LayoutRenderers.LayoutRenderer.Render(StringBuilder builder, LogEventInfo logEvent)
   at NLog.Layouts.SimpleLayout.GetFormattedMessage(LogEventInfo logEvent)
   at NLog.Targets.FileTarget.GetFormattedMessage(LogEventInfo logEvent)
   at NLog.Targets.FileTarget.GetBytesToWrite(LogEventInfo logEvent)
   at NLog.Targets.FileTarget.Write(LogEventInfo logEvent)
   at NLog.Targets.Target.Write(AsyncLogEventInfo logEvent)
   at NLog.Targets.Target.WriteAsyncThreadSafe(AsyncLogEventInfo logEvent)
   at NLog.Targets.Target.WriteAsyncLogEvent(AsyncLogEventInfo logEvent)
   at NLog.LoggerImpl.WriteToTargetWithFilterChain(TargetWithFilterChain targetListHead, LogEventInfo logEvent, AsyncContinuation onException)
   at NLog.LoggerImpl.Write(Type loggerType, TargetWithFilterChain targets, LogEventInfo logEvent, LogFactory factory)
   at NLog.Logger.Log(LogEventInfo logEvent)
   at NLog.Extensions.Logging.NLogLogger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
   at Microsoft.Extensions.Logging.Logger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)

Our application is using WindowsAuthentication. User's Identity is not replaced, only an additional identity is added to the principal.

Strangest thing, it happens after few messages were already successfully logged.

Will try later to reproduce in a sample project.

Database Target - Connection String as an IP Address

I'm building an ASP.NET Core Web API Prototype using the new NLog.Web.AspNetCore v4.2.4 writing my logs to a SQL Server database. However, if I attempt to use the IP Address of the SQL Server in the NLog connection string, no logging occurs. For example:
<target xsi:type="Database" name="database" dbProvider="sqlserver" dbHost="123.45.6.7,1433" dbDatabase="MyDbName" dbUserName="SA" dbPassword="aPass123">

The same connection string for Entity Framework Core works for the rest of the application:
"ConnectionStrings": { "DbConnStr": "Data Source=123.45.6.7,1433; Database=MyDbName;user id=SA;password=aPass123;" }

With this configuration, I am able to add, edit records on my database via EntityFrameworkCore, however, no logging via NLog occurs.

I'm not sure if it is relevant but both the app and the SQL Server database are being hosted in Docker Containers (on the same machine & docker bridge network).

Am I missing something or does NLog.Web.ASPNetCore not currently support the use of an IP Address?

My NLog dependencies in my project.json:
"NLog.Extensions.Logging": "1.0.0-rtm-alpha5", "NLog.Web.AspNetCore": "4.2.4"

rename layout renderers for consistency

  • aspnet-request-cookie - To Render cookie(s) from the request. Allows comma separated to get multiple cookie values. Can also allow json formatting.
  • aspnet-request-querystring - querystring
  • aspnet-request-method - the method (GET/POST etc)
  • aspnet-request-referrer - To Render the Referrer URL.
  • aspnet-request-url - To Render the Request URL.a
  • aspnet-useragent - To Capture the Useragent of the request.
  • aspnet-host- The host of the request
  • aspnet-mvc-action - action name

  • aspnet-mvc-controller - controller name

  • rename aspnet-host

  • rename aspnet-useragent

Additional Request Layout renderers + split into new layout renderers

What do you think about including AspNet layout renderers for the following:

  1. User Agent: useful to correlate an issue with an specific browser or better yet to identify that a bot performed the request and ignore the error since must likely the bot passed invalid data.
  2. Request Url: super important to try to reproduce the error. What page generated the error!
  3. Referer Url: useful when trying to understand how a user end up in the current url.
  4. Post Body: critical to know what data the user entered that generated the error. Caveat: we have to provide a way to mask certain information like PII and PCI.
  5. IP Address: useful for analytics. You can understand where your users are coming from.
  6. True Client IP Address: if a website is behind a CDN like Akamai or CloudFlare the IP address the web app receives is from one of the nodes of the CDN, they usually send the true client IP in a HTTP header. Caveat: each CDN uses a different headers so we will need to make it configurable but have a few of the major players.

${assembly-version} returns "Could not find entry assembly" in ASP.NET

moved from NLog/NLog#275

reported by @slolife:


the ${assembly-version} layout renderer returns "Could not find entry assembly" in ASP.NET. It seems that:

var assembly = Assembly.GetEntryAssembly();

Returns null in ASP.NET situations.

There is a StackOverflow question/answer that seems to have a solution:

http://stackoverflow.com/a/4803419/698

For myself, I've been able to make it work with:

Assembly assembly = HttpContext.Current == null ? Assembly.GetEntryAssembly() : Assembly.GetExecutingAssembly();

edit:
this only works in the assembly itself


Steps

If everything works as expected, the layout renderer can be added with the same name to NLog.Web. It should overwrite the one from core. (double check that).

Steps:

  • Create a subclass of the current layout renderer in NLog.Web, same name, different namespace.
  • Implement proposed code
  • Test with unit test in NLog.web

strongname is 0.0.0.0 since NLog.Web 4.2.1

Since NLog.Web 4.2.1 is the strongname 0.0.0.0 instead of 4.0.0.0, which is wrong.

4.2.0:

image

4.2.1:
image

4.3.0:
image

This is no problem in NLog.Web.AspNetCore (checked 4.2.4 and 4.3.0)

Move to 1 solution

currently there are 2 solutions, 1 ASP.NET classic and 1 ASP.NET Core

This could be in one solution, (but still separated projects)

Some configuration still needed for asp.net mvc projects

Hi, i have Asp.net MVC 5 project targets 4.5.2 framework which uses NLog and its AspNetBufferingWrapper to write logs per request. I have upgraded to latest NLog(4.2.3) and NLog.Web(4.1) nuget packages. As your readme says: "no additional configuration is needed". So i do nothing in my web.config. My nlog.config was very basic
<nlog> <targets> <target name="aspNetBufferingFileTarget" xsi:type="ASPNetBufferingWrapper"> <target xsi:type="File" fileName="C:/Log/test.log" layout="${message}" encoding="utf-8" /> </target> </targets> <rules> <logger name="*" minlevel="Debug" writeTo="aspNetBufferingFileTarget" final="true"/> </rules> </nlog>
For testing purposes i do multiple parallel requests to one of my test action (that simply write some logs then Thread.Sleep for 1 sec and again write some more logs) the go to see what logs do i get - it was complete mess, there is no buffering per request at all. So i turned on nlog tracing and see that ther is something wrong

first(when application starts) http request:
2016-01-28 12:30:36.2329 Trace Appending log event 1 to ASP.NET request buffer.
2016-01-28 12:30:36.2329 Trace Appending log event 2 to ASP.NET request buffer.

second(and all others) http requests:
2016-01-28 12:30:44.6534 Trace ASP.NET request buffer does not exist. Passing to wrapped target.
2016-01-28 12:30:44.6534 Trace Opening C:/Log/test.log with allowFileSharedWriting=False
2016-01-28 12:30:44.6723 Trace ASP.NET request buffer does not exist. Passing to wrapped target.
2016-01-28 12:30:44.6723 Trace Opening C:/Log/test.log with allowFileSharedWriting=False

It seems to be that ASPNetBufferingWrapper doesnt get HttpContext.Current for this requests.

After some digging in demo projects that ships with nlog i found that some of them actualy has this configuration in web.config:
<system.webServer> <modules runAllManagedModulesForAllRequests="true"> <add name="NLog" type="NLog.Web.NLogHttpModule, NLog.Web" /> </modules> </system.webServer>

After adding this to my web.config problems with logging is gone.

2016-01-28 12:57:09.1926 Trace Appending log event 1 to ASP.NET request buffer.
2016-01-28 12:57:09.2018 Trace Appending log event 2 to ASP.NET request buffer.
2016-01-28 12:57:16.2365 Trace Sending buffered events to wrapped target: File Target[(unnamed)].
2016-01-28 12:57:16.2641 Trace Opening c:\Log\test.log with concurrentWrite=False

So i think it is critical for ASPNetBufferingWrapper to work correctly and you should make a statement about that in readme

Cannot access the constructor of type: NLog.Web.LayoutRenderers.AspNetRequestValueLayoutRenderer. Is the required permission granted?

NLog.NLogConfigurationException was unhandled by user code
  HResult=-2146233088
  Message=Cannot access the constructor of type: NLog.Web.LayoutRenderers.AspNetRequestValueLayoutRenderer. Is the required permission granted?
  Source=NLog
  StackTrace:
       at NLog.Internal.FactoryHelper.CreateInstance(Type t)
       at NLog.Config.Factory`2.TryCreateInstance(String itemName, TBaseType& result)
       at NLog.Config.Factory`2.CreateInstance(String name)
       at NLog.Layouts.LayoutParser.ParseLayoutRenderer(ConfigurationItemFactory configurationItemFactory, SimpleStringReader sr)
       at NLog.Layouts.LayoutParser.CompileLayout(ConfigurationItemFactory configurationItemFactory, SimpleStringReader sr, Boolean isNested, String& text)
       at NLog.Layouts.SimpleLayout.set_Text(String value)
       at NLog.Layouts.SimpleLayout..ctor(String txt, ConfigurationItemFactory configurationItemFactory)
       at NLog.Internal.PropertyHelper.TryNLogSpecificConversion(Type propertyType, String value, Object& newValue, ConfigurationItemFactory configurationItemFactory)
       at NLog.Internal.PropertyHelper.SetPropertyFromString(Object obj, String propertyName, String value, ConfigurationItemFactory configurationItemFactory)
       at NLog.Config.XmlLoggingConfiguration.ConfigureObjectFromAttributes(Object targetObject, NLogXmlElement element, Boolean ignoreType)
       at NLog.Config.XmlLoggingConfiguration.ParseTargetElement(Target target, NLogXmlElement targetElement)
       at NLog.Config.XmlLoggingConfiguration.ParseTargetsElement(NLogXmlElement targetsElement)
       at NLog.Config.XmlLoggingConfiguration.ParseNLogElement(NLogXmlElement nlogElement, String filePath, Boolean autoReloadDefault)
       at NLog.Config.XmlLoggingConfiguration.ParseTopLevel(NLogXmlElement content, String filePath, Boolean autoReloadDefault)
       at NLog.Config.XmlLoggingConfiguration.Initialize(XmlReader reader, String fileName, Boolean ignoreErrors)
       at NLog.Config.XmlLoggingConfiguration..ctor(String fileName, Boolean ignoreErrors)
       at NLog.Extensions.Logging.AspNetExtensions.ConfigureNLog(String fileName)
       at NLog.Extensions.Logging.AspNetExtensions.ConfigureNLog(IHostingEnvironment env, String configFileRelativePath)
       at aspnet5application.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) in X:\_github\nlog\NLog.Framework.logging\examples\aspnet5application\src\aspnet5application\Startup.cs:line 50
  InnerException: 

License

Readme.md mentions BSD as license and the LICENSE file is GPL. Which one is the correct one?

Use of asp-session causing stack overflow

Hi,

I've got a situation where if dnx is restarted for any reason (and thus sessions invalidated) any logging that is performed that has a layout that includes aspnet-session causes a stack overflow. I assume that somewhere there is some code that is trying to log the fact that the session has expired and so given that nlog is then trying to access the session again, we are getting a stack overflow.

Is there any solution to this? We would like to log some information from the session but we obviously cannot have the server crash just from someone accessing the server with an expired session.

Below is a copy of the repeating section of the stack trace:

Microsoft.AspNet.Session.dll!Microsoft.AspNet.Session.DistributedSession.LoadAsync()    Unknown
    mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<Microsoft.AspNet.Session.DistributedSession.<LoadAsync>d__19>(ref Microsoft.AspNet.Session.DistributedSession.<LoadAsync>d__19 stateMachine)  Unknown
    Microsoft.AspNet.Session.dll!Microsoft.AspNet.Session.DistributedSession.LoadAsync()    Unknown
    Microsoft.AspNet.Session.dll!Microsoft.AspNet.Session.DistributedSession.Load() Unknown
    Microsoft.AspNet.Session.dll!Microsoft.AspNet.Session.DistributedSession.TryGetValue(string key, out byte[] value)  Unknown
    Microsoft.AspNet.Http.Extensions.dll!Microsoft.AspNet.Http.SessionExtensions.Get(Microsoft.AspNet.Http.Features.ISession session, string key)   Unknown
    Microsoft.AspNet.Http.Extensions.dll!Microsoft.AspNet.Http.SessionExtensions.GetString(Microsoft.AspNet.Http.Features.ISession session, string key) Unknown
    NLog.Web.ASPNET5.dll!NLog.Web.LayoutRenderers.AspNetSessionValueLayoutRenderer.DoAppend.AnonymousMethod__0(string k)    Unknown
    NLog.Web.ASPNET5.dll!NLog.Web.Internal.PropertyReader.GetValue(string key, System.Func<string, object> getVal, bool evaluateAsNestedProperties) Unknown
    NLog.Web.ASPNET5.dll!NLog.Web.LayoutRenderers.AspNetSessionValueLayoutRenderer.DoAppend(System.Text.StringBuilder builder, NLog.LogEventInfo logEvent)  Unknown
    NLog.Web.ASPNET5.dll!NLog.Web.LayoutRenderers.AspNetLayoutRendererBase.Append(System.Text.StringBuilder builder, NLog.LogEventInfo logEvent)    Unknown
    NLog.dll!NLog.LayoutRenderers.LayoutRenderer.Render(System.Text.StringBuilder builder, NLog.LogEventInfo logEvent)  Unknown
    NLog.dll!NLog.Layouts.SimpleLayout.GetFormattedMessage(NLog.LogEventInfo logEvent)  Unknown
    NLog.dll!NLog.Layouts.Layout.Render(NLog.LogEventInfo logEvent) Unknown
    NLog.dll!NLog.Layouts.Layout.Precalculate(NLog.LogEventInfo logEvent)   Unknown
    NLog.dll!NLog.Targets.Target.PrecalculateVolatileLayouts(NLog.LogEventInfo logEvent)    Unknown
    NLog.dll!NLog.Targets.Wrappers.AsyncTargetWrapper.Write(NLog.Common.AsyncLogEventInfo logEvent) Unknown
    NLog.dll!NLog.Targets.Target.WriteAsyncLogEvent(NLog.Common.AsyncLogEventInfo logEvent) Unknown
    NLog.dll!NLog.LoggerImpl.WriteToTargetWithFilterChain(NLog.Internal.TargetWithFilterChain targetListHead, NLog.LogEventInfo logEvent, NLog.Common.AsyncContinuation onException)    Unknown
    NLog.dll!NLog.LoggerImpl.Write(System.Type loggerType, NLog.Internal.TargetWithFilterChain targets, NLog.LogEventInfo logEvent, NLog.LogFactory factory)    Unknown
    NLog.dll!NLog.Logger.WriteToTargets(NLog.LogEventInfo logEvent) Unknown
    NLog.dll!NLog.Logger.Log(NLog.LogEventInfo logEvent)    Unknown
    NLog.Extensions.Logging.dll!NLog.Extensions.Logging.NLogLogger.Log(Microsoft.Extensions.Logging.LogLevel logLevel, int eventId, object state, System.Exception exception, System.Func<object, System.Exception, string> formatter)  Unknown
    Microsoft.Extensions.Logging.dll!Microsoft.Extensions.Logging.Logger.Log(Microsoft.Extensions.Logging.LogLevel logLevel, int eventId, object state, System.Exception exception, System.Func<object, System.Exception, string> formatter)    Unknown
    Microsoft.Extensions.Logging.Abstractions.dll!Microsoft.Extensions.Logging.LoggerExtensions.LogWarning(Microsoft.Extensions.Logging.ILogger logger, string format, object[] args)   Unknown

Consider creating an AspNetLayoutRendererBase class

I just went through the exercise of creating a few custom Layout Renderers for AspNet and I experienced some pain points that I wanted to share and provide a solution.

Problem

1- Looking at the LayoutRenderers that are part of the NLog.Web package there is a bit of duplication in all of them in the form:

    HttpContext context = HttpContext.Current;
    if (context == null)
    {
        return;
    }

    var httpRequest = context.Request;
    if (httpRequest == null)
    {
        return;
    }

2- The raw usage of the static HttpContext.Current in the layout renderers makes it hard to unit test. I looked at how the NLog.Web layout renderers were unit tested and most do not have unit tests. Maybe this is part of the reason.

Proposal

Introduce the following two concepts: IHttpContextProvider and AspNetLayoutRendererBase:

    public interface IHttpContextProvider
    {
        HttpContextBase Get(); //returns HttpContextBase which is unit testable.
    }

    public class DefaultHttpContextProvider : IHttpContextProvider
    {
        public HttpContextBase Get()
        {
            if (HttpContext.Current == null)
                return null;
            return new HttpContextWrapper(HttpContext.Current);
        }
    }

    public abstract class AspNetLayoutRendererBase : LayoutRenderer
    {
        private readonly IHttpContextProvider _httpContextProvider;

        //this is the constructor that would run during "normal" mode
        protected AspNetLayoutRendererBase() : this(new DefaultHttpContextProvider())
        {
        }

        //this constructor can be used during unit tests to pass an implementation will return a
        //a mocked HttpContextBase
        protected AspNetLayoutRendererBase(IHttpContextProvider httpContextProvider)
        {
            _httpContextProvider = httpContextProvider;
        }

        //Expose a property that subclasses can use instead of the static HttpContext.Current
        public HttpContextBase HttpContext
        {
            get { return _httpContextProvider.Get(); }
        }

        protected override void Append(StringBuilder builder, LogEventInfo logEvent)
        {
            //do this check in the base class instead of in each Layout Renderer
            if (HttpContext == null)
                return;

            //subclasses implement this method with the assurance that they will have a valid HttpContext.
            AppendCore(builder, logEvent);
        }

        protected abstract void AppendCore(StringBuilder builder, LogEventInfo logEvent);
    }

Here is a sample Layout Renderer:

    [LayoutRenderer("aspnet-client-real-ip")]
    public class AspNetRealIpLayoutRenderer : AspNetLayoutRendererBase
    {
        public AspNetRealIpLayoutRenderer()
        {
        }

        public AspNetRealIpLayoutRenderer(IHttpContextProvider httpContextProvider) : base(httpContextProvider)
        {
        }

        protected override void AppendCore(StringBuilder builder, LogEventInfo logEvent)
        {
            var httpRequest = HttpContext.Request;

            string ip = httpRequest.Headers["True-Client-IP"] ?? httpRequest.Headers["X-Forwarded-For"];
            if (string.IsNullOrEmpty(ip))
            {
                return;
            }

            if (!IpValidator.IsValid(ip))
            {
                return;
            }

            builder.Append(ip);
        }
    }

Here is how the unit tests would look like:

    [Fact]
    public void NullHttpContextRendersEmptyString()
    {
        var renderer = new AspNetRealIpLayoutRenderer();

        string value = renderer.Render(new LogEventInfo(LogLevel.Debug, "LoggerName", "Msg"));

        Assert.Empty(value);
    }

    [Fact]
    public void RendersRealClientIp()
    {
        var ip = "1.0.0.1";
        var httpContext = Substitute.For<HttpContextBase>();
        var httpRequest = Substitute.For<HttpRequestBase>();
        var headers = new NameValueCollection { { "True-Client-IP", ip } };
        httpRequest.Headers.Returns(headers);
        httpContext.Request.Returns(httpRequest);
        var httpContextProvider = Substitute.For<IHttpContextProvider>();
        httpContextProvider.Get().Returns(httpContext);

        var renderer = new AspNetRealIpLayoutRenderer(httpContextProvider);

        string value = renderer.Render(new LogEventInfo(LogLevel.Debug, "LoggerName", "Msg"));

        Assert.Equal(ip, value);
    }

Additional Renderer - Consolidation - Proposal

Consolidated List of Additional Renderer from various requests #21, #45

  • 1. aspnet-request-cookie - To Render cookie(s) from the request. Allows comma separated to get multiple cookie values. Can also allow json formatting.
  • 2. aspnet-request-querystring - To Render querystring(s) from the request. Allows comma separated to get multiple querystring values. Can also allow json formatting.
  • 4. aspnet-request-method - To Render the Http Method for the request.
  • 5. aspnet-request-referrer - To Render the Referrer URL.
  • 6. aspnet-request-url - To Render the Request URL.
  • 7. aspnet-mvc-action - To Render the MVC action method.
  • 8. aspnet-mvc-controller - To Render the MVC Controller Name.
  • 9. aspnet-host - To Capture the HOST.in MVC Core Apps (a.k.a ASP.NET 5)
  • 12. aspnet-useragent - To Capture the Useragent of the request.

Nice to Have

  1. aspnet-mvc-routedata - To capture the additional information, not sure if this is possible but can check.
  2. aspnet-machinename - To Capture the machine name where the WebSite is hosted. Not Sure if there is another NLog Layout Renderer can accommodate the same. This is available in the base NLog Refer https://github.com/NLog/NLog/wiki/Machinename-Layout-Renderer
  3. aspnet-host-version - No sure if this is required, but just a thought. Needs more discussion.

History
04/19/2016
Changed aspnet-request-referrerurl to aspnet-request-referrer
Changed aspnet-request-requesturl to aspnet-request-url
Added more renderer for User Agent, IP Addressm IsHttps (item 11, 12, 13) above

06/04/2016
Moved this item from above.
3. aspnet-request-servervariable - To Capture any servervariable. Allows comma separated to get mulitple server variables. Can also allow json formatting. This is specific to Pre MVC CORE 1.0 (a.k.a ASP.NET 5)
13. aspnet-ipaddress - To Capture the ip address of the machine from where the request is made.
11. aspnet-ishttps - true/false value which says if the site is setup as https or not.

Add TraceIdentifier for ASP.Net Core

I have a middleware that add a HTTP response header with the value of HttpContext.TraceIdentifier. It would be really useful if I could log the corresponding TraceIdentifier to find out what went wrong in case of errors. Thank you.

Logging outside of request scope fails with exception

In the AspNetRequestValueLayoutRenderer.cs the request is fetched from the http context. Next, it's checked for null before values are appended to the log:

 protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent)
 {
     var httpRequest = HttpContextAccessor.HttpContext.Request;
     if (httpRequest == null)
     {
          return;
     }
   ...
 }

The problem is that we never get an null return value. Instead an exception is thrown from the .net framework:

        /// <devdoc>
        ///    <para>
        ///       Retrieves a reference to the target <see cref='System.Web.HttpRequest'/>
        ///       object for the current request.
        ///    </para>
        /// </devdoc>
        public HttpRequest Request {
            get {
                 if (HideRequestResponse)
                    throw new HttpException(SR.GetString(SR.Request_not_available));
                return _request;
            }
        }

This is a problem when we use the logger outside a request context, like inside of Application_Start(), giving us the 'yellow screen of death':

image

Layout renderers missing when referencing from .NETStandard 1.6

Hi,

I've just created a new WebAPI project in Visual Studio 2015, Community Edition. I've then downloaded via NuGet the 4.2.4 version of NLog.Web.AspNetCore. I see only a part of the layout renderers that are supposed to be there. For example, AspNetRequestUrlRenderer is missing. Have I missed something?
untitled

renames

classes:
AspNetQueryStringLayoutRenderer -> AspNetRequestQueryStringLayoutRenderer
AspNetCoreHostLayoutRenderer -> AspNetHostLayoutRenderer

names:
aspnet-useragent - > aspnet-request-useragent

DNX / ASP 5 - ${aspnet-request:serverVariable result in System.NotSupportedException

The documentation https://github.com/NLog/NLog/wiki/AspNetRequest-layout-renderer

implies that serverVariable works for asp.net5 /coreclr but the source code

https://github.com/NLog/NLog.Web/blob/master/NLog.Web.ASPNET5/LayoutRenderers/AspNetRequestValueLayoutRenderer.cs

explicitly seems to throw an exception :

else if (this.ServerVariable != null)
{
#if !DNX
builder.Append(httpRequest.ServerVariables[this.ServerVariable]);
#else
throw new NotSupportedException();
#endi

For example in my nlog.config, the first 3 parameters work fine but the last two throw internal nlog exceptions (Warn Exception in layout renderer. Exception: System.NotSupportedException: Specified method is not supported.)

  • parameter name="@requestmethod" layout="${aspnet-item:variable=RequestMethod}"/
  • parameter name="@responseParamThree" layout="${aspnet-request:header=X-Forwarded-For}"/
  • parameter name="@responseParamFour" layout="${aspnet-request:serverVariable=REMOTE_ADDR}"/
  • parameter name="@responseParamFive" layout="${aspnet-request:serverVariable=ALL_RAW}"/

From project.json

"dependencies": {
.....
"NLog": "4.4.0-beta1",
"NLog.Config": "4.3.0-beta1",
"NLog.Extensions.Logging": "1.0.0-rc1-final-2016-03-11",
"NLog.Schema": "4.3.0-beta1",
"NLog.Web.ASPNET5": "4.2.1",
.......

readme - usage for non-core sites?

Hi, thanks for the library.

I'm a bit flummoxed how to use it with a normal asp.net mvc application rather than this new fangled core thing.

The instructions all seem to relate to core, could you assist?

aspnet-request-querystring - QueryStringKeys is required.

Environment:

.net 4.6.2

This line works:
${aspnet-request-querystring:QueryStringKeys=someKey;OutputFormat=Flat}

This line does not work:
${aspnet-request-querystring:OutputFormat=Flat}

The documentation uses "CAN" instead of "MUST" this implies that the "QueryStringKeys is optional. Ideally this value would not be manadatory, but if it is mandatory then the documentation should reflect that it is.

Link to documentation : https://github.com/NLog/NLog/wiki/AspNetRequest-QueryString-Layout-Renderer

Error while trying to use aspnet- elements in layout

I updated to the NLog 4 and also updated to the NLog.Web 2 but I still get the following error:
{"Error when setting property 'Layout' on File Target[f]"} when calling the GetCurrentClassLogger().

My layout is pretty simple:

        <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
            layout="${longdate} ${uppercase:${level}} :: ${aspnet-user-identity} :: ${stacktrace} ${newline} ${message}" />

Already tested if I remove the ${aspnet-user-identity} it works.

My packages.config file:

   <package id="NLog" version="4.0.0" targetFramework="net451" />
   <package id="NLog.Config" version="4.0.0" targetFramework="net451" />
  <package id="NLog.Extended" version="4.0.0" targetFramework="net451" />
  <package id="NLog.ManualFlush" version="2.0.0.0" targetFramework="net451" />
  <package id="NLog.Schema" version="4.0.0" targetFramework="net451" />
  <package id="NLog.Web" version="2.0.0.0" targetFramework="net451" />

Null processing for ${aspnet-session:Variable=User.Name:EvaluateAsNestedProperties=true}

Session["user"] = new UserInfo { Name= "johnDoe", Id = 100};
layout="${aspnet-session:Variable=User.Name:EvaluateAsNestedProperties=true}"

I think there need to null check for Session["user"].
If object is not null, then try to read property of that object, else return.

From NLog.Web.Internal => PropertyReader => method GetPropertyInfo:
return value.GetType().GetProperty(propertyName); // "value" can be null here.
Thanks.

Add MVC layout renderers

Proposal:

add the following layout renderers.

  • ${mvc-action}
  • ${mvc-controller}
  • ${mvc-route}

Needs System.Web.Mvc. But that's I think now problem, as the layout renders just won't work if MVC is not included.

It's unclear if we need <assemblyBindings> for the different MVC version (3,4,5 etc)

and what about API projects? (which has also actions and controllers)

AspNetCore: AspNetRequestUrlRenderer returns nothing/empty string

I've updated NLog.Web.AspNetCore to 4.3.0, after that updated NLog to 5.0.0-beta4 and NLog.Extensions.Logging to 1.0.0-rtm-beta1, as required by the NLog.Web.AspNetCore package.
Changed the Nlog.config to pass ${aspnet-request-url:IncludePort=true:IncludeQueryString=true} instead of 'n/a' as value for the SP parameter (I'm logging to MS SQL database via Stored Procedure).
Did a test request, but the column stays empty, where as it was first filled with n/a, so I pass it to the correct parameter.
Before the update I was using NLog.Web.AspNetCore 4.2.4 which would log an internal exception if I use aspnet-request-url, as expected, so the update did add support for the renderer, but now it doesn't render any info. Am I missing something?

I'm using the default ILogger interface MS provides by the AspNetCore WebApi project:

public SomeController(IActionContextAccessor actionContextAccessor, ILogger<SomeController> logger)
    : base(actionContextAccessor)`
{
    this.logger = logger;
}

public IActionResult GetSome(int someId)
{
    this.logger.LogInformation($"Trying to get some. SomeId: {someId}");
}

Add ${aspnet-content-type}

I want to log http requests content type and remote address.

{aspnet-remote-address} RemoteAddress => context.Request.UserHostAddress (Update ${aspnet-request-host} - @304NotModified)
{aspnet-content-type} ContentType => context.Request.ContentType

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤ī¸ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.