From e40731f722fa66096e5470c21971e25570b88e12 Mon Sep 17 00:00:00 2001 From: Rolf Kristensen Date: Sun, 28 Oct 2018 09:29:33 +0100 Subject: [PATCH] Added ThreadSafe-attribute for LayoutRenderer to optimize async Layout.Precalculate --- .../AspNetRequestValueLayoutRendererTests.cs | 44 +++++-- .../AspNetAppBasePathLayoutRenderer.cs | 3 + .../AspNetApplicationValueLayoutRenderer.cs | 1 + .../AspNetEnvironmentLayoutRenderer.cs | 3 + .../AspNetItemValueLayoutRenderer.cs | 1 + .../AspNetMvcActionRenderer.cs | 4 +- .../AspNetMvcControllerRenderer.cs | 5 +- .../AspNetRequestContentTypeLayoutRenderer.cs | 2 + .../AspNetRequestCookieLayoutRenderer.cs | 63 ++++------ .../AspNetRequestFormLayoutRenderer.cs | 51 ++++---- .../AspNetRequestHostLayoutRenderer.cs | 16 +-- .../AspNetRequestHttpMethodRenderer.cs | 3 +- .../AspNetRequestIpLayoutRenderer.cs | 5 +- .../AspNetRequestQueryStringLayoutRenderer.cs | 32 ++--- .../AspNetRequestReferrerRenderer.cs | 2 + .../AspNetRequestUrlRenderer.cs | 70 +++++------ .../AspNetRequestValueLayoutRenderer.cs | 112 ++++++++---------- .../LayoutRenderers/AspNetRequestuseragent.cs | 2 + .../AspNetSessionIdLayoutRenderer.cs | 4 +- .../AspNetSessionValueLayoutRenderer.cs | 9 +- .../AspNetTraceIdentifierLayoutRenderer.cs | 2 + .../AspNetUserAuthTypeLayoutRenderer.cs | 3 +- .../AspNetUserIdentityLayoutRenderer.cs | 3 +- ...AspNetUserIsAuthenticatedLayoutRenderer.cs | 2 + .../AspNetWebRootPathLayoutRenderer.cs | 3 + .../AssemblyVersionLayoutRenderer.cs | 3 + .../IISInstanceNameLayoutRenderer.cs | 3 + 27 files changed, 235 insertions(+), 216 deletions(-) diff --git a/NLog.Web.AspNetCore.Tests/LayoutRenderers/AspNetRequestValueLayoutRendererTests.cs b/NLog.Web.AspNetCore.Tests/LayoutRenderers/AspNetRequestValueLayoutRendererTests.cs index 75f84782..1d4df699 100644 --- a/NLog.Web.AspNetCore.Tests/LayoutRenderers/AspNetRequestValueLayoutRendererTests.cs +++ b/NLog.Web.AspNetCore.Tests/LayoutRenderers/AspNetRequestValueLayoutRendererTests.cs @@ -1,25 +1,24 @@ -#if !ASP_NET_CORE -//TODO test .NET Core -using System.Collections.Specialized; -using System.IO; +using System.IO; #if !ASP_NET_CORE +using System.Collections.Specialized; using System.Web; using System.Web.Routing; using System.Web.SessionState; #else +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; using HttpContextBase = Microsoft.AspNetCore.Http.HttpContext; #endif using NLog.Common; -using NLog.Config; using NLog.Web.LayoutRenderers; using NSubstitute; using NSubstitute.ExceptionExtensions; using Xunit; +using System.Collections.Generic; namespace NLog.Web.Tests.LayoutRenderers { - public class AspNetRequestValueLayoutRendererTests : TestBase + public class AspNetRequestValueLayoutRendererTests : TestInvolvingAspNetHttpContext { [Fact] public void NullHttpContextRendersEmptyString() @@ -31,6 +30,7 @@ public void NullHttpContextRendersEmptyString() Assert.Empty(result); } +#if !ASP_NET_CORE [Fact] public void NullRequestRendersEmptyStringWithoutLoggingError() { @@ -50,6 +50,7 @@ public void NullRequestRendersEmptyStringWithoutLoggingError() Assert.Empty(result); Assert.True(string.IsNullOrEmpty(internalLog.ToString())); } +#endif public class ItemTests { @@ -86,7 +87,11 @@ public void KeyFoundRendersValue() { var expectedResult = "value"; var httpContext = Substitute.For(); +#if !ASP_NET_CORE httpContext.Request["key"].Returns(expectedResult); +#else + httpContext.Request.HttpContext.Items.Returns(new Dictionary() { { "key", expectedResult } }); +#endif var renderer = new AspNetRequestValueLayoutRenderer(); renderer.HttpContextAccessor = new FakeHttpContextAccessor(httpContext); @@ -133,7 +138,12 @@ public void KeyFoundRendersValue() { var expectedResult = "value"; var httpContext = Substitute.For(); +#if !ASP_NET_CORE httpContext.Request.QueryString.Returns(new NameValueCollection { {"key", expectedResult} }); +#else + var queryCollection = new Microsoft.AspNetCore.Http.Internal.QueryCollection(new Dictionary() { { "key", expectedResult } }); + httpContext.Request.Query.Returns(queryCollection); +#endif var renderer = new AspNetRequestValueLayoutRenderer(); renderer.HttpContextAccessor = new FakeHttpContextAccessor(httpContext); @@ -180,7 +190,12 @@ public void KeyFoundRendersValue() { var expectedResult = "value"; var httpContext = Substitute.For(); +#if !ASP_NET_CORE httpContext.Request.Headers.Returns(new NameValueCollection { { "key", expectedResult } }); +#else + var headerDictionary = new HeaderDictionary(new Dictionary() { { "key", expectedResult } }); + httpContext.Request.Headers.Returns(headerDictionary); +#endif var renderer = new AspNetRequestValueLayoutRenderer(); renderer.HttpContextAccessor = new FakeHttpContextAccessor(httpContext); @@ -227,7 +242,13 @@ public void KeyFoundRendersValue() { var expectedResult = "value"; var httpContext = Substitute.For(); +#if !ASP_NET_CORE httpContext.Request.Form.Returns(new NameValueCollection { { "key", expectedResult } }); +#else + httpContext.Request.HasFormContentType.Returns(true); + var formCollection = new FormCollection(new Dictionary{ { "key", expectedResult } }); + httpContext.Request.Form.Returns(formCollection); +#endif var renderer = new AspNetRequestValueLayoutRenderer(); renderer.HttpContextAccessor = new FakeHttpContextAccessor(httpContext); @@ -239,6 +260,7 @@ public void KeyFoundRendersValue() } } +#if !ASP_NET_CORE public class ServerVariablesTests { [Fact] @@ -285,7 +307,7 @@ public void KeyFoundRendersValue() Assert.Equal(expectedResult, result); } } - +#endif public class CookieTests { [Fact] @@ -321,7 +343,12 @@ public void KeyFoundRendersValue() { var expectedResult = "value"; var httpContext = Substitute.For(); +#if !ASP_NET_CORE httpContext.Request.Cookies.Returns(new HttpCookieCollection {new HttpCookie("key", expectedResult) }); +#else + var cookieCollection = new Microsoft.AspNetCore.Http.Internal.RequestCookieCollection(new Dictionary{ { "key", expectedResult } }); + httpContext.Request.Cookies.Returns(cookieCollection); +#endif var renderer = new AspNetRequestValueLayoutRenderer(); renderer.HttpContextAccessor = new FakeHttpContextAccessor(httpContext); @@ -333,5 +360,4 @@ public void KeyFoundRendersValue() } } } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetAppBasePathLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetAppBasePathLayoutRenderer.cs index badf4ddd..1efa5b86 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetAppBasePathLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetAppBasePathLayoutRenderer.cs @@ -7,6 +7,7 @@ #else using System.Web.Hosting; #endif +using NLog.Config; using NLog.LayoutRenderers; namespace NLog.Web.LayoutRenderers @@ -21,6 +22,8 @@ namespace NLog.Web.LayoutRenderers /// #endif [LayoutRenderer("aspnet-appbasepath")] + [ThreadAgnostic] + [ThreadSafe] public class AspNetAppBasePathLayoutRenderer : LayoutRenderer { #if ASP_NET_CORE diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetApplicationValueLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetApplicationValueLayoutRenderer.cs index 821d9280..cf41cfec 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetApplicationValueLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetApplicationValueLayoutRenderer.cs @@ -35,6 +35,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-application")] + [ThreadSafe] public class AspNetApplicationValueLayoutRenderer : AspNetLayoutRendererBase { /// diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetEnvironmentLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetEnvironmentLayoutRenderer.cs index 79b8825b..3bffac4a 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetEnvironmentLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetEnvironmentLayoutRenderer.cs @@ -3,6 +3,7 @@ using System.Text; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; +using NLog.Config; using NLog.LayoutRenderers; using NLog.Web.DependencyInjection; @@ -13,6 +14,8 @@ namespace NLog.Web.LayoutRenderers /// Rendering development environment. /// [LayoutRenderer("aspnet-environment")] + [ThreadAgnostic] + [ThreadSafe] public class AspNetEnvironmentLayoutRenderer : LayoutRenderer { private static IHostingEnvironment _hostingEnvironment; diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetItemValueLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetItemValueLayoutRenderer.cs index 2af718e9..d5920559 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetItemValueLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetItemValueLayoutRenderer.cs @@ -40,6 +40,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-item")] + [ThreadSafe] public class AspNetItemValueLayoutRenderer : AspNetLayoutRendererBase { /// diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetMvcActionRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetMvcActionRenderer.cs index 5cf35fbf..a70e6208 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetMvcActionRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetMvcActionRenderer.cs @@ -1,4 +1,3 @@ -using NLog.LayoutRenderers; using System.Text; #if !ASP_NET_CORE using System.Web.Routing; @@ -8,6 +7,8 @@ using Microsoft.AspNetCore.Http; using HttpContextBase = Microsoft.AspNetCore.Http.HttpContext; #endif +using NLog.Config; +using NLog.LayoutRenderers; namespace NLog.Web.LayoutRenderers { @@ -23,6 +24,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-mvc-action")] + [ThreadSafe] public class AspNetMvcActionRenderer : AspNetMvcLayoutRendererBase { /// diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetMvcControllerRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetMvcControllerRenderer.cs index b491b8e2..9bb54eb0 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetMvcControllerRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetMvcControllerRenderer.cs @@ -1,4 +1,3 @@ -using NLog.LayoutRenderers; using System.Text; #if !ASP_NET_CORE using System.Web.Routing; @@ -8,7 +7,8 @@ using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Http; #endif - +using NLog.Config; +using NLog.LayoutRenderers; namespace NLog.Web.LayoutRenderers { @@ -24,6 +24,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-mvc-controller")] + [ThreadSafe] public class AspNetMvcControllerRenderer : AspNetMvcLayoutRendererBase { /// diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestContentTypeLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestContentTypeLayoutRenderer.cs index 126219fa..5a437f42 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestContentTypeLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestContentTypeLayoutRenderer.cs @@ -1,5 +1,6 @@ #if ASP_NET_CORE using System.Text; +using NLog.Config; using NLog.LayoutRenderers; using NLog.Web.Internal; @@ -14,6 +15,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-request-contenttype")] + [ThreadSafe] public class AspNetRequestContentTypeLayoutRenderer : AspNetLayoutRendererBase { /// diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestCookieLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestCookieLayoutRenderer.cs index 6d9c8414..289c5093 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestCookieLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestCookieLayoutRenderer.cs @@ -7,9 +7,9 @@ #else using Microsoft.AspNetCore.Http; #endif +using NLog.Config; using NLog.LayoutRenderers; using NLog.Web.Enums; - using NLog.Web.Internal; namespace NLog.Web.LayoutRenderers @@ -25,6 +25,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-request-cookie")] + [ThreadSafe] public class AspNetRequestCookieLayoutRenderer : AspNetLayoutMultiValueRendererBase { /// @@ -52,62 +53,50 @@ protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) } #if !ASP_NET_CORE - private IEnumerable> GetCookies(HttpCookieCollection cookies) { - var cookieNames = CookieNames; - if (cookieNames != null) + foreach (var cookieName in CookieNames) { - foreach (var cookieName in cookieNames) + var httpCookie = cookies[cookieName]; + if (httpCookie == null) { - var httpCookie = cookies[cookieName]; - if (httpCookie == null) - { - continue; - } + continue; + } - if (OutputFormat == AspNetRequestLayoutOutputFormat.Json) + if (OutputFormat == AspNetRequestLayoutOutputFormat.Json) + { + // Split multi-valued cookie, as allowed for in the HttpCookie API for backwards compatibility with classic ASP + var isFirst = true; + foreach (var multiValueKey in httpCookie.Values.AllKeys) { - // Split multi-valued cookie, as allowed for in the HttpCookie API for backwards compatibility with classic ASP - var isFirst = true; - foreach (var multiValueKey in httpCookie.Values.AllKeys) + var cookieKey = multiValueKey; + if (isFirst) { - var cookieKey = multiValueKey; - if (isFirst) - { - cookieKey = cookieName; - isFirst = false; - } - yield return new KeyValuePair(cookieKey, httpCookie.Values[multiValueKey]); + cookieKey = cookieName; + isFirst = false; } - } - else - { - yield return new KeyValuePair(cookieName, httpCookie.Value); + yield return new KeyValuePair(cookieKey, httpCookie.Values[multiValueKey]); } } + else + { + yield return new KeyValuePair(cookieName, httpCookie.Value); + } } } - #else - private IEnumerable> GetCookies(IRequestCookieCollection cookies) { - var cookieNames = CookieNames; - if (cookieNames != null) + foreach (var cookieName in CookieNames) { - foreach (var cookieName in cookieNames) + if (!cookies.TryGetValue(cookieName, out var cookieValue)) { - if (!cookies.TryGetValue(cookieName, out var cookieValue)) - { - continue; - } - - yield return new KeyValuePair(cookieName, cookieValue); + continue; } + + yield return new KeyValuePair(cookieName, cookieValue); } } - #endif } } diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestFormLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestFormLayoutRenderer.cs index 3359429d..569b0238 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestFormLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestFormLayoutRenderer.cs @@ -1,9 +1,9 @@ -using NLog.LayoutRenderers; -using NLog.Web.Internal; -using System; +using System; using System.Collections.Generic; -using System.Linq; using System.Text; +using NLog.Config; +using NLog.LayoutRenderers; +using NLog.Web.Internal; namespace NLog.Web.LayoutRenderers { @@ -21,6 +21,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-request-form")] + [ThreadSafe] public class AspNetRequestFormLayoutRenderer : AspNetLayoutMultiValueRendererBase { /// @@ -59,40 +60,36 @@ public AspNetRequestFormLayoutRenderer() /// protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) { - if (HttpContextAccessor?.HttpContext?.TryGetRequest() == null) - { - return; - } - - var formDataToInclude = GetPairsToInclude(); - - if (formDataToInclude.Any()) + var httpRequest = HttpContextAccessor.HttpContext.TryGetRequest(); +#if !ASP_NET_CORE + var formKeys = httpRequest?.Form?.Keys; +#else + var formKeys = httpRequest?.HasFormContentType == true ? httpRequest.Form?.Keys : null; +#endif + if (formKeys?.Count > 0) { + var formDataToInclude = GetPairsToInclude(formKeys, httpRequest); SerializePairs(formDataToInclude, builder, logEvent); } } - private IEnumerable> GetPairsToInclude() - { - var httpRequest = HttpContextAccessor?.HttpContext?.TryGetRequest(); - var pairs = new List>(); - -#if ASP_NET_CORE - if (httpRequest.HasFormContentType && httpRequest.Form != null) + private IEnumerable> GetPairsToInclude( +#if !ASP_NET_CORE + System.Collections.Specialized.NameValueCollection.KeysCollection formKeys, + System.Web.HttpRequestBase httpRequest #else - if (httpRequest.Form != null) + ICollection formKeys, + Microsoft.AspNetCore.Http.HttpRequest httpRequest #endif + ) + { + foreach (string key in formKeys) { - foreach (string key in httpRequest.Form.Keys) + if ((Include.Count == 0 || Include.Contains(key)) && !Exclude.Contains(key)) { - if ((!Include.Any() || Include.Contains(key)) && !Exclude.Contains(key)) - { - pairs.Add(new KeyValuePair(key, httpRequest.Form[key])); - } + yield return new KeyValuePair(key, httpRequest.Form[key]); } } - - return pairs; } } } diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestHostLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestHostLayoutRenderer.cs index f45ed3c0..51958935 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestHostLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestHostLayoutRenderer.cs @@ -1,4 +1,5 @@ using System.Text; +using NLog.Config; using NLog.LayoutRenderers; using NLog.Web.Internal; @@ -12,10 +13,11 @@ namespace NLog.Web.LayoutRenderers /// /// /// - /// ${aspnet-host} + /// ${aspnet-request-host} /// /// [LayoutRenderer("aspnet-request-host")] + [ThreadSafe] public class AspNetRequestHostLayoutRenderer : AspNetLayoutRendererBase { /// @@ -30,17 +32,11 @@ protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) return; #if ASP_NET_CORE - var host = request.Host; + var host = request.Host.ToString(); #else - var host = request.UserHostName; + var host = request.UserHostName?.ToString(); #endif - if (host != null) - { - var hostString = host.ToString(); - - if (!string.IsNullOrEmpty(hostString)) - builder.Append(hostString); - } + builder.Append(host); } } } diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestHttpMethodRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestHttpMethodRenderer.cs index 4d9980f9..4ca1bb72 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestHttpMethodRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestHttpMethodRenderer.cs @@ -2,8 +2,8 @@ using System.Text; #if !ASP_NET_CORE using System.Web; -using System.Collections.Specialized; #endif +using NLog.Config; using NLog.LayoutRenderers; using NLog.Web.Internal; @@ -19,6 +19,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-request-method")] + [ThreadSafe] public class AspNetRequestHttpMethodRenderer : AspNetLayoutRendererBase { /// diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestIpLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestIpLayoutRenderer.cs index 3d92aa5d..a6afac9d 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestIpLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestIpLayoutRenderer.cs @@ -3,6 +3,7 @@ #if ASP_NET_CORE using Microsoft.AspNetCore.Http; #endif +using NLog.Config; using NLog.LayoutRenderers; using NLog.Web.Internal; @@ -17,6 +18,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-request-ip")] + [ThreadSafe] public class AspNetRequestIpLayoutRenderer : AspNetLayoutRendererBase { private const string ForwardedForHeader = "X-Forwarded-For"; @@ -73,10 +75,9 @@ string TryLookupForwardHeader(System.Web.HttpRequestBase httpRequest) #else string TryLookupForwardHeader(HttpRequest httpRequest) { - if (httpRequest.Headers.ContainsKey(ForwardedForHeader)) + if (httpRequest.Headers?.ContainsKey(ForwardedForHeader)==true) { var forwardedHeaders = httpRequest.Headers.GetCommaSeparatedValues(ForwardedForHeader); - if (forwardedHeaders.Length > 0) { return forwardedHeaders[0]; diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestQueryStringLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestQueryStringLayoutRenderer.cs index b5da0ee8..c3d8e786 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestQueryStringLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestQueryStringLayoutRenderer.cs @@ -8,8 +8,8 @@ #else using Microsoft.AspNetCore.Http; #endif +using NLog.Config; using NLog.LayoutRenderers; -using NLog.Web.Enums; using NLog.Web.Internal; namespace NLog.Web.LayoutRenderers @@ -25,6 +25,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-request-querystring")] + [ThreadSafe] public class AspNetQueryStringLayoutRenderer : AspNetLayoutMultiValueRendererBase { /// @@ -48,7 +49,7 @@ protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) var queryStringKeys = QueryStringKeys; #if !ASP_NET_CORE var queryStrings = httpRequest.QueryString; - if (queryStrings == null) + if (queryStrings == null || queryStrings.Count == 0) return; if (printAllQueryString) @@ -65,7 +66,7 @@ protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) } #else var queryStrings = httpRequest.Query; - if (queryStrings == null) + if (queryStrings == null || queryStrings.Count == 0) return; if (printAllQueryString) @@ -79,27 +80,26 @@ protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) } private static IEnumerable> GetPairs( -#if ASP_NET_CORE - IQueryCollection queryStrings, -#else +#if !ASP_NET_CORE NameValueCollection queryStrings, +#else + IQueryCollection queryStrings, #endif List queryStringKeys) { - if (queryStrings.Count > 0) + foreach (var key in queryStringKeys) { - foreach (var key in queryStringKeys) - { - // This platoform specific code is to prevent an unncessary .ToString call otherwise. + // This platoform specific code is to prevent an unncessary .ToString call otherwise. #if !ASP_NET_CORE - var value = queryStrings[key]; + var value = queryStrings[key]; #else - var value = queryStrings[key].ToString(); + if (!queryStrings.TryGetValue(key, out var objValue)) + continue; + var value = objValue.ToString(); #endif - if (!String.IsNullOrEmpty(value)) - { - yield return new KeyValuePair(key, value); - } + if (!String.IsNullOrEmpty(value)) + { + yield return new KeyValuePair(key, value); } } } diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestReferrerRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestReferrerRenderer.cs index cd4860ca..63640835 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestReferrerRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestReferrerRenderer.cs @@ -4,6 +4,7 @@ using System.Web; using System.Collections.Specialized; #endif +using NLog.Config; using NLog.LayoutRenderers; using NLog.Web.Internal; @@ -19,6 +20,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-request-referrer")] + [ThreadSafe] public class AspNetRequestReferrerRenderer : AspNetLayoutRendererBase { /// diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestUrlRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestUrlRenderer.cs index e21d948a..1dc61ae7 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestUrlRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestUrlRenderer.cs @@ -3,8 +3,8 @@ #if !ASP_NET_CORE using System.Collections.Specialized; using System.Web; -#else #endif +using NLog.Config; using NLog.LayoutRenderers; using NLog.Web.Internal; @@ -25,6 +25,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-request-url")] + [ThreadSafe] public class AspNetRequestUrlRenderer : AspNetLayoutRendererBase { /// @@ -42,7 +43,6 @@ public class AspNetRequestUrlRenderer : AspNetLayoutRendererBase /// public bool IncludeHost { get; set; } = true; - /// /// To specify whether to exclude / include the scheme. Default is true. /// @@ -59,71 +59,59 @@ protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) if (httpRequest == null) return; - var url = CreateUrl(httpRequest); - builder.Append(url); + RenderUrl(httpRequest, builder); } #if !ASP_NET_CORE - - private string CreateUrl(HttpRequestBase httpRequest) + private void RenderUrl(HttpRequestBase httpRequest, StringBuilder builder) { - string port = null, host = null, scheme = null; - - if (httpRequest.Url == null) - { - return null; - } + var url = httpRequest.Url; + if (url == null) + return; - if (IncludePort && httpRequest.Url.Port > 0) + if (IncludeScheme && !string.IsNullOrEmpty(url.Scheme)) { - port = ":" + httpRequest.Url.Port; + builder.Append(url.Scheme); + builder.Append("://"); } - - var pathAndQuery = IncludeQueryString ? httpRequest.Url.PathAndQuery : httpRequest.Url.AbsolutePath; - if (IncludeHost) { - host = httpRequest.Url?.Host; + builder.Append(url.Host); } - - if (IncludeScheme) + if (IncludePort && url.Port > 0) { - scheme = httpRequest.Url.Scheme + "://"; + builder.Append(':'); + builder.Append(url.Port); } - var url = $"{scheme}{host}{port}{pathAndQuery}"; - return url; + var pathAndQuery = IncludeQueryString ? url.PathAndQuery : url.AbsolutePath; + builder.Append(pathAndQuery); } - #else - private string CreateUrl(Microsoft.AspNetCore.Http.HttpRequest httpRequest) + private void RenderUrl(Microsoft.AspNetCore.Http.HttpRequest httpRequest, StringBuilder builder) { - string pathAndQuery = null, port = null, host = null, scheme = null; - - if (IncludeQueryString) + if (IncludeScheme && !string.IsNullOrWhiteSpace(httpRequest.Scheme)) { - pathAndQuery = httpRequest.QueryString.Value; + builder.Append(httpRequest.Scheme); + builder.Append("://"); } - - if (IncludePort && httpRequest.Host.Port > 0) + if (IncludeHost) { - port = ":" + httpRequest.Host.Port.ToString(); + builder.Append(httpRequest.Host.Host); } - - if (IncludeHost) + if (IncludePort && httpRequest.Host.Port > 0) { - host = httpRequest.Host.Host; + builder.Append(':'); + builder.Append(httpRequest.Host.Port.Value); } - if (IncludeScheme && !String.IsNullOrWhiteSpace(httpRequest.Scheme)) + builder.Append(httpRequest.PathBase.ToUriComponent()); + builder.Append(httpRequest.Path.ToUriComponent()); + if (IncludeQueryString) { - scheme = httpRequest.Scheme + "://"; + builder.Append(httpRequest.QueryString.Value); } - - var url = $"{scheme}{host}{port}{httpRequest.PathBase.ToUriComponent()}{httpRequest.Path.ToUriComponent()}{pathAndQuery}"; - return url; } - #endif } } diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestValueLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestValueLayoutRenderer.cs index 18f3a0c0..0a483d54 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestValueLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestValueLayoutRenderer.cs @@ -30,6 +30,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-request")] + [ThreadSafe] public class AspNetRequestValueLayoutRenderer : AspNetLayoutRendererBase { /// @@ -58,15 +59,11 @@ public class AspNetRequestValueLayoutRenderer : AspNetLayoutRendererBase public string Cookie { get; set; } #if !ASP_NET_CORE - - //missing in .NET Core (RC2) - /// /// Gets or sets the ServerVariables item to be rendered. /// /// public string ServerVariable { get; set; } - #endif /// @@ -86,114 +83,103 @@ protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) if (httpRequest == null) return; + string value = string.Empty; if (QueryString != null) { - AppendQueryString(builder, httpRequest); + value = LookupQueryString(QueryString, httpRequest); } - else if (Form != null && httpRequest.Form != null) + else if (Form != null) { - AppendForm(builder, httpRequest); + value = LookupFormValue(Form, httpRequest); } - else if (Cookie != null && httpRequest.Cookies != null) + else if (Cookie != null) { - AppendCookie(builder, httpRequest); + value = LookupCookieValue(Cookie, httpRequest); } #if !ASP_NET_CORE - else if (ServerVariable != null && httpRequest.ServerVariables != null) + else if (ServerVariable != null) { - builder.Append(httpRequest.ServerVariables[ServerVariable]); + value = httpRequest.ServerVariables?.Count > 0 ? + httpRequest.ServerVariables[ServerVariable] : null; } #endif - else if (Header != null && httpRequest.Headers != null) + else if (Header != null) { - AppendHeader(builder, httpRequest); + value = LookupHeaderValue(Header, httpRequest); } else if (Item != null) { - AppendItem(builder, httpRequest); + value = LookupItemValue(Item, httpRequest); } + builder.Append(value); } #if !ASP_NET_CORE - - private void AppendQueryString(StringBuilder builder, HttpRequestBase httpRequest) + private static string LookupQueryString(string key, HttpRequestBase httpRequest) { - var queryString = httpRequest.QueryString; - if (queryString == null) - return; - - var query = queryString[QueryString]; - if (query != null) - builder.Append(query); + var collection = httpRequest.QueryString; + return collection?.Count > 0 ? collection[key] : null; } - private void AppendForm(StringBuilder builder, HttpRequestBase httpRequest) + private static string LookupFormValue(string key, HttpRequestBase httpRequest) { - var formValue = httpRequest.Form[Form]; - if (formValue != null) - builder.Append(formValue); + var collection = httpRequest.Form; + return collection?.Count > 0 ? collection[key] : null; } - private void AppendCookie(StringBuilder builder, HttpRequestBase httpRequest) + private static string LookupCookieValue(string key, HttpRequestBase httpRequest) { - var cookie = httpRequest.Cookies[Cookie]; - if (cookie != null) - builder.Append(cookie.Value); + var cookieCollection = httpRequest.Cookies; + return cookieCollection?.Count > 0 ? cookieCollection[key]?.Value : null; } - private void AppendHeader(StringBuilder builder, HttpRequestBase httpRequest) + private static string LookupHeaderValue(string key, HttpRequestBase httpRequest) { - var header = httpRequest.Headers[Header]; - if (header != null) - builder.Append(header); + var collection = httpRequest.Headers; + return collection?.Count > 0 ? collection[key] : null; } - private void AppendItem(StringBuilder builder, HttpRequestBase httpRequest) + private static string LookupItemValue(string key, HttpRequestBase httpRequest) { - builder.Append(httpRequest[Item]); + return httpRequest[key]; } #else - - private void AppendQueryString(StringBuilder builder, HttpRequest httpRequest) + private static string LookupQueryString(string key, HttpRequest httpRequest) { - if (httpRequest.Query?.TryGetValue(QueryString, out var queryValue) ?? false) - { - builder.Append(queryValue.ToString()); - } + if (httpRequest.Query?.TryGetValue(key, out var queryValue) ?? false) + return queryValue.ToString(); + return null; } - private void AppendForm(StringBuilder builder, HttpRequest httpRequest) + private static string LookupFormValue(string key, HttpRequest httpRequest) { - if (httpRequest.Form.TryGetValue(Form, out var formValue)) - { - builder.Append(formValue.ToString()); - } + if (httpRequest.HasFormContentType && (httpRequest.Form?.TryGetValue(key, out var queryValue) ?? false)) + return queryValue.ToString(); + return null; } - private void AppendCookie(StringBuilder builder, HttpRequest httpRequest) + private static string LookupCookieValue(string key, HttpRequest httpRequest) { - if (httpRequest.Cookies.TryGetValue(Cookie, out var cookieValue)) - { - builder.Append(cookieValue); - } + string cookieValue = null; + if (httpRequest.Cookies?.TryGetValue(key, out cookieValue) ?? false) + return cookieValue; + return null; } - private void AppendHeader(StringBuilder builder, HttpRequest httpRequest) + private static string LookupHeaderValue(string key, HttpRequest httpRequest) { - if (httpRequest.Headers.TryGetValue(Header, out var headerValue)) - { - builder.Append(headerValue.ToString()); - } + if (httpRequest.Headers?.TryGetValue(key, out var headerValue) ?? false) + return headerValue.ToString(); + return null; } - private void AppendItem(StringBuilder builder, HttpRequest httpRequest) + private static string LookupItemValue(string key, HttpRequest httpRequest) { object itemValue = null; - if (httpRequest.HttpContext.Items?.TryGetValue(Item, out itemValue) ?? false) - { - builder.Append(itemValue); - } + if (httpRequest.HttpContext.Items?.TryGetValue(key, out itemValue) ?? false) + return itemValue?.ToString(); + return null; } #endif } diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestuseragent.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestuseragent.cs index 105da9d5..ddbcbb51 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestuseragent.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestuseragent.cs @@ -4,6 +4,7 @@ using System.Collections.Specialized; using System.Web; #endif +using NLog.Config; using NLog.LayoutRenderers; using NLog.Web.Internal; @@ -19,6 +20,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-request-useragent")] + [ThreadSafe] public class AspNetRequestUserAgent : AspNetLayoutRendererBase { /// diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetSessionIdLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetSessionIdLayoutRenderer.cs index 237f4e30..e67b9c69 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetSessionIdLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetSessionIdLayoutRenderer.cs @@ -1,9 +1,8 @@ using System.Text; #if !ASP_NET_CORE using System.Web; -#else - #endif +using NLog.Config; using NLog.LayoutRenderers; namespace NLog.Web.LayoutRenderers @@ -12,6 +11,7 @@ namespace NLog.Web.LayoutRenderers /// ASP.NET Session ID. /// [LayoutRenderer("aspnet-sessionid")] + [ThreadSafe] public class AspNetSessionIdLayoutRenderer : AspNetLayoutRendererBase { /// diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetSessionValueLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetSessionValueLayoutRenderer.cs index 305bae50..9fa61cee 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetSessionValueLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetSessionValueLayoutRenderer.cs @@ -42,6 +42,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-session")] + [ThreadSafe] public class AspNetSessionValueLayoutRenderer : AspNetLayoutRendererBase { /// @@ -111,9 +112,11 @@ protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) context.Items.Remove(NLogRetrievingSessionValue); } #endif - - var formatProvider = GetFormatProvider(logEvent, Culture); - builder.Append(Convert.ToString(value, formatProvider)); + if (value != null) + { + var formatProvider = GetFormatProvider(logEvent, Culture); + builder.Append(Convert.ToString(value, formatProvider)); + } } #if ASP_NET_CORE diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetTraceIdentifierLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetTraceIdentifierLayoutRenderer.cs index d31ddcfc..0f66ce38 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetTraceIdentifierLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetTraceIdentifierLayoutRenderer.cs @@ -1,5 +1,6 @@ using System; using System.Text; +using NLog.Config; using NLog.LayoutRenderers; namespace NLog.Web.LayoutRenderers @@ -9,6 +10,7 @@ namespace NLog.Web.LayoutRenderers /// /// .NET Core Only [LayoutRenderer("aspnet-traceidentifier")] + [ThreadSafe] public class AspNetTraceIdentifierLayoutRenderer : AspNetLayoutRendererBase { /// diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetUserAuthTypeLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetUserAuthTypeLayoutRenderer.cs index 51fa861c..fea43886 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetUserAuthTypeLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetUserAuthTypeLayoutRenderer.cs @@ -2,8 +2,8 @@ using System.Text; #if !ASP_NET_CORE using System.Web; -#else #endif +using NLog.Config; using NLog.LayoutRenderers; namespace NLog.Web.LayoutRenderers @@ -12,6 +12,7 @@ namespace NLog.Web.LayoutRenderers /// ASP.NET User variable. /// [LayoutRenderer("aspnet-user-authtype")] + [ThreadSafe] public class AspNetUserAuthTypeLayoutRenderer : AspNetLayoutRendererBase { /// diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetUserIdentityLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetUserIdentityLayoutRenderer.cs index 963cddff..61711fbf 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetUserIdentityLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetUserIdentityLayoutRenderer.cs @@ -2,8 +2,8 @@ using System.Text; #if !ASP_NET_CORE using System.Web; -#else #endif +using NLog.Config; using NLog.LayoutRenderers; namespace NLog.Web.LayoutRenderers @@ -12,6 +12,7 @@ namespace NLog.Web.LayoutRenderers /// ASP.NET User variable. /// [LayoutRenderer("aspnet-user-identity")] + [ThreadSafe] public class AspNetUserIdentityLayoutRenderer : AspNetLayoutRendererBase { /// diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetUserIsAuthenticatedLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetUserIsAuthenticatedLayoutRenderer.cs index dd54dcad..d77c065f 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetUserIsAuthenticatedLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetUserIsAuthenticatedLayoutRenderer.cs @@ -1,5 +1,6 @@ using System; using System.Text; +using NLog.Config; using NLog.LayoutRenderers; using NLog.Web.LayoutRenderers; @@ -11,6 +12,7 @@ namespace NLog.Web.AspNetCore.LayoutRenderers /// ${aspnet-user-isAuthenticated} /// [LayoutRenderer("aspnet-user-isAuthenticated")] + [ThreadSafe] public class AspNetUserIsAuthenticatedLayoutRenderer : AspNetLayoutRendererBase { /// diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetWebRootPathLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetWebRootPathLayoutRenderer.cs index 431e1db0..eec5d6b1 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetWebRootPathLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetWebRootPathLayoutRenderer.cs @@ -7,6 +7,7 @@ #else using System.Web.Hosting; #endif +using NLog.Config; using NLog.LayoutRenderers; namespace NLog.Web.LayoutRenderers @@ -21,6 +22,8 @@ namespace NLog.Web.LayoutRenderers /// #endif [LayoutRenderer("aspnet-webrootpath")] + [ThreadAgnostic] + [ThreadSafe] public class AspNetWebRootPathLayoutRenderer : LayoutRenderer { #if ASP_NET_CORE diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AssemblyVersionLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AssemblyVersionLayoutRenderer.cs index 09378916..f8b1c542 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AssemblyVersionLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AssemblyVersionLayoutRenderer.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using NLog.Common; +using NLog.Config; using NLog.LayoutRenderers; namespace NLog.Web.LayoutRenderers @@ -11,6 +12,8 @@ namespace NLog.Web.LayoutRenderers /// Extend NLog.LayoutRenderers.AssemblyVersionLayoutRenderer with ASP.NET Full and Core support /// [LayoutRenderer("assembly-version")] + [ThreadAgnostic] + [ThreadSafe] public class AssemblyVersionLayoutRenderer : NLog.LayoutRenderers.AssemblyVersionLayoutRenderer { /// diff --git a/NLog.Web.AspNetCore/LayoutRenderers/IISInstanceNameLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/IISInstanceNameLayoutRenderer.cs index 205509c0..f2fa80db 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/IISInstanceNameLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/IISInstanceNameLayoutRenderer.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; #endif +using NLog.Config; using NLog.LayoutRenderers; namespace NLog.Web.LayoutRenderers @@ -23,6 +24,8 @@ namespace NLog.Web.LayoutRenderers #endif [LayoutRenderer("iis-site-name")] // ReSharper disable once InconsistentNaming + [ThreadAgnostic] + [ThreadSafe] public class IISInstanceNameLayoutRenderer : LayoutRenderer { #if ASP_NET_CORE