diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs index 22a85663c7..ddcf16e11a 100644 --- a/src/Avalonia.Base/AvaloniaObject.cs +++ b/src/Avalonia.Base/AvaloniaObject.cs @@ -333,12 +333,11 @@ namespace Avalonia throw new ArgumentException($"The property {property.Name} is readonly."); } - if (Logger.IsEnabled(LogEventLevel.Verbose)) + if (Logger.TryGetLogger(LogEventLevel.Verbose, out var logger)) { var description = GetDescription(source); - Logger.Log( - LogEventLevel.Verbose, + logger.Log( LogArea.Property, this, "Bound {Property} to {Binding} with priority LocalValue", @@ -355,12 +354,11 @@ namespace Avalonia } else { - if (Logger.IsEnabled(LogEventLevel.Verbose)) + if (Logger.TryGetLogger(LogEventLevel.Verbose, out var logger)) { var description = GetDescription(source); - Logger.Log( - LogEventLevel.Verbose, + logger.Log( LogArea.Property, this, "Bound {Property} to {Binding} with priority {Priority}", @@ -416,18 +414,14 @@ namespace Avalonia { RaisePropertyChanged(property, oldValue, newValue, (BindingPriority)priority); - if (Logger.IsEnabled(LogEventLevel.Verbose)) - { - Logger.Log( - LogEventLevel.Verbose, - LogArea.Property, - this, - "{Property} changed from {$Old} to {$Value} with priority {Priority}", - property, - oldValue, - newValue, - (BindingPriority)priority); - } + Logger.TryGetLogger(LogEventLevel.Verbose)?.Log( + LogArea.Property, + this, + "{Property} changed from {$Old} to {$Value} with priority {Priority}", + property, + oldValue, + newValue, + (BindingPriority)priority); } } @@ -826,19 +820,16 @@ namespace Avalonia /// The priority. private void LogPropertySet(AvaloniaProperty property, object value, BindingPriority priority) { - if (!Logger.IsEnabled(LogEventLevel.Verbose)) + if (Logger.TryGetLogger(LogEventLevel.Verbose, out var logger)) { - return; + logger.Log( + LogArea.Property, + this, + "Set {Property} to {$Value} with priority {Priority}", + property, + value, + priority); } - - Logger.Log( - LogEventLevel.Verbose, - LogArea.Property, - this, - "Set {Property} to {$Value} with priority {Priority}", - property, - value, - priority); } private class DirectBindingSubscription : IObserver, IDisposable diff --git a/src/Avalonia.Base/Logging/Logger.cs b/src/Avalonia.Base/Logging/Logger.cs index c46edd4b4b..ef4c29b9f3 100644 --- a/src/Avalonia.Base/Logging/Logger.cs +++ b/src/Avalonia.Base/Logging/Logger.cs @@ -25,6 +25,36 @@ namespace Avalonia.Logging return Sink?.IsEnabled(level) == true; } + /// + /// Returns parametrized logging sink if given log level is enabled. + /// + /// The log event level. + /// Log sink or if log level is not enabled. + public static ParametrizedLogger? TryGetLogger(LogEventLevel level) + { + if (!IsEnabled(level)) + { + return null; + } + + return new ParametrizedLogger(Sink, level); + } + + /// + /// Returns parametrized logging sink if given log level is enabled. + /// + /// The log event level. + /// Log sink that is valid only if method returns . + /// if logger was obtained successfully. + public static bool TryGetLogger(LogEventLevel level, out ParametrizedLogger outLogger) + { + ParametrizedLogger? logger = TryGetLogger(level); + + outLogger = logger.GetValueOrDefault(); + + return logger.HasValue; + } + /// /// Logs an event. /// diff --git a/src/Avalonia.Base/Logging/ParametrizedLogger.cs b/src/Avalonia.Base/Logging/ParametrizedLogger.cs new file mode 100644 index 0000000000..1a0678c79a --- /dev/null +++ b/src/Avalonia.Base/Logging/ParametrizedLogger.cs @@ -0,0 +1,116 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System.Runtime.CompilerServices; + +namespace Avalonia.Logging +{ + /// + /// Logger sink parametrized for given logging level. + /// + public readonly struct ParametrizedLogger + { + private readonly ILogSink _sink; + private readonly LogEventLevel _level; + + public ParametrizedLogger(ILogSink sink, LogEventLevel level) + { + _sink = sink; + _level = level; + } + + /// + /// Checks if this logger can be used. + /// + public bool IsValid => _sink != null; + + /// + /// Logs an event. + /// + /// The area that the event originates. + /// The object from which the event originates. + /// The message template. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Log( + string area, + object source, + string messageTemplate) + { + _sink.Log(_level, area, source, messageTemplate); + } + + /// + /// Logs an event. + /// + /// The area that the event originates. + /// The object from which the event originates. + /// The message template. + /// Message property value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Log( + string area, + object source, + string messageTemplate, + T0 propertyValue0) + { + _sink.Log(_level, area, source, messageTemplate, propertyValue0); + } + + /// + /// Logs an event. + /// + /// The area that the event originates. + /// The object from which the event originates. + /// The message template. + /// Message property value. + /// Message property value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Log( + string area, + object source, + string messageTemplate, + T0 propertyValue0, + T1 propertyValue1) + { + _sink.Log(_level, area, source, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Logs an event. + /// + /// The area that the event originates. + /// The object from which the event originates. + /// The message template. + /// Message property value. + /// Message property value. + /// Message property value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Log( + string area, + object source, + string messageTemplate, + T0 propertyValue0, + T1 propertyValue1, + T2 propertyValue2) + { + _sink.Log(_level, area, source, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Logs an event. + /// + /// The area that the event originates. + /// The object from which the event originates. + /// The message template. + /// The message property values. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Log( + string area, + object source, + string messageTemplate, + params object[] propertyValues) + { + _sink.Log(_level, area, source, messageTemplate, propertyValues); + } + } +}