diff --git a/.github/instructions/instructions.instructions.md b/.github/instructions/instructions.instructions.md
deleted file mode 100644
index 18ef755..0000000
--- a/.github/instructions/instructions.instructions.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-applyTo: '**'
----
-You are a senior C# developer with many years of experience. You use TDD to develop ALL code in small increments.
-For your tests, you use xUnit as the testing framework, Shouldly for the Assertions and, when necessary, NSubstitute for mocking. You try not to use mocks though as it suggests the underlying production code has not been written correctly. Clearly, there are times that mocks have to be used for external dependencies etc.
-Test coverage should be 100% wherever possible. Test coverage should be based on branch coverage, not just line coverage.
-When creating the tests, you use the AAA approach but use blank lines to separate the sections. You do not use comments for this.
-You favour the functional paradigm and use an external library called AStar.Dev.Functional.Extensions that you have full control over. It already contains many classes and methods such as Result, Option, Try and Map, Bind, Match, Tap and async versions of these methods. If a new method is required to make the implementation code, you add the new method with appropriate tests.
-You follow the Microsoft naming conventions.
\ No newline at end of file
diff --git a/.github/prompts/prompts.prompt.md b/.github/prompts/prompts.prompt.md
deleted file mode 100644
index 9c82e52..0000000
--- a/.github/prompts/prompts.prompt.md
+++ /dev/null
@@ -1,27 +0,0 @@
----
-mode: ask
----
-You are a senior C# developer with many years of experience. You use TDD to develop ALL code in small increments.
-For your tests, you use xUnit as the testing framework, Shouldly for the Assertions and, when necessary, NSubstitute for mocking. You try not to use mocks though as it suggests the underlying production code has not been written correctly. Clearly, there are times that mocks have to be used for external dependencies etc.
-Test coverage should be 100% wherever possible. Test coverage should be based on branch coverage, not just line coverage.
-When creating the tests, you use the AAA approach but use blank lines to separate the sections. You do not use comments for this.
-You favour the functional paradigm and use an external library called AStar.Dev.Functional.Extensions that you have full control over. It already contains many classes and methods such as Result, Option, Try and Map, Bind, Match, Tap and async versions of these methods. If a new method is required to make the implementation code, you add the new method with appropriate tests.
-You follow the Microsoft naming conventions.
----
-mode: Agent
----
-You are a senior C# developer with many years of experience. You use TDD to develop ALL code in small increments.
-For your tests, you use xUnit as the testing framework, Shouldly for the Assertions and, when necessary, NSubstitute for mocking. You try not to use mocks though as it suggests the underlying production code has not been written correctly. Clearly, there are times that mocks have to be used for external dependencies etc.
-Test coverage should be 100% wherever possible. Test coverage should be based on branch coverage, not just line coverage.
-When creating the tests, you use the AAA approach but use blank lines to separate the sections. You do not use comments for this.
-You favour the functional paradigm and use an external library called AStar.Dev.Functional.Extensions that you have full control over. It already contains many classes and methods such as Result, Option, Try and Map, Bind, Match, Tap and async versions of these methods. If a new method is required to make the implementation code, you add the new method with appropriate tests.
-You follow the Microsoft naming conventions.
----
-mode: edit
----
-You are a senior C# developer with many years of experience. You use TDD to develop ALL code in small increments.
-For your tests, you use xUnit as the testing framework, Shouldly for the Assertions and, when necessary, NSubstitute for mocking. You try not to use mocks though as it suggests the underlying production code has not been written correctly. Clearly, there are times that mocks have to be used for external dependencies etc.
-Test coverage should be 100% wherever possible. Test coverage should be based on branch coverage, not just line coverage.
-When creating the tests, you use the AAA approach but use blank lines to separate the sections. You do not use comments for this.
-You favour the functional paradigm and use an external library called AStar.Dev.Functional.Extensions that you have full control over. It already contains many classes and methods such as Result, Option, Try and Map, Bind, Match, Tap and async versions of these methods. If a new method is required to make the implementation code, you add the new method with appropriate tests.
-You follow the Microsoft naming conventions.
\ No newline at end of file
diff --git a/.github/scratch.md b/.github/scratch.md
deleted file mode 100644
index e69de29..0000000
diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
index 95533eb..125d797 100644
--- a/.github/workflows/dotnet.yml
+++ b/.github/workflows/dotnet.yml
@@ -1,4 +1,4 @@
-name: Build the NuGet package
+name: .NET
on:
workflow_dispatch:
@@ -11,10 +11,7 @@ jobs:
build:
name: Build and analyze
runs-on: windows-latest
- env:
- SONAR_PROJECT: astar-dev-logging-extensions
- ProjectName: 'AStar.Dev.Logging.Extensions'
- RepositoryName: 'astar-dev-logging-extensions'
+
steps:
- name: Set up JDK
uses: actions/setup-java@v4.4.0
@@ -49,23 +46,14 @@ jobs:
New-Item -Path .\.sonar\scanner -ItemType Directory
dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
- - name: 🔍 Restore, 🛠 Build and 🧪 Test with ☁️ SonarCloud / Qube
+ - name: 🔍 Restore, 🛠 Build and 🧪 Test with ☁️ SonarCloud / Qube project - ${{ vars.SONAR_PROJECT_NAME }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: powershell
run: |
dotnet tool install --global dotnet-coverage
- .\.sonar\scanner\dotnet-sonarscanner begin /k:"astar-development_${{ env.SONAR_PROJECT }}" /o:"astar-development" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml /d:sonar.scanner.scanAll=false /d:sonar.scanner.skipJreProvisioning=true
+ .\.sonar\scanner\dotnet-sonarscanner begin /k:"astar-development_${{ github.event.repository.name }}" /o:"astar-development" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml /d:sonar.scanner.scanAll=false /d:sonar.scanner.skipJreProvisioning=true
dotnet build --configuration Release
dotnet-coverage collect 'dotnet test --filter "FullyQualifiedName!~Tests.EndToEnd"' -f xml -o 'coverage.xml'
.\.sonar\scanner\dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
-
- - name: Pack NuGet package
- if: github.ref == 'refs/heads/main'
- run: dotnet pack .\src\${{ env.ProjectName }}\${{ env.ProjectName }}.csproj
-
- - name: Push to NuGet
- if: github.ref == 'refs/heads/main'
- run: dotnet nuget push "**\${{ env.ProjectName }}.*.nupkg" --api-key ${{secrets.nuget_api_key}} --skip-duplicate --source https://api.nuget.org/v3/index.json
-
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 0000000..1f8c366
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,32 @@
+name: 🚀 Publish NuGet Package
+
+on:
+ workflow_dispatch:
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+
+ steps:
+ - name: 🧾 Checkout code
+ uses: actions/checkout@v4
+
+ - name: 🛠 Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: '9.x'
+
+ - name: 🔍 Restore dependencies
+ run: dotnet restore
+
+ - name: 🛠 Build solution
+ run: dotnet build --configuration Release
+
+ - name: 📦 Pack NuGet package for ${{ github.event.repository.name }}
+ run: dotnet pack ./src/**/*.csproj --configuration Release --output ./nupkg
+
+ - name: 🚀 Publish to NuGet.org
+ run: dotnet nuget push ./nupkg/*.nupkg --skip-duplicate --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NuGet_API_Key }} #
+
diff --git a/.idea/.idea.AStar.Dev.Logging.Extensions/.idea/sonarlint.xml b/.idea/.idea.AStar.Dev.Logging.Extensions/.idea/sonarlint.xml
new file mode 100644
index 0000000..539a9ad
--- /dev/null
+++ b/.idea/.idea.AStar.Dev.Logging.Extensions/.idea/sonarlint.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AStar.Dev.Logging.Extensions.sln b/AStar.Dev.Logging.Extensions.sln
deleted file mode 100644
index 5f2e7e7..0000000
--- a/AStar.Dev.Logging.Extensions.sln
+++ /dev/null
@@ -1,52 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.0.31903.59
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{2148A5BF-30D5-460A-BE18-C19426C87428}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{BB29ADA9-37FE-434B-BF05-2E195E7C83A2}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AStar.Dev.Logging.Extensions", "src\AStar.Dev.Logging.Extensions\AStar.Dev.Logging.Extensions.csproj", "{9F2D808F-D24F-4031-9C2D-7744B32E15FC}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AStar.Dev.Logging.Extensions.Tests.Unit", "tests\AStar.Dev.Logging.Extensions.Tests.Unit\AStar.Dev.Logging.Extensions.Tests.Unit.csproj", "{B6EE17A9-0491-466B-8240-A304617A9DB3}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{D3039A93-8371-42A2-814F-2E09B74E8FBF}"
- ProjectSection(SolutionItems) = preProject
- .github\dependabot.yml = .github\dependabot.yml
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{A62713CB-F1A7-446C-875B-74F964FC52F4}"
- ProjectSection(SolutionItems) = preProject
- .github\workflows\dotnet.yml = .github\workflows\dotnet.yml
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7F1D630D-103D-4EA1-848F-F24489B64E5C}"
- ProjectSection(SolutionItems) = preProject
- blog-draft.md = blog-draft.md
- EndProjectSection
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {9F2D808F-D24F-4031-9C2D-7744B32E15FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9F2D808F-D24F-4031-9C2D-7744B32E15FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9F2D808F-D24F-4031-9C2D-7744B32E15FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9F2D808F-D24F-4031-9C2D-7744B32E15FC}.Release|Any CPU.Build.0 = Release|Any CPU
- {B6EE17A9-0491-466B-8240-A304617A9DB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B6EE17A9-0491-466B-8240-A304617A9DB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B6EE17A9-0491-466B-8240-A304617A9DB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B6EE17A9-0491-466B-8240-A304617A9DB3}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {9F2D808F-D24F-4031-9C2D-7744B32E15FC} = {BB29ADA9-37FE-434B-BF05-2E195E7C83A2}
- {B6EE17A9-0491-466B-8240-A304617A9DB3} = {2148A5BF-30D5-460A-BE18-C19426C87428}
- {A62713CB-F1A7-446C-875B-74F964FC52F4} = {D3039A93-8371-42A2-814F-2E09B74E8FBF}
- EndGlobalSection
-EndGlobal
diff --git a/AStar.Dev.Logging.Extensions.slnx b/AStar.Dev.Logging.Extensions.slnx
new file mode 100644
index 0000000..ef8b145
--- /dev/null
+++ b/AStar.Dev.Logging.Extensions.slnx
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AStar.png b/AStar.png
deleted file mode 100644
index 8cac0a1..0000000
Binary files a/AStar.png and /dev/null differ
diff --git a/astar.ico b/astar.ico
new file mode 100644
index 0000000..38b6709
Binary files /dev/null and b/astar.ico differ
diff --git a/astar.png b/astar.png
new file mode 100644
index 0000000..74b197e
Binary files /dev/null and b/astar.png differ
diff --git a/src/AStar.Dev.Logging.Extensions/AStar.Dev.Logging.Extensions.csproj b/src/AStar.Dev.Logging.Extensions/AStar.Dev.Logging.Extensions.csproj
index 81dc4ea..e6367da 100644
--- a/src/AStar.Dev.Logging.Extensions/AStar.Dev.Logging.Extensions.csproj
+++ b/src/AStar.Dev.Logging.Extensions/AStar.Dev.Logging.Extensions.csproj
@@ -2,38 +2,50 @@
net9.0
- enableenable
- astar.ico
+ enable
+ latest-recommended
+ True
+
+ AStar Developement, Jason Barden
+ AStar DevelopmentAStar Developement, 2025
- https://github.com/astar-development/astar-dev-logging-extensions
- https://github.com/astar-development/astar-dev-logging-extensions.git
- git
- True
- snupkg
- Readme.md
- true
- LICENSE
+ This package contains extension methods designed to add Serilog and Application Insights to the project. The logging is opinionated but the configuration can be overridden. In addition, Open Telemetry is being incorporated$(AssemblyName).xml
+ truetrue
- 0.6.0
- AStar.Dev.Logging.Extensions
- This package contains extension methods designed to add Serilog and Application Insights to the project. The logging is opinionated but the configuration can be overridden.
+ true
+ trueastar.png
- Logging Application Insights Serilog LoggerMessage Templates
+ AStar.Dev.Logging.Extensions
+ MIT
+ Readme.mdAdd some LoggerMessage templates to cover the core use-cases
+ true
+ Logging Application Insights Serilog LoggerMessage Templates
+ true
+ git
+ https://github.com/astar-development/astar-dev-logging-extensions
+ https://github.com/astar-development/astar-dev-logging-extensions.git
+ snupkg
+ AStar.Dev.Logging.Extensions
+ 0.6.1
-
+
+
+
+
+
+
-
diff --git a/src/AStar.Dev.Logging.Extensions/AStar.Dev.Logging.Extensions.xml b/src/AStar.Dev.Logging.Extensions/AStar.Dev.Logging.Extensions.xml
index 054a8d6..6c82a4e 100644
--- a/src/AStar.Dev.Logging.Extensions/AStar.Dev.Logging.Extensions.xml
+++ b/src/AStar.Dev.Logging.Extensions/AStar.Dev.Logging.Extensions.xml
@@ -6,52 +6,40 @@
- The
-
- class contains the defined
-
- events available for logging
- Stand-alone
-
- events can be defined but care should be taken to avoid reusing the values used here
+ The class contains the defined events available for logging
+ Stand-alone events can be defined but care should be taken to avoid reusing the values used here
- Gets the
-
- preconfigured for logging a page view
+ Gets the preconfigured for logging a page view
- Provides an implementation of
-
- that integrates application telemetry tracking
+ Provides an implementation of that integrates application telemetry tracking
with structured logging for enhanced observability in A* applications.
The category name for the logger, typically derived from the type being logged.
- Provides an implementation of
-
- that integrates application telemetry tracking
+ Provides an implementation of that integrates application telemetry tracking
with structured logging for enhanced observability in A* applications.
The category name for the logger, typically derived from the type being logged.
-
+
-
+
-
+
-
+
@@ -70,7 +58,7 @@
The Instrumentation Key to configure Application Insights with
-
+
@@ -112,17 +100,13 @@
- The
-
- class contains, as you might expect, extension methods for configuring Serilog
+ The class contains, as you might expect, extension methods for configuring Serilog
/ Application Insights.
- The
-
- method will add Serilog to the logging providers.
+ The method will add Serilog to the logging providers.
@@ -130,16 +114,12 @@
The name (including extension) of the file containing the Serilog Configuration settings.
- The original instance of
-
- for further method chaining.
+ The original instance of for further method chaining.
- The
-
- method will add Serilog to the logging providers.
+ The method will add Serilog to the logging providers.
@@ -147,9 +127,7 @@
The name (including extension) of the file containing the Serilog Configuration settings.
- The original instance of
-
- for further method chaining.
+ The original instance of for further method chaining.
@@ -157,6 +135,13 @@
Provides static methods for logging specific HTTP-related events using strongly-typed logging templates.
+
+
+ Logs an informational message indicating that a specific page has been viewed.
+
+ The logger to be used for logging the event.
+ The name of the page that was viewed.
+
Logs a warning message for a Bad Request (400) event, including the requested path.
@@ -237,9 +222,7 @@
- The
-
- class which is used to configure the logging.
+ The class which is used to configure the logging.
@@ -315,9 +298,9 @@
Gets or sets a value indicating whether the JSON output should be indented.
- If set to, the JSON will be formatted with additional
+ If set to , the JSON will be formatted with additional
whitespace for readability (e.g., line breaks and indentation).
- If set to, the JSON will be written as a single line
+ If set to , the JSON will be written as a single line
without extra whitespace, minimizing the output size.
@@ -367,18 +350,14 @@
- Represents the default logging level configuration within the
-
- class,
+ Represents the default logging level configuration within the class,
allowing the specification of a baseline logging level for the application.
Represents configuration overrides for specific logging sources or categories within
- the
-
- class, allowing custom logging levels to be defined
+ the class, allowing custom logging levels to be defined
for particular components of the application.
@@ -469,17 +448,10 @@
Configures the Serilog logger using the specified settings and telemetry configuration.
- The
-
- instance to be configured.
-
+ The instance to be configured.
The application configuration settings to read from.
- The
-
- instance used for Application Insights integration.
-
- The configured instance of.
-
+ The instance used for Application Insights integration.
+ The configured instance of .
diff --git a/src/AStar.Dev.Logging.Extensions/AStarLogger.cs b/src/AStar.Dev.Logging.Extensions/AStarLogger.cs
index 3757c27..1afe209 100644
--- a/src/AStar.Dev.Logging.Extensions/AStarLogger.cs
+++ b/src/AStar.Dev.Logging.Extensions/AStarLogger.cs
@@ -13,8 +13,8 @@ public sealed class AStarLogger(ILogger logger, IT
public void LogPageView(string pageName)
{
ArgumentNullException.ThrowIfNull(pageName);
+ LogMessageTemplate.NotFound(logger, "/missing-resource");
- logger.LogInformation(AStarEventIds.PageView, "Page view: {PageView}", pageName);
telemetryClient.TrackPageView(pageName);
}
@@ -25,6 +25,6 @@ public void LogPageView(string pageName)
public bool IsEnabled(LogLevel logLevel) => logger.IsEnabled(logLevel);
///
- public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) =>
- logger.Log(logLevel, eventId, state, exception, formatter);
+ public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter)
+ => logger.Log(logLevel, eventId, state, exception, formatter);
}
\ No newline at end of file
diff --git a/src/AStar.Dev.Logging.Extensions/LogMessageTemplate.cs b/src/AStar.Dev.Logging.Extensions/LogMessageTemplate.cs
index 1adad48..bb7154c 100644
--- a/src/AStar.Dev.Logging.Extensions/LogMessageTemplate.cs
+++ b/src/AStar.Dev.Logging.Extensions/LogMessageTemplate.cs
@@ -7,6 +7,14 @@ namespace AStar.Dev.Logging.Extensions;
///
public static partial class LogMessageTemplate
{
+ ///
+ /// Logs an informational message indicating that a specific page has been viewed.
+ ///
+ /// The logger to be used for logging the event.
+ /// The name of the page that was viewed.
+ [LoggerMessage(EventId = 200, Level = LogLevel.Information, Message = "Page `{PageName}` viewed.")]
+ public static partial void PageView(ILogger logger, string pageName);
+
///
/// Logs a warning message for a Bad Request (400) event, including the requested path.
///
diff --git a/src/AStar.Dev.Logging.Extensions/LoggingExtensions.cs b/src/AStar.Dev.Logging.Extensions/LoggingExtensions.cs
index b54dab8..f1e72e7 100644
--- a/src/AStar.Dev.Logging.Extensions/LoggingExtensions.cs
+++ b/src/AStar.Dev.Logging.Extensions/LoggingExtensions.cs
@@ -68,7 +68,7 @@ public static HostApplicationBuilder AddSerilogLogging(this HostApplicationBuild
}
// Register a default TelemetryConfiguration if not present, for test/integration scenarios.
- builder.Services.AddSingleton(_ => new());
+ _ = builder.Services.AddSingleton(_ => new());
var serviceProvider = builder.Services.BuildServiceProvider();
var logger = new LoggerConfiguration()
diff --git a/src/AStar.Dev.Logging.Extensions/SerilogConfigure.cs b/src/AStar.Dev.Logging.Extensions/SerilogConfigure.cs
index 3b9a17d..210d23e 100644
--- a/src/AStar.Dev.Logging.Extensions/SerilogConfigure.cs
+++ b/src/AStar.Dev.Logging.Extensions/SerilogConfigure.cs
@@ -1,3 +1,4 @@
+using System.Globalization;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Extensions.Configuration;
using Serilog;
@@ -16,9 +17,10 @@ internal static class SerilogConfigure
/// The application configuration settings to read from.
/// The instance used for Application Insights integration.
/// The configured instance of .
- public static LoggerConfiguration Configure(this LoggerConfiguration loggerConfiguration, IConfiguration configuration, TelemetryConfiguration telemetryConfiguration) =>
- loggerConfiguration
- .WriteTo.ApplicationInsights(telemetryConfiguration,
- TelemetryConverter.Traces).WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {Message:lj}{NewLine}{Exception}")
- .ReadFrom.Configuration(configuration);
+ public static LoggerConfiguration Configure(this LoggerConfiguration loggerConfiguration, IConfiguration configuration, TelemetryConfiguration telemetryConfiguration)
+ => loggerConfiguration
+ .WriteTo.ApplicationInsights(telemetryConfiguration,
+ TelemetryConverter.Traces).WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {Message:lj}{NewLine}{Exception}",
+ formatProvider: new CultureInfo(0809))
+ .ReadFrom.Configuration(configuration);
}
\ No newline at end of file
diff --git a/tests/AStar.Dev.Logging.Extensions.Tests.Unit/AStar.Dev.Logging.Extensions.Tests.Unit.csproj b/tests/AStar.Dev.Logging.Extensions.Tests.Unit/AStar.Dev.Logging.Extensions.Tests.Unit.csproj
index a312c53..629ccd9 100644
--- a/tests/AStar.Dev.Logging.Extensions.Tests.Unit/AStar.Dev.Logging.Extensions.Tests.Unit.csproj
+++ b/tests/AStar.Dev.Logging.Extensions.Tests.Unit/AStar.Dev.Logging.Extensions.Tests.Unit.csproj
@@ -12,12 +12,12 @@
-
+ allruntime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/tests/tests.sln b/tests/tests.sln
new file mode 100644
index 0000000..f56eb69
--- /dev/null
+++ b/tests/tests.sln
@@ -0,0 +1,24 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.2.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AStar.Dev.Logging.Extensions.Tests.Unit", "AStar.Dev.Logging.Extensions.Tests.Unit\AStar.Dev.Logging.Extensions.Tests.Unit.csproj", "{B632B798-552A-ABF4-C2EC-8BA23B67C816}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B632B798-552A-ABF4-C2EC-8BA23B67C816}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B632B798-552A-ABF4-C2EC-8BA23B67C816}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B632B798-552A-ABF4-C2EC-8BA23B67C816}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B632B798-552A-ABF4-C2EC-8BA23B67C816}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {43F8AC86-7006-4F6B-917D-64CCB494E87A}
+ EndGlobalSection
+EndGlobal