diff --git a/src/NLog/LayoutRenderers/EnvironmentUserLayoutRenderer.cs b/src/NLog/LayoutRenderers/EnvironmentUserLayoutRenderer.cs new file mode 100644 index 0000000000..acd50ed139 --- /dev/null +++ b/src/NLog/LayoutRenderers/EnvironmentUserLayoutRenderer.cs @@ -0,0 +1,136 @@ +// +// Copyright (c) 2004-2019 Jaroslaw Kowalski , Kim Christensen, Julian Verdurmen +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of Jaroslaw Kowalski nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !NETSTANDARD1_0 && !SILVERLIGHT + +namespace NLog.LayoutRenderers +{ + using System; + using System.ComponentModel; + using System.Text; + using NLog.Common; + using NLog.Config; + using NLog.Internal; + + /// + /// Thread identity information (username). + /// + [LayoutRenderer("environment-user")] + [ThreadSafe] + public class EnvironmentUserLayoutRenderer : LayoutRenderer, IStringValueRenderer + { + /// + /// Initializes a new instance of the class. + /// + public EnvironmentUserLayoutRenderer() + { + UserName = true; + Domain = false; + } + + /// + /// Gets or sets a value indicating whether username should be included. + /// + /// + [DefaultValue(true)] + public bool UserName { get; set; } + + /// + /// Gets or sets a value indicating whether domain name should be included. + /// + /// + [DefaultValue(false)] + public bool Domain { get; set; } + + /// + /// Gets or sets the default value to be used when the User is not set. + /// + /// + [DefaultValue("UserUnknown")] + public string DefaultUser { get; set; } = "UserUnknown"; + + /// + /// Gets or sets the default value to be used when the Domain is not set. + /// + /// + [DefaultValue("DomainUnknown")] + public string DefaultDomain { get; set; } = "DomainUnknown"; + + /// + protected override void Append(StringBuilder builder, LogEventInfo logEvent) + { + builder.Append(GetStringValue()); + } + + /// + string IStringValueRenderer.GetFormattedString(LogEventInfo logEvent) => GetStringValue(); + + private string GetStringValue() + { + if (UserName) + { + return Domain ? string.Concat(GetDomainName(), "\\", GetUserName()) : GetUserName(); + } + else + { + return Domain ? GetDomainName() : string.Empty; + } + } + + string GetUserName() + { + return GetValueSafe(() => Environment.UserName, DefaultUser); + } + + string GetDomainName() + { + return GetValueSafe(() => Environment.UserDomainName, DefaultDomain); + } + + private string GetValueSafe(Func getValue, string defaultValue) + { + try + { + var value = getValue(); + return string.IsNullOrEmpty(value) ? (defaultValue ?? string.Empty) : value; + } + catch (Exception ex) + { + InternalLogger.Warn(ex, "Failed to lookup Environment-User. Fallback value={0}", defaultValue); + return defaultValue ?? string.Empty; + } + } + } +} + +#endif \ No newline at end of file diff --git a/tests/NLog.UnitTests/LayoutRenderers/EnvironmentUserLayoutRendererTests.cs b/tests/NLog.UnitTests/LayoutRenderers/EnvironmentUserLayoutRendererTests.cs new file mode 100644 index 0000000000..d6a8a5565e --- /dev/null +++ b/tests/NLog.UnitTests/LayoutRenderers/EnvironmentUserLayoutRendererTests.cs @@ -0,0 +1,65 @@ +// +// Copyright (c) 2004-2019 Jaroslaw Kowalski , Kim Christensen, Julian Verdurmen +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of Jaroslaw Kowalski nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +// + +namespace NLog.UnitTests.LayoutRenderers +{ + using System; + using NLog.Layouts; + using Xunit; + + public class EnvironmentUserLayoutRendererTests + { + [Fact] + public void EnvironmentUserTest() + { + var userName = Environment.GetEnvironmentVariable("USERNAME"); + if (string.IsNullOrEmpty(userName)) + userName = Environment.GetEnvironmentVariable("USER") ?? string.Empty; + + Layout layout = "${environment-user}"; + var result = layout.Render(LogEventInfo.CreateNullEvent()); + if (!string.IsNullOrEmpty(userName)) + { + Assert.Equal(userName, result); + + var userDomainName = Environment.GetEnvironmentVariable("USERDOMAIN") ?? string.Empty; + if (!string.IsNullOrEmpty(userDomainName)) + { + layout = "${environment-user:domain=true}"; + result = layout.Render(LogEventInfo.CreateNullEvent()); + Assert.Equal(userDomainName + "\\" + userName, result); + } + } + } + } +} diff --git a/tests/NLog.UnitTests/LayoutRenderers/IdentityTests.cs b/tests/NLog.UnitTests/LayoutRenderers/IdentityTests.cs index 66507406ea..b1e62d2790 100644 --- a/tests/NLog.UnitTests/LayoutRenderers/IdentityTests.cs +++ b/tests/NLog.UnitTests/LayoutRenderers/IdentityTests.cs @@ -31,18 +31,15 @@ // THE POSSIBILITY OF SUCH DAMAGE. // -using System; -using NLog.Common; -using NLog.Config; -using NLog.Targets; -using NLog.Targets.Wrappers; -using NLog.UnitTests.Common; -using NLog.UnitTests.Targets.Wrappers; - namespace NLog.UnitTests.LayoutRenderers { + using System; using System.Security.Principal; using System.Threading; + using NLog.Common; + using NLog.Config; + using NLog.Targets.Wrappers; + using NLog.UnitTests.Common; using Xunit; public class IdentityTests : NLogTestBase @@ -56,7 +53,10 @@ public void WindowsIdentityTest() { #if NETSTANDARD if (IsTravis()) + { + Console.WriteLine("[SKIP] IdentityTests.WindowsIdentityTest NetStandard on Travis not supporting WindowsIdentity"); return; // NetCore on Travis not supporting WindowsIdentity + } #endif var userDomainName = Environment.GetEnvironmentVariable("USERDOMAIN") ?? string.Empty;