diff --git a/.github/workflows/dotnet-desktop.yml b/.github/workflows/dotnet-desktop.yml
index a4ed437..0a5a46d 100644
--- a/.github/workflows/dotnet-desktop.yml
+++ b/.github/workflows/dotnet-desktop.yml
@@ -28,9 +28,19 @@ jobs:
- name: Restore dependencies
run: dotnet restore
+ - name: Bump & push tag
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
+ uses: mathieudutour/github-tag-action@v6.2
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ tag_prefix: ""
+
- name: Build
run: dotnet build --configuration Release --no-restore
+ - name: Test
+ run: dotnet test --configuration Release --no-build
+
- name: Publish Nuget
shell: pwsh
run: |
diff --git a/FluentLoggerExtensions.slnx b/FluentLoggerExtensions.slnx
index 150dff5..110d30d 100644
--- a/FluentLoggerExtensions.slnx
+++ b/FluentLoggerExtensions.slnx
@@ -1,6 +1,8 @@
+
-
+
+
diff --git a/CallerLogContext.cs b/src/CallerLogContext.cs
similarity index 100%
rename from CallerLogContext.cs
rename to src/CallerLogContext.cs
diff --git a/CallerLogContextExtensions.cs b/src/CallerLogContextExtensions.cs
similarity index 53%
rename from CallerLogContextExtensions.cs
rename to src/CallerLogContextExtensions.cs
index 35547ca..3fd42c7 100644
--- a/CallerLogContextExtensions.cs
+++ b/src/CallerLogContextExtensions.cs
@@ -15,8 +15,22 @@ public static class CallerLogContextExtensions
/// The arguments for the message.
public static void LogInformation(this CallerLogContext context, string message, params object?[] args)
{
- string? fileName = Path.GetFileName(context.File);
- context.Logger.LogInformation("[{File}:{Member}:{Line}] " + message, PrependCallerArgs(fileName, context.Member, context.Line, args));
+ string fileName = Path.GetFileName(context.File);
+
+ try
+ {
+ context.Logger.LogInformation(
+ "[{File}:{Member}:{Line}] " + message,
+ PrependCallerArgs(fileName, context.Member, context.Line, args));
+ }
+ catch (Exception ex)
+ {
+ // Fall back to a safe message; don't rethrow
+ context.Logger.LogError(
+ ex,
+ "[{File}:{Member}:{Line}] Logging failed for template. Template={Template}",
+ fileName, context.Member, context.Line, message);
+ }
}
///
@@ -27,8 +41,22 @@ public static void LogInformation(this CallerLogContext context, string message,
/// The arguments for the message.
public static void LogError(this CallerLogContext context, string message, params object?[] args)
{
- string? fileName = Path.GetFileName(context.File);
- context.Logger.LogError("[{File}:{Member}:{Line}] " + message, PrependCallerArgs(fileName, context.Member, context.Line, args));
+ string fileName = Path.GetFileName(context.File);
+
+ try
+ {
+ context.Logger.LogError(
+ "[{File}:{Member}:{Line}] " + message,
+ PrependCallerArgs(fileName, context.Member, context.Line, args));
+ }
+ catch (Exception ex)
+ {
+ // Fall back to a safe message; don't rethrow
+ context.Logger.LogError(
+ ex,
+ "[{File}:{Member}:{Line}] Logging failed for template. Template={Template}",
+ fileName, context.Member, context.Line, message);
+ }
}
///
@@ -39,8 +67,22 @@ public static void LogError(this CallerLogContext context, string message, param
/// The arguments for the message.
public static void LogDebug(this CallerLogContext context, string message, params object?[] args)
{
- string? fileName = Path.GetFileName(context.File);
- context.Logger.LogDebug("[{File}:{Member}:{Line}] " + message, PrependCallerArgs(fileName, context.Member, context.Line, args));
+ string fileName = Path.GetFileName(context.File);
+
+ try
+ {
+ context.Logger.LogDebug(
+ "[{File}:{Member}:{Line}] " + message,
+ PrependCallerArgs(fileName, context.Member, context.Line, args));
+ }
+ catch (Exception ex)
+ {
+ // Fall back to a safe message; don't rethrow
+ context.Logger.LogDebug(
+ ex,
+ "[{File}:{Member}:{Line}] Logging failed for template. Template={Template}",
+ fileName, context.Member, context.Line, message);
+ }
}
///
@@ -51,8 +93,22 @@ public static void LogDebug(this CallerLogContext context, string message, param
/// The arguments for the message.
public static void LogWarning(this CallerLogContext context, string message, params object?[] args)
{
- string? fileName = Path.GetFileName(context.File);
- context.Logger.LogWarning("[{File}:{Member}:{Line}] " + message, PrependCallerArgs(fileName, context.Member, context.Line, args));
+ string fileName = Path.GetFileName(context.File);
+
+ try
+ {
+ context.Logger.LogWarning(
+ "[{File}:{Member}:{Line}] " + message,
+ PrependCallerArgs(fileName, context.Member, context.Line, args));
+ }
+ catch (Exception ex)
+ {
+ // Fall back to a safe message; don't rethrow
+ context.Logger.LogWarning(
+ ex,
+ "[{File}:{Member}:{Line}] Logging failed for template. Template={Template}",
+ fileName, context.Member, context.Line, message);
+ }
}
///
diff --git a/FluentLoggerExtensions.cs b/src/FluentLoggerExtensions.cs
similarity index 100%
rename from FluentLoggerExtensions.cs
rename to src/FluentLoggerExtensions.cs
diff --git a/FluentLoggerExtensions.csproj b/src/FluentLoggerExtensions.csproj
similarity index 88%
rename from FluentLoggerExtensions.csproj
rename to src/FluentLoggerExtensions.csproj
index c8f6846..97813f0 100644
--- a/FluentLoggerExtensions.csproj
+++ b/src/FluentLoggerExtensions.csproj
@@ -13,6 +13,7 @@
MIT
true
snupkg
+ README.md
@@ -23,4 +24,8 @@
+
+
+
+
diff --git a/tests/FluentLoggerExtensions.Tests/CallerLogContextLogDebugTests.cs b/tests/FluentLoggerExtensions.Tests/CallerLogContextLogDebugTests.cs
new file mode 100644
index 0000000..7f0cfcf
--- /dev/null
+++ b/tests/FluentLoggerExtensions.Tests/CallerLogContextLogDebugTests.cs
@@ -0,0 +1,73 @@
+using FluentLogger;
+using Microsoft.Extensions.Logging;
+using Moq;
+
+namespace FluentLoggerExtensions.Tests;
+
+public class CallerLogContextLogDebugTests
+{
+ [Theory]
+ [InlineData("This is a test log message")]
+ [InlineData("This is another test log message")]
+ [InlineData("This is a really log test message")]
+ public void LogDebug_WithPlainMessage_DoesNotThrow(string message)
+ {
+ Mock logger = new();
+ logger.Object.WithCaller().LogDebug(message);
+ logger.VerifyLogContains(message, LogLevel.Debug);
+ }
+
+ [Theory]
+ [InlineData("hello")]
+ public void LogDebug_WithInterpolatedString_DoesNotThrow(string id)
+ {
+ Mock logger = new();
+
+ logger.Object.WithCaller().LogDebug($"{id}");
+ }
+
+ [Theory]
+ [InlineData("hello", "there")]
+ public void LogDebug_WithMatchingPlaceholdersAndArguments_DoesNotThrow(string id, string id2)
+ {
+ Mock logger = new();
+ logger.Object.WithCaller().LogDebug("{FirstWord} {SecondWord}", id, id2);
+ }
+
+ [Theory]
+ [InlineData("hello")]
+ public void LogDebug_WithMissingArguments_DoesNotThrowUntilStateIsEnumerated(string id)
+ {
+ Mock logger = new();
+ logger.Object.WithCaller().LogDebug("{FirstWord} {SecondWord}", id);
+ }
+
+ [Fact]
+ public void Mismatched_placeholders_throw_when_state_is_enumerated()
+ {
+ var logger = new Mock();
+
+ logger
+ .Setup(l => l.Log(
+ It.IsAny(),
+ It.IsAny(),
+ It.IsAny(),
+ It.IsAny(),
+ (Func)It.IsAny