├── test
├── .gitignore
├── Rendering
│ ├── Verified
│ │ ├── MarginControlRendererTests.RenderWritesExpectedOutputForAdjust.DotNet.verified.txt
│ │ ├── MarginControlRendererTests.RenderWritesExpectedOutputForSet.DotNet.verified.txt
│ │ ├── ExceptionRendererTests.RenderHidesAggregateInnerExceptions.Core.verified.txt
│ │ ├── ExceptionRendererTests.RenderHidesAggregateInnerExceptions.DotNet.verified.txt
│ │ ├── ExceptionRendererTests.RenderHidesSourcePaths.Core.verified.txt
│ │ ├── ExceptionRendererTests.RenderHidesSourcePaths.DotNet.verified.txt
│ │ ├── ExceptionRendererTests.RenderHidesParameterNames.Core.verified.txt
│ │ ├── ExceptionRendererTests.RenderHidesParameterTypes.DotNet.verified.txt
│ │ ├── ExceptionRendererTests.RenderHidesParameterNames.DotNet.verified.txt
│ │ ├── ExceptionRendererTests.RenderHidesParameterTypes.Core.verified.txt
│ │ ├── ExceptionRendererTests.RenderHidesSourceLocations.Core.verified.txt
│ │ ├── ExceptionRendererTests.RenderWritesExpected.Core.verified.txt
│ │ ├── ExceptionRendererTests.RenderHidesSourceLocations.DotNet.verified.txt
│ │ ├── ExceptionRendererTests.RenderWritesExpected.DotNet.verified.txt
│ │ ├── ExceptionRendererTests.RenderLimitsStackFrames.DotNet.verified.txt
│ │ └── ExceptionRendererTests.RenderLimitsStackFrames.Core.verified.txt
│ ├── StaticSpanRendererTests.cs
│ ├── NewLineRendererTests.cs
│ ├── ProcessIdRendererTests.cs
│ ├── ThreadIdRendererTests.cs
│ ├── DateTimeRendererTests.cs
│ ├── ActivityIdRendererTests.cs
│ ├── MarginControlRendererTests.cs
│ ├── LogLevelRendererTests.cs
│ ├── MessageRendererTests.cs
│ └── CategoryNameRendererTests.cs
├── Destructuring
│ ├── DestructuringWriterTests.WriteObjectRendersExpectedContent.verified.txt
│ ├── DestructuringWriterTests.WriteDictionaryRendersExpectedContent.verified.txt
│ ├── DestructuringWriterTests.WriteDictionaryRespectsMaxDepth.verified.txt
│ ├── DestructuringWriterTests.WriteObjectIndented.verified.txt
│ └── CompiledWriterCacheTests.cs
├── Formatting
│ ├── NullValueTests.cs
│ ├── MultiTypeFormatProviderTests.cs
│ ├── IntegralFormattingTests.cs
│ ├── ValueFormatterTests.cs
│ ├── ProviderFormatterTests.cs
│ └── MultiTypeFormatterTests.cs
├── Infrastructure
│ ├── Factory.cs
│ ├── Person.cs
│ ├── ExceptionHelper.cs
│ ├── SharedSettings.cs
│ └── RendererTestHarness.cs
├── DependencyInjectionTests.cs
├── Options
│ ├── SerilogStyleLoggerOptionsTests.cs
│ └── MicrosoftStyleLoggerOptionsTests.cs
├── Internal
│ └── DelegateLogEventFilterTests.cs
├── Reflection
│ ├── EnumerableWriterFactoryTests.cs
│ ├── DictionaryWriterFactoryTests.cs
│ ├── ObjectWriterFactoryTests.cs
│ └── TypeActivatorTests.cs
├── TestHelpers.cs
├── Vertical.SpectreLogger.Tests.csproj
├── Output
│ ├── BackgroundConsoleWriterTests.cs
│ └── ActualConsoleWriterTests.cs
├── Templates
│ └── TemplatePatternBuilderTests.cs
└── Threading
│ └── MultiThreadedLoggingTests.cs
├── assets
├── cap1.png
├── cap2.png
├── cap3.png
├── icon.ai
├── icon.png
└── vertical-software.snk
├── bug-repro
├── Directory.Build.props
├── MultiThreaded
│ ├── MultiThreaded.csproj
│ └── Program.cs
├── Destructuring
│ ├── Destructuring.csproj
│ ├── Model.cs
│ └── Program.cs
└── solution.sln
├── src
├── Reflection
│ ├── CompiledWriter.cs
│ ├── CompiledWriterFactory.cs
│ └── ObjectWriterFactory.cs
├── Templates
│ ├── TemplateCallback.cs
│ ├── ITemplateRendererBuilder.cs
│ ├── TemplateString.cs
│ ├── TemplateDescriptor.cs
│ └── TemplateRendererBuilder.cs
├── Core
│ ├── LogEventFilterDelegate.cs
│ ├── IRendererPipeline.cs
│ ├── IScopeValues.cs
│ ├── ILogEventFilter.cs
│ ├── ITemplateRenderer.cs
│ └── LogEventContext.cs
├── Destructuring
│ ├── DestructuredKeyValue.cs
│ ├── CompiledWriterCache.cs
│ └── IDestructuringWriter.cs
├── Scopes
│ ├── ScopeValues.cs
│ ├── SingleScopeValue.cs
│ ├── EmptyScopeValues.cs
│ ├── MultiScopeValues.cs
│ ├── LoggerScope.cs
│ └── ScopeManager.cs
├── Rendering
│ ├── NewLineRenderer.cs
│ ├── StaticSpanRenderer.cs
│ ├── MessageRenderer.cs
│ ├── ActivityIdRenderer.cs
│ ├── CategoryNameRenderer.cs
│ ├── MarginControlRenderer.cs
│ ├── ExceptionRenderer.Options.cs
│ ├── LogLevelRenderer.cs
│ ├── ProcessIdRenderer.cs
│ ├── ThreadIdRenderer.cs
│ ├── ScopeValuesRenderer.cs
│ ├── DateTimeRenderer.cs
│ ├── RendererPipeline.cs
│ ├── ExceptionRenderer.Formatting.cs
│ └── CategoryNameRenderer.Formatting.cs
├── Output
│ ├── IConsoleWriter.cs
│ ├── ForegroundConsoleWriter.cs
│ ├── ConsoleWriter.cs
│ ├── IWriteBuffer.cs
│ ├── BackgroundConsoleWriter.cs
│ └── WriteBuffer.cs
├── Internal
│ ├── DelegateLogEventFilter.cs
│ ├── SpectreLoggerOptionsExtensions.cs
│ ├── WriteBufferPooledObjectPolicy.cs
│ ├── TypeNameFormatter.cs
│ └── CollectionExtensions.cs
├── Properties
│ └── AssemblyInfo.cs
├── Formatting
│ ├── NullValue.cs
│ ├── ValueFormatter.cs
│ ├── MultiTypeFormatProvider.cs
│ ├── TypeFormatterAttribute.cs
│ ├── ProviderFormatter.cs
│ ├── MultiTypeFormatter.cs
│ └── ValueWrapper.cs
├── Options
│ ├── DestructuringOptions.cs
│ ├── MicrosoftStyleLoggerOptions.cs
│ ├── OptionsCollection.cs
│ ├── SpectreLoggerOptions.cs
│ └── LogLevelProfile.cs
├── SpectreLoggerProvider.cs
├── LoggingBuilderExtensions.cs
├── SpectreLogger.cs
└── Vertical.SpectreLogger.csproj
├── examples
├── Exceptions
│ └── Exceptions.csproj
├── Scopes
│ └── Scopes.csproj
├── OutOfBoxStyles
│ └── OutOfBoxStyles.csproj
├── DestructuredValues
│ ├── DestructuredValues.csproj
│ └── Program.cs
├── Directory.Build.props
├── Formatting
│ ├── Formatting.csproj
│ └── Program.cs
├── CustomRenderer
│ ├── CustomRenderer.csproj
│ ├── Program.cs
│ ├── IncrementingIdRenderer.cs
│ └── IncrementingId.cs
└── MinimumLevelOverrides
│ ├── MinimumLevelOverrides.csproj
│ └── Program.cs
├── docs
├── log-level.md
├── newline.md
├── extending.md
├── thread-id.md
├── process-id.md
├── activity-id.md
├── message.md
├── scope-value.md
├── advanced-config.md
├── date-time.md
├── category-name.md
├── margin-control.md
├── scope-values.md
├── docs-home.md
├── styling.md
├── destructuring.md
└── output-template.md
├── install-local.sh
├── .github
└── workflows
│ ├── release.yml
│ ├── dev-build.yml
│ ├── pre-release.yml
│ └── dev-build-windows.yml
├── LICENSE
└── README.md
/test/.gitignore:
--------------------------------------------------------------------------------
1 | *.received.txt
2 |
--------------------------------------------------------------------------------
/assets/cap1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/verticalsoftware/vertical-spectreconsolelogger/HEAD/assets/cap1.png
--------------------------------------------------------------------------------
/assets/cap2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/verticalsoftware/vertical-spectreconsolelogger/HEAD/assets/cap2.png
--------------------------------------------------------------------------------
/assets/cap3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/verticalsoftware/vertical-spectreconsolelogger/HEAD/assets/cap3.png
--------------------------------------------------------------------------------
/assets/icon.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/verticalsoftware/vertical-spectreconsolelogger/HEAD/assets/icon.ai
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/verticalsoftware/vertical-spectreconsolelogger/HEAD/assets/icon.png
--------------------------------------------------------------------------------
/assets/vertical-software.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/verticalsoftware/vertical-spectreconsolelogger/HEAD/assets/vertical-software.snk
--------------------------------------------------------------------------------
/test/Rendering/Verified/MarginControlRendererTests.RenderWritesExpectedOutputForAdjust.DotNet.verified.txt:
--------------------------------------------------------------------------------
1 | Indent-0
2 | Indent+2
3 | Indent-0
--------------------------------------------------------------------------------
/test/Rendering/Verified/MarginControlRendererTests.RenderWritesExpectedOutputForSet.DotNet.verified.txt:
--------------------------------------------------------------------------------
1 | Indent-0
2 | Indent-5
3 | Indent-0
--------------------------------------------------------------------------------
/bug-repro/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/test/Destructuring/DestructuringWriterTests.WriteObjectRendersExpectedContent.verified.txt:
--------------------------------------------------------------------------------
1 | {FirstName: Testy, LastName: McTesterson, Address: {Street: 123 Main Street, City: Denver, State: CO}}
--------------------------------------------------------------------------------
/test/Destructuring/DestructuringWriterTests.WriteDictionaryRendersExpectedContent.verified.txt:
--------------------------------------------------------------------------------
1 | {firstName: Testy, lastName: McTesterson, address: {street: 123 Main Street, city: Denver, state: CO}}
--------------------------------------------------------------------------------
/src/Reflection/CompiledWriter.cs:
--------------------------------------------------------------------------------
1 | using Vertical.SpectreLogger.Destructuring;
2 |
3 | namespace Vertical.SpectreLogger.Reflection
4 | {
5 | internal delegate void CompiledWriter(IDestructuringWriter writer, object? value);
6 | }
--------------------------------------------------------------------------------
/test/Destructuring/DestructuringWriterTests.WriteDictionaryRespectsMaxDepth.verified.txt:
--------------------------------------------------------------------------------
1 | {Name: Testy, Children: [[{Name: Testy Jr., Children: [[{Name: Testy III, Children: Vertical.SpectreLogger.Tests.Infrastructure.Person[[]]}]]}]]}
--------------------------------------------------------------------------------
/examples/Exceptions/Exceptions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | $(ExamplesRuntime)
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/examples/Scopes/Scopes.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | $(ExamplesRuntime)
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/examples/OutOfBoxStyles/OutOfBoxStyles.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | $(ExamplesRuntime)
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/examples/DestructuredValues/DestructuredValues.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | $(ExamplesRuntime)
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/examples/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | net6.0
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/Formatting/Formatting.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | $(ExamplesRuntime)
6 | enable
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/examples/CustomRenderer/CustomRenderer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | $(ExamplesRuntime)
6 | enable
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/Templates/TemplateCallback.cs:
--------------------------------------------------------------------------------
1 | namespace Vertical.SpectreLogger.Templates
2 | {
3 | ///
4 | /// Defines a delegate that receives template segments during split operations.
5 | ///
6 | public delegate void TemplateCallback(in TemplateSegment segment);
7 | }
--------------------------------------------------------------------------------
/bug-repro/MultiThreaded/MultiThreaded.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net7.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/bug-repro/Destructuring/Destructuring.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/examples/MinimumLevelOverrides/MinimumLevelOverrides.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/Core/LogEventFilterDelegate.cs:
--------------------------------------------------------------------------------
1 | namespace Vertical.SpectreLogger.Core
2 | {
3 | ///
4 | /// Defines a delegate that receives log event data and returns a boolean
5 | /// indicating whether or not the event should be filtered from the output.
6 | ///
7 | public delegate bool LogEventFilterDelegate(in LogEventContext context);
8 | }
--------------------------------------------------------------------------------
/test/Destructuring/DestructuringWriterTests.WriteObjectIndented.verified.txt:
--------------------------------------------------------------------------------
1 | {
2 | Id: 5e093875-2c3f-4d28-9718-1339aa03f9ca,
3 | FirstName: Testy,
4 | LastName: McTesterson,
5 | Address: {
6 | Street: 6715 W Colfax Ave,
7 | City: Lakewood,
8 | State: CO,
9 | ZipCode: 80214
10 | },
11 | Roles: [[
12 | Manager,
13 | Cook
14 | ]]
15 | }
--------------------------------------------------------------------------------
/test/Formatting/NullValueTests.cs:
--------------------------------------------------------------------------------
1 | using Shouldly;
2 | using Vertical.SpectreLogger.Formatting;
3 | using Xunit;
4 |
5 | namespace Vertical.SpectreLogger.Tests.Formatting
6 | {
7 | public class NullValueTests
8 | {
9 | [Fact]
10 | public void FormatReturnsExpectedConstant()
11 | {
12 | NullValue.Default.ToString(null, null).ShouldBe("(null)");
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/Core/IRendererPipeline.cs:
--------------------------------------------------------------------------------
1 | namespace Vertical.SpectreLogger.Core
2 | {
3 | ///
4 | /// Defines a renderer pipeline.
5 | ///
6 | public interface IRendererPipeline
7 | {
8 | ///
9 | /// Renders the log event.
10 | ///
11 | /// Log event info
12 | void Render(in LogEventContext logEventContext);
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Destructuring/DestructuredKeyValue.cs:
--------------------------------------------------------------------------------
1 | using Vertical.SpectreLogger.Formatting;
2 |
3 | namespace Vertical.SpectreLogger.Destructuring
4 | {
5 | ///
6 | /// Wraps the key of a destructured value.
7 | ///
8 | public class DestructuredKeyValue : ValueWrapper
9 | {
10 | ///
11 | public DestructuredKeyValue(string key) : base(key)
12 | {
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/test/Infrastructure/Factory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace Vertical.SpectreLogger.Tests.Infrastructure
6 | {
7 | public static class Factory
8 | {
9 | public static T New(Func function) => function();
10 |
11 | public static IEnumerable New(Func function, int count) =>
12 | Enumerable.Range(0, count).Select(_ => function());
13 | }
14 | }
--------------------------------------------------------------------------------
/docs/log-level.md:
--------------------------------------------------------------------------------
1 | # Log Level Renderer
2 |
3 | ## Overview
4 |
5 | Prints the log level of the current event.
6 |
7 | ### Placeholder Syntax
8 |
9 | ```
10 | {LogLevel[,alignment]}
11 | ```
12 |
13 | ### Emitted Types
14 |
15 | The following type(s) can be formatted & styled:
16 |
17 | |Type|Description|
18 | |---|---|
19 | |`Microsoft.Extensions.Logging.LogLevel`|The event severity|
20 |
21 | ## See Also
22 | - [Next: Margin Control](./margin-control.md)
23 | - [Rendering Overview](./renderer-overview.md)
--------------------------------------------------------------------------------
/src/Scopes/ScopeValues.cs:
--------------------------------------------------------------------------------
1 | using Vertical.SpectreLogger.Core;
2 |
3 | namespace Vertical.SpectreLogger.Scopes
4 | {
5 | internal static class ScopeValues
6 | {
7 | internal static IScopeValues Create(LoggerScope? scope)
8 | {
9 | return scope switch
10 | {
11 | {PreviousScope: { }} => new MultiScopeValues(scope),
12 | { } => new SingleScopeValue(scope),
13 | _ => EmptyScopeValues.Default
14 | };
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/Rendering/NewLineRenderer.cs:
--------------------------------------------------------------------------------
1 | using Vertical.SpectreLogger.Core;
2 | using Vertical.SpectreLogger.Output;
3 | using Vertical.SpectreLogger.Templates;
4 |
5 | namespace Vertical.SpectreLogger.Rendering
6 | {
7 | ///
8 | /// Renders a new line.
9 | ///
10 | [Template("{NewLine}")]
11 | public class NewLineRenderer : ITemplateRenderer
12 | {
13 | ///
14 | public void Render(IWriteBuffer buffer, in LogEventContext context) => buffer.WriteLine();
15 | }
16 | }
--------------------------------------------------------------------------------
/test/Infrastructure/Person.cs:
--------------------------------------------------------------------------------
1 | namespace Vertical.SpectreLogger.Tests.Infrastructure
2 | {
3 | public class Person
4 | {
5 | public Person(string name, Person[] children)
6 | {
7 | Name = name;
8 | Children = children;
9 | }
10 |
11 | public string Name { get; }
12 |
13 | public Person[] Children { get; }
14 |
15 | ///
16 | public override string ToString() => $"{Name}, Children={Children?.Length}";
17 | }
18 | }
--------------------------------------------------------------------------------
/test/DependencyInjectionTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using Shouldly;
3 | using Xunit;
4 |
5 | namespace Vertical.SpectreLogger.Tests
6 | {
7 | public class DependencyInjectionTests
8 | {
9 | [Fact]
10 | public void ServicesAndDependenciesCreated()
11 | {
12 | var factory = LoggerFactory.Create(builder => builder.AddSpectreConsole());
13 |
14 | var logger = factory.CreateLogger();
15 |
16 | logger.ShouldNotBeNull();
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/bug-repro/Destructuring/Model.cs:
--------------------------------------------------------------------------------
1 | namespace Destructuring;
2 |
3 | public record Model(
4 | Guid MigrationId,
5 | string DbVersion,
6 | DateTime DateApplied,
7 | Guid LogId,
8 | string SourcePath,
9 | string SourceFile,
10 | string Sha,
11 | string Agent,
12 | string Host,
13 | IDictionary Metrics,
14 | IDictionary OperationTags,
15 | IDictionary Metadata)
16 | {
17 | ///
18 | public override string ToString() => $"{MigrationId} (version={DbVersion})";
19 | }
--------------------------------------------------------------------------------
/src/Core/IScopeValues.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace Vertical.SpectreLogger.Core
4 | {
5 | ///
6 | /// Provides access to scope values.
7 | ///
8 | public interface IScopeValues
9 | {
10 | ///
11 | /// Gets whether the collection has any values.
12 | ///
13 | bool HasValues { get; }
14 |
15 | ///
16 | /// Gets the items in the collection;
17 | ///
18 | IReadOnlyList