Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions WB.Logging.Base.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
<Folder Name="/tests/ILoggerExtensionsTests/src/">
<Project Path="tests/ILoggerExtensionsTests/src/ILoggerExtensionsTests.csproj" />
</Folder>
<Folder Name="/tests/LogMessageRegistryTests/" />
<Folder Name="/tests/LogMessageRegistryTests/src/">
<Project Path="tests/LogMessageRegistryTests/src/LogMessageRegistryTests.csproj" />
<Folder Name="/tests/LogMessageFiltersTests/" />
<Folder Name="/tests/LogMessageFiltersTests/src/">
<Project Path="tests/LogMessageFiltersTests/src/LogMessageFiltersTests.csproj" />
</Folder>
</Solution>
36 changes: 0 additions & 36 deletions src/ILogMessage.cs

This file was deleted.

9 changes: 4 additions & 5 deletions src/ILogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public interface ILogger : IAsyncDisposable
public IReadOnlyList<ILogSink> LogSinks { get; }

/// <summary>
/// Gets the minimum <see cref="LogLevel"/> for <see cref="ILogMessage{TPayload}"/>s.
/// Gets the minimum <see cref="LogLevel"/> for <see cref="LogMessage"/>s.
/// </summary>
public LogLevel? MinimumLogLevel { get; set; }

Expand Down Expand Up @@ -84,10 +84,9 @@ public void Log<TPayload>(LogLevel? logLevel, TPayload payload)
public ILogger CreateChildLogger(string name);

/// <summary>
/// Attaches a <see cref="LogMessageFilter{TPayload}"/> to this logger. The filter will be applied to all log messages of type <typeparamref name="TPayload"/> submitted to this logger.
/// Attaches a <see cref="LogMessageFilter"/> to this logger. The filter will be applied to all log messages submitted to this logger.
/// </summary>
/// <param name="filter">The <see cref="LogMessageFilter{TPayload}"/> to attach.</param>
/// <param name="filter">The <see cref="LogMessageFilter"/> to attach.</param>
/// <returns>An <see cref="IDisposable"/> that can be used to detach the filter.</returns>
public IDisposable AddLogMessageFilter<TPayload>(LogMessageFilter<TPayload> filter)
where TPayload : notnull;
public IDisposable AddLogMessageFilter(LogMessageFilter filter);
}
46 changes: 46 additions & 0 deletions src/LogMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;

namespace WB.Logging;

/// <summary>
/// A log message.
/// </summary>
public sealed record LogMessage
{
// ┌─────────────────────────────────────────────────────────────────────────────┐
// │ Public Properties │
// └─────────────────────────────────────────────────────────────────────────────┘
private readonly List<string> senders = [];

// ┌─────────────────────────────────────────────────────────────────────────────┐
// │ Public Properties │
// └─────────────────────────────────────────────────────────────────────────────┘

/// <summary>
/// Gets the timestamp of the log message.
/// </summary>
public DateTimeOffset Timestamp { get; init; } = DateTimeOffset.Now;

/// <summary>
/// Gets the senders of the log message.
/// </summary>
public IReadOnlyList<string> Senders => senders.AsReadOnly();

/// <summary>
/// Gets the <see cref="LogLevel"/> of the log message.
/// </summary>
public LogLevel? LogLevel { get; init; }

/// <summary>
/// Gets the payload of the log message.
/// </summary>
public required object Payload { get; init; }

// ┌─────────────────────────────────────────────────────────────────────────────┐
// │ Internal Properties │
// └─────────────────────────────────────────────────────────────────────────────┘
internal void AddSender(string sender)
=> senders.Add(sender);

}
11 changes: 0 additions & 11 deletions src/LogMessageFilter/ILogMessageFilterWrapper.cs

This file was deleted.

10 changes: 10 additions & 0 deletions src/LogMessageFilter/LogMessageFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;

namespace WB.Logging;

/// <summary>
/// A filter for <see cref="LogMessage"/>.
/// </summary>
/// <param name="message">The log message to filter.</param>
/// <returns><c>true</c> if the log message matches the filter; otherwise, <c>false</c>.</returns>
public delegate bool LogMessageFilter(LogMessage message);
12 changes: 0 additions & 12 deletions src/LogMessageFilter/LogMessageFilterDelegate.cs

This file was deleted.

141 changes: 0 additions & 141 deletions src/LogMessageFilter/LogMessageFilterRegistry.cs

This file was deleted.

13 changes: 0 additions & 13 deletions src/LogMessageFilter/LogMessageFilterWrapper{TPayload}.cs

This file was deleted.

59 changes: 59 additions & 0 deletions src/LogMessageFilter/LogMessageFilters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;

namespace WB.Logging;

/// <summary>
/// A set of <see cref="LogMessageFilter"/>s registered for different payload types.
/// </summary>
public sealed class LogMessageFilters
{
// ┌─────────────────────────────────────────────────────────────────────────────┐
// │ Private Fields │
// └─────────────────────────────────────────────────────────────────────────────┘
private readonly ConcurrentBag<LogMessageFilter> logMessageFilters = [];

// ┌─────────────────────────────────────────────────────────────────────────────┐
// │ Public Methods │
// └─────────────────────────────────────────────────────────────────────────────┘

/// <summary>
/// Registers the <paramref name="filter"/> for <see cref="LogMessage"/>.
/// </summary>
/// <param name="filter">The <see cref="LogMessageFilter"/> to register.</param>
/// <returns>An <see cref="IDisposable"/> that can be used to unregister the filter.</returns>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="filter"/> is <c>null</c>.</exception>
public IDisposable Add(LogMessageFilter filter)
{
ArgumentNullException.ThrowIfNull(filter);

logMessageFilters.Add(filter);

return new DelegateDisposable(() =>
{
logMessageFilters.TryTake(out LogMessageFilter? _);
});
}

/// <summary>
/// Determines whether the specified <paramref name="logMessage"/> matches the registered filter for
/// its payload type.
/// </summary>
/// <param name="logMessage">The log message to check.</param>
/// <returns><c>true</c> if the log message matches the filter; otherwise, <c>false</c>.</returns>
public bool IsMatch(LogMessage logMessage)
{
ArgumentNullException.ThrowIfNull(logMessage);

foreach (LogMessageFilter logMessageFilter in logMessageFilters)
{
if (!logMessageFilter(logMessage))
{
return false;
}
}

return true;
}
}
8 changes: 3 additions & 5 deletions src/LogSinks/IAsyncLogSink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ public interface IAsyncLogSink
// └─────────────────────────────────────────────────────────────────────────────┘

/// <summary>
/// Submits a <see cref="ILogMessage{TPayload}"/> to this log sink for processing.
/// Submits a <see cref="LogMessage"/> to this log sink for processing.
/// </summary>
/// <param name="logMessage">The <see cref="ILogMessage{TPayload}"/> to submit.</param>
/// <typeparam name="TPayload">The type of the payload of the log message.</typeparam>
/// <param name="logMessage">The <see cref="LogMessage"/> to submit.</param>
/// <returns>A <see cref="ValueTask"/> that represents the asynchronous operation of submitting the log message.</returns>
public ValueTask SubmitAsync<TPayload>(ILogMessage<TPayload> logMessage)
where TPayload : notnull;
public ValueTask SubmitAsync(LogMessage logMessage);
}
Loading
Loading