From dfc1208321a91c5d8d31445c1cef50c54a973e8c Mon Sep 17 00:00:00 2001 From: Lowell Manners Date: Wed, 2 Sep 2020 10:44:44 +0200 Subject: [PATCH 1/8] Add ILogEvent.LogKeyValue(...) methods for logging structured log data. --- src/ZeroLog.Tests/LogEventTests.EdgeCases.cs | 16 +- src/ZeroLog.Tests/LogEventTests.KeyValues.cs | 158 ++++++++ src/ZeroLog/ArgumentType.cs | 1 + src/ZeroLog/ForwardingLogEvent.cs | 1 + src/ZeroLog/ILogEvent.cs | 2 + src/ZeroLog/LogEvent.Append.cs | 360 +++++++++++++++++++ src/ZeroLog/LogEvent.Append.tt | 30 ++ src/ZeroLog/LogEvent.cs | 192 +++++++++- src/ZeroLog/NoopLogEvent.cs | 1 + 9 files changed, 759 insertions(+), 2 deletions(-) create mode 100644 src/ZeroLog.Tests/LogEventTests.KeyValues.cs diff --git a/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs b/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs index 5806071b..a17162ec 100644 --- a/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs +++ b/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs @@ -40,7 +40,9 @@ public void should_truncate_ascii_string_if_buffer_is_not_large_enough() } [Test] - public void should_ignore_ascii_string_if_buffer_is_not_large_enough_for_header([Range(_bufferSize - 2 * _asciiHeaderSize, _bufferSize)] int firstStringLength) + public void should_ignore_ascii_string_if_buffer_is_not_large_enough_for_header( + [Range(_bufferSize - 2 * _asciiHeaderSize, _bufferSize)] + int firstStringLength) { var largeString1 = new string('a', firstStringLength); var asciiBytes1 = Encoding.ASCII.GetBytes(largeString1); @@ -212,6 +214,18 @@ public void should_ignore_append_time_span_if_buffer_is_full() Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } + [Test] + public void should_ignore_append_key_values_if_buffer_is_full() + { + FillBufferWithWhiteSpaces(); + _logEvent.AppendKeyValue("key1", (string)null) + .AppendKeyValue("key2", "val2") + .AppendKeyValue("key3", 3); + _logEvent.WriteToStringBuffer(_output); + + Check.That(string.IsNullOrWhiteSpace(_output.ToString())); + } + private void FillBufferWithWhiteSpaces() { var largeString = new string(' ', _bufferSize); diff --git a/src/ZeroLog.Tests/LogEventTests.KeyValues.cs b/src/ZeroLog.Tests/LogEventTests.KeyValues.cs new file mode 100644 index 00000000..c6f17686 --- /dev/null +++ b/src/ZeroLog.Tests/LogEventTests.KeyValues.cs @@ -0,0 +1,158 @@ +using System; +using NUnit.Framework; + +namespace ZeroLog.Tests +{ + public partial class LogEventTests + { + [Test] + public void should_append_single_key_value() + { + _logEvent.AppendKeyValue("myKey", "myValue"); + _logEvent.WriteToStringBuffer(_output); + + Assert.AreEqual(" ~~ { \"myKey\": \"myValue\" }", _output.ToString()); + } + + [Test] + public void should_append_multiple_key_values() + { + _logEvent.AppendKeyValue("myKey", "myValue"); + _logEvent.AppendKeyValue("otherKey", 2); + _logEvent.WriteToStringBuffer(_output); + + Assert.AreEqual(" ~~ { \"myKey\": \"myValue\", \"otherKey\": 2 }", _output.ToString()); + } + + [Test] + public void should_append_formatted_string_mixed_with_key_values() + { + // TODO(lmanners): There are more edge cases here. + _logEvent.AppendKeyValue("myKey", "myValue"); + _logEvent.AppendFormat("Some {} message"); + _logEvent.Append("formatted"); + _logEvent.AppendKeyValue("otherKey", 2); + _logEvent.WriteToStringBuffer(_output); + + Assert.AreEqual("Some formatted message ~~ { \"myKey\": \"myValue\", \"otherKey\": 2 }", _output.ToString()); + } + + [Test] + public void should_be_chainable() + { + _logEvent.AppendKeyValue("myKey", 1.1f).AppendKeyValue("otherKey", new Guid()); + _logEvent.Append("message"); + _logEvent.WriteToStringBuffer(_output); + + Assert.AreEqual("message ~~ { \"myKey\": 1.1, \"otherKey\": \"00000000-0000-0000-0000-000000000000\" }", _output.ToString()); + } + + [TestCase] + public void should_support_char() + { + _logEvent.AppendKeyValue("key1", 'a'); + _logEvent.WriteToStringBuffer(_output); + Assert.AreEqual(" ~~ { \"key1\": \"a\" }", _output.ToString()); + } + + [TestCase] + public void should_support_datetime() + { + _logEvent.AppendKeyValue("key1", DateTime.MinValue); + _logEvent.WriteToStringBuffer(_output); + Assert.AreEqual(" ~~ { \"key1\": \"0001-01-01 00:00:00.000\" }", _output.ToString()); + } + + [TestCase] + public void should_support_boolean() + { + _logEvent.AppendKeyValue("key1", true).AppendKeyValue("key2", false); + _logEvent.WriteToStringBuffer(_output); + Assert.AreEqual(" ~~ { \"key1\": \"true\", \"key2\": \"false\" }", _output.ToString()); + } + + [TestCase] + public void should_support_single_null_key_value() + { + _logEvent.AppendKeyValue("key1", (int?)null); + _logEvent.WriteToStringBuffer(_output); + Assert.AreEqual(" ~~ { \"key1\": \"null\" }", _output.ToString()); + } + + [TestCase] + public void should_support_null_string_key_value() + { + _logEvent.AppendKeyValue("key1", "val1") + .AppendKeyValue("key2", (string)null) + .AppendKeyValue("key3", 3); + _logEvent.WriteToStringBuffer(_output); + Assert.AreEqual(" ~~ { \"key1\": \"val1\", \"key2\": \"null\", \"key3\": 3 }", _output.ToString()); + } + + [TestCase] + public void should_support_number_types() + { + _logEvent.AppendKeyValue("byte", (byte)1) + .AppendKeyValue("short", (short)2) + .AppendKeyValue("int", 3) + .AppendKeyValue("long", 4L) + .AppendKeyValue("float", 5.5f) + .AppendKeyValue("double", 6.6d) + .AppendKeyValue("decimal", 6.6m); + + _logEvent.WriteToStringBuffer(_output); + Assert.AreEqual(" ~~ { \"byte\": 1, \"short\": 2, \"int\": 3, \"long\": 4, \"float\": 5.5, \"double\": 6.6, \"decimal\": 6.6 }", + _output.ToString()); + } + + [TestCase] + public void should_handle_truncated_key_values() + { + _logEvent.Initialize(Level.Info, null, LogEventArgumentExhaustionStrategy.TruncateMessage); + for (var i = 0; i < 6; i++) + { + _logEvent.AppendKeyValue($"key{i}", $"value{i}"); + } + + _logEvent.WriteToStringBuffer(_output); + Assert.AreEqual( + " ~~ { \"key0\": \"value0\", \"key1\": \"value1\", \"key2\": \"value2\", \"key3\": \"value3\", \"key4\": \"value4\" } [TRUNCATED]", + _output.ToString()); + } + + [TestCase] + public void should_allocate_space_for_more_key_values() + { + for (var i = 0; i < 6; i++) + { + _logEvent.AppendKeyValue($"key{i}", $"value{i}"); + } + + _logEvent.WriteToStringBuffer(_output); + Assert.AreEqual( + " ~~ { \"key0\": \"value0\", \"key1\": \"value1\", \"key2\": \"value2\", \"key3\": \"value3\", \"key4\": \"value4\", \"key5\": \"value5\" }", + _output.ToString()); + } + + [TestCase] + public void should_handle_partially_truncated_key_value() + { + _logEvent.Initialize(Level.Info, null, LogEventArgumentExhaustionStrategy.TruncateMessage); + + // This value 'consumes' one slot in the buffer. This will cause us to be out of space when appending the value for key4. + _logEvent.Append("msg"); + + for (var i = 0; i < 5; i++) + { + _logEvent.AppendKeyValue($"key{i}", $"value{i}"); + } + + _logEvent.WriteToStringBuffer(_output); + + // 'key4' is not present because there wasn't space for its value. + Assert.AreEqual( + "msg ~~ { \"key0\": \"value0\", \"key1\": \"value1\", \"key2\": \"value2\", \"key3\": \"value3\" } [TRUNCATED]", + _output.ToString()); + } + } +} diff --git a/src/ZeroLog/ArgumentType.cs b/src/ZeroLog/ArgumentType.cs index e2c23942..778836c0 100644 --- a/src/ZeroLog/ArgumentType.cs +++ b/src/ZeroLog/ArgumentType.cs @@ -20,5 +20,6 @@ internal enum ArgumentType : byte Enum, Null, Unmanaged, + KeyString, } } diff --git a/src/ZeroLog/ForwardingLogEvent.cs b/src/ZeroLog/ForwardingLogEvent.cs index 3dd5fbd4..e8f04616 100644 --- a/src/ZeroLog/ForwardingLogEvent.cs +++ b/src/ZeroLog/ForwardingLogEvent.cs @@ -39,6 +39,7 @@ public void AppendGeneric(T arg) public unsafe ILogEvent AppendAsciiString(byte* bytes, int length) => this; public ILogEvent AppendAsciiString(ReadOnlySpan bytes) => this; public ILogEvent AppendAsciiString(ReadOnlySpan chars) => this; + public ILogEvent AppendKeyValue(string key, string? value) => this; public ILogEvent AppendEnum(T value) where T : struct, Enum diff --git a/src/ZeroLog/ILogEvent.cs b/src/ZeroLog/ILogEvent.cs index 13f03f56..f37e832e 100644 --- a/src/ZeroLog/ILogEvent.cs +++ b/src/ZeroLog/ILogEvent.cs @@ -19,6 +19,8 @@ ILogEvent AppendEnum(T value) ILogEvent AppendEnum(T? value) where T : struct, Enum; + ILogEvent AppendKeyValue(string key, string? value); + void Log(); } } diff --git a/src/ZeroLog/LogEvent.Append.cs b/src/ZeroLog/LogEvent.Append.cs index bed9a915..50fa2686 100644 --- a/src/ZeroLog/LogEvent.Append.cs +++ b/src/ZeroLog/LogEvent.Append.cs @@ -16,46 +16,70 @@ partial interface ILogEvent { ILogEvent Append(bool value); ILogEvent Append(bool? value); + ILogEvent AppendKeyValue(string key, bool value); + ILogEvent AppendKeyValue(string key, bool? value); ILogEvent Append(byte value); ILogEvent Append(byte? value); + ILogEvent AppendKeyValue(string key, byte value); + ILogEvent AppendKeyValue(string key, byte? value); ILogEvent Append(byte value, string format); ILogEvent Append(byte? value, string format); ILogEvent Append(char value); ILogEvent Append(char? value); + ILogEvent AppendKeyValue(string key, char value); + ILogEvent AppendKeyValue(string key, char? value); ILogEvent Append(short value); ILogEvent Append(short? value); + ILogEvent AppendKeyValue(string key, short value); + ILogEvent AppendKeyValue(string key, short? value); ILogEvent Append(short value, string format); ILogEvent Append(short? value, string format); ILogEvent Append(int value); ILogEvent Append(int? value); + ILogEvent AppendKeyValue(string key, int value); + ILogEvent AppendKeyValue(string key, int? value); ILogEvent Append(int value, string format); ILogEvent Append(int? value, string format); ILogEvent Append(long value); ILogEvent Append(long? value); + ILogEvent AppendKeyValue(string key, long value); + ILogEvent AppendKeyValue(string key, long? value); ILogEvent Append(long value, string format); ILogEvent Append(long? value, string format); ILogEvent Append(float value); ILogEvent Append(float? value); + ILogEvent AppendKeyValue(string key, float value); + ILogEvent AppendKeyValue(string key, float? value); ILogEvent Append(float value, string format); ILogEvent Append(float? value, string format); ILogEvent Append(double value); ILogEvent Append(double? value); + ILogEvent AppendKeyValue(string key, double value); + ILogEvent AppendKeyValue(string key, double? value); ILogEvent Append(double value, string format); ILogEvent Append(double? value, string format); ILogEvent Append(decimal value); ILogEvent Append(decimal? value); + ILogEvent AppendKeyValue(string key, decimal value); + ILogEvent AppendKeyValue(string key, decimal? value); ILogEvent Append(decimal value, string format); ILogEvent Append(decimal? value, string format); ILogEvent Append(Guid value); ILogEvent Append(Guid? value); + ILogEvent AppendKeyValue(string key, Guid value); + ILogEvent AppendKeyValue(string key, Guid? value); ILogEvent Append(Guid value, string format); ILogEvent Append(Guid? value, string format); ILogEvent Append(DateTime value); ILogEvent Append(DateTime? value); + ILogEvent AppendKeyValue(string key, DateTime value); + ILogEvent AppendKeyValue(string key, DateTime? value); ILogEvent Append(DateTime value, string format); ILogEvent Append(DateTime? value, string format); ILogEvent Append(TimeSpan value); ILogEvent Append(TimeSpan? value); + ILogEvent AppendKeyValue(string key, TimeSpan value); + ILogEvent AppendKeyValue(string key, TimeSpan? value); ILogEvent Append(TimeSpan value, string format); ILogEvent Append(TimeSpan? value, string format); } @@ -159,6 +183,30 @@ public ILogEvent Append(bool? value) return this; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, bool value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, bool? value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(byte value) { @@ -189,6 +237,30 @@ public ILogEvent Append(byte? value) return this; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, byte value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, byte? value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(byte value, string format) @@ -252,6 +324,30 @@ public ILogEvent Append(char? value) return this; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, char value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, char? value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(short value) { @@ -282,6 +378,30 @@ public ILogEvent Append(short? value) return this; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, short value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, short? value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(short value, string format) @@ -345,6 +465,30 @@ public ILogEvent Append(int? value) return this; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, int value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, int? value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(int value, string format) @@ -408,6 +552,30 @@ public ILogEvent Append(long? value) return this; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, long value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, long? value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(long value, string format) @@ -471,6 +639,30 @@ public ILogEvent Append(float? value) return this; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, float value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, float? value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(float value, string format) @@ -534,6 +726,30 @@ public ILogEvent Append(double? value) return this; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, double value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, double? value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(double value, string format) @@ -597,6 +813,30 @@ public ILogEvent Append(decimal? value) return this; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, decimal value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, decimal? value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(decimal value, string format) @@ -660,6 +900,30 @@ public ILogEvent Append(Guid? value) return this; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, Guid value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, Guid? value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(Guid value, string format) @@ -723,6 +987,30 @@ public ILogEvent Append(DateTime? value) return this; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, DateTime value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, DateTime? value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(DateTime value, string format) @@ -786,6 +1074,30 @@ public ILogEvent Append(TimeSpan? value) return this; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, TimeSpan value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, TimeSpan? value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(TimeSpan value, string format) @@ -825,46 +1137,70 @@ partial class NoopLogEvent { public ILogEvent Append(bool value) => this; public ILogEvent Append(bool? value) => this; + public ILogEvent AppendKeyValue(string key, bool value) => this; + public ILogEvent AppendKeyValue(string key, bool? value) => this; public ILogEvent Append(byte value) => this; public ILogEvent Append(byte? value) => this; + public ILogEvent AppendKeyValue(string key, byte value) => this; + public ILogEvent AppendKeyValue(string key, byte? value) => this; public ILogEvent Append(byte value, string format) => this; public ILogEvent Append(byte? value, string format) => this; public ILogEvent Append(char value) => this; public ILogEvent Append(char? value) => this; + public ILogEvent AppendKeyValue(string key, char value) => this; + public ILogEvent AppendKeyValue(string key, char? value) => this; public ILogEvent Append(short value) => this; public ILogEvent Append(short? value) => this; + public ILogEvent AppendKeyValue(string key, short value) => this; + public ILogEvent AppendKeyValue(string key, short? value) => this; public ILogEvent Append(short value, string format) => this; public ILogEvent Append(short? value, string format) => this; public ILogEvent Append(int value) => this; public ILogEvent Append(int? value) => this; + public ILogEvent AppendKeyValue(string key, int value) => this; + public ILogEvent AppendKeyValue(string key, int? value) => this; public ILogEvent Append(int value, string format) => this; public ILogEvent Append(int? value, string format) => this; public ILogEvent Append(long value) => this; public ILogEvent Append(long? value) => this; + public ILogEvent AppendKeyValue(string key, long value) => this; + public ILogEvent AppendKeyValue(string key, long? value) => this; public ILogEvent Append(long value, string format) => this; public ILogEvent Append(long? value, string format) => this; public ILogEvent Append(float value) => this; public ILogEvent Append(float? value) => this; + public ILogEvent AppendKeyValue(string key, float value) => this; + public ILogEvent AppendKeyValue(string key, float? value) => this; public ILogEvent Append(float value, string format) => this; public ILogEvent Append(float? value, string format) => this; public ILogEvent Append(double value) => this; public ILogEvent Append(double? value) => this; + public ILogEvent AppendKeyValue(string key, double value) => this; + public ILogEvent AppendKeyValue(string key, double? value) => this; public ILogEvent Append(double value, string format) => this; public ILogEvent Append(double? value, string format) => this; public ILogEvent Append(decimal value) => this; public ILogEvent Append(decimal? value) => this; + public ILogEvent AppendKeyValue(string key, decimal value) => this; + public ILogEvent AppendKeyValue(string key, decimal? value) => this; public ILogEvent Append(decimal value, string format) => this; public ILogEvent Append(decimal? value, string format) => this; public ILogEvent Append(Guid value) => this; public ILogEvent Append(Guid? value) => this; + public ILogEvent AppendKeyValue(string key, Guid value) => this; + public ILogEvent AppendKeyValue(string key, Guid? value) => this; public ILogEvent Append(Guid value, string format) => this; public ILogEvent Append(Guid? value, string format) => this; public ILogEvent Append(DateTime value) => this; public ILogEvent Append(DateTime? value) => this; + public ILogEvent AppendKeyValue(string key, DateTime value) => this; + public ILogEvent AppendKeyValue(string key, DateTime? value) => this; public ILogEvent Append(DateTime value, string format) => this; public ILogEvent Append(DateTime? value, string format) => this; public ILogEvent Append(TimeSpan value) => this; public ILogEvent Append(TimeSpan? value) => this; + public ILogEvent AppendKeyValue(string key, TimeSpan value) => this; + public ILogEvent AppendKeyValue(string key, TimeSpan? value) => this; public ILogEvent Append(TimeSpan value, string format) => this; public ILogEvent Append(TimeSpan? value, string format) => this; } @@ -873,46 +1209,70 @@ partial class ForwardingLogEvent { public ILogEvent Append(bool value) => this; public ILogEvent Append(bool? value) => this; + public ILogEvent AppendKeyValue(string key, bool value) => this; + public ILogEvent AppendKeyValue(string key, bool? value) => this; public ILogEvent Append(byte value) => this; public ILogEvent Append(byte? value) => this; + public ILogEvent AppendKeyValue(string key, byte value) => this; + public ILogEvent AppendKeyValue(string key, byte? value) => this; public ILogEvent Append(byte value, string format) => this; public ILogEvent Append(byte? value, string format) => this; public ILogEvent Append(char value) => this; public ILogEvent Append(char? value) => this; + public ILogEvent AppendKeyValue(string key, char value) => this; + public ILogEvent AppendKeyValue(string key, char? value) => this; public ILogEvent Append(short value) => this; public ILogEvent Append(short? value) => this; + public ILogEvent AppendKeyValue(string key, short value) => this; + public ILogEvent AppendKeyValue(string key, short? value) => this; public ILogEvent Append(short value, string format) => this; public ILogEvent Append(short? value, string format) => this; public ILogEvent Append(int value) => this; public ILogEvent Append(int? value) => this; + public ILogEvent AppendKeyValue(string key, int value) => this; + public ILogEvent AppendKeyValue(string key, int? value) => this; public ILogEvent Append(int value, string format) => this; public ILogEvent Append(int? value, string format) => this; public ILogEvent Append(long value) => this; public ILogEvent Append(long? value) => this; + public ILogEvent AppendKeyValue(string key, long value) => this; + public ILogEvent AppendKeyValue(string key, long? value) => this; public ILogEvent Append(long value, string format) => this; public ILogEvent Append(long? value, string format) => this; public ILogEvent Append(float value) => this; public ILogEvent Append(float? value) => this; + public ILogEvent AppendKeyValue(string key, float value) => this; + public ILogEvent AppendKeyValue(string key, float? value) => this; public ILogEvent Append(float value, string format) => this; public ILogEvent Append(float? value, string format) => this; public ILogEvent Append(double value) => this; public ILogEvent Append(double? value) => this; + public ILogEvent AppendKeyValue(string key, double value) => this; + public ILogEvent AppendKeyValue(string key, double? value) => this; public ILogEvent Append(double value, string format) => this; public ILogEvent Append(double? value, string format) => this; public ILogEvent Append(decimal value) => this; public ILogEvent Append(decimal? value) => this; + public ILogEvent AppendKeyValue(string key, decimal value) => this; + public ILogEvent AppendKeyValue(string key, decimal? value) => this; public ILogEvent Append(decimal value, string format) => this; public ILogEvent Append(decimal? value, string format) => this; public ILogEvent Append(Guid value) => this; public ILogEvent Append(Guid? value) => this; + public ILogEvent AppendKeyValue(string key, Guid value) => this; + public ILogEvent AppendKeyValue(string key, Guid? value) => this; public ILogEvent Append(Guid value, string format) => this; public ILogEvent Append(Guid? value, string format) => this; public ILogEvent Append(DateTime value) => this; public ILogEvent Append(DateTime? value) => this; + public ILogEvent AppendKeyValue(string key, DateTime value) => this; + public ILogEvent AppendKeyValue(string key, DateTime? value) => this; public ILogEvent Append(DateTime value, string format) => this; public ILogEvent Append(DateTime? value, string format) => this; public ILogEvent Append(TimeSpan value) => this; public ILogEvent Append(TimeSpan? value) => this; + public ILogEvent AppendKeyValue(string key, TimeSpan value) => this; + public ILogEvent AppendKeyValue(string key, TimeSpan? value) => this; public ILogEvent Append(TimeSpan value, string format) => this; public ILogEvent Append(TimeSpan? value, string format) => this; } diff --git a/src/ZeroLog/LogEvent.Append.tt b/src/ZeroLog/LogEvent.Append.tt index ecdfcfba..c905b188 100644 --- a/src/ZeroLog/LogEvent.Append.tt +++ b/src/ZeroLog/LogEvent.Append.tt @@ -43,6 +43,8 @@ namespace ZeroLog #> ILogEvent Append(<#= type.name #> value); ILogEvent Append(<#= type.name #>? value); + ILogEvent AppendKeyValue(string key, <#= type.name #> value); + ILogEvent AppendKeyValue(string key, <#= type.name #>? value); <# if (type.isFormattable) { @@ -121,6 +123,30 @@ namespace ZeroLog return this; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, <#= type.name #> value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, <#= type.name #>? value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + <# if (type.isFormattable) { @@ -172,6 +198,8 @@ namespace ZeroLog #> public ILogEvent Append(<#= type.name #> value) => this; public ILogEvent Append(<#= type.name #>? value) => this; + public ILogEvent AppendKeyValue(string key, <#= type.name #> value) => this; + public ILogEvent AppendKeyValue(string key, <#= type.name #>? value) => this; <# if (type.isFormattable) { @@ -192,6 +220,8 @@ namespace ZeroLog #> public ILogEvent Append(<#= type.name #> value) => this; public ILogEvent Append(<#= type.name #>? value) => this; + public ILogEvent AppendKeyValue(string key, <#= type.name #> value) => this; + public ILogEvent AppendKeyValue(string key, <#= type.name #>? value) => this; <# if (type.isFormattable) { diff --git a/src/ZeroLog/LogEvent.cs b/src/ZeroLog/LogEvent.cs index 4e5b12d6..3985943a 100644 --- a/src/ZeroLog/LogEvent.cs +++ b/src/ZeroLog/LogEvent.cs @@ -16,6 +16,7 @@ internal unsafe partial class LogEvent : IInternalLogEvent private const int _maxArgCapacity = byte.MaxValue; private string[] _strings; private IntPtr[] _argPointers; + private IntPtr[] _keyValuePointers; private Log _log; private LogEventArgumentExhaustionStrategy _argumentExhaustionStrategy; @@ -23,12 +24,16 @@ internal unsafe partial class LogEvent : IInternalLogEvent protected readonly byte* _endOfBuffer; protected byte* _dataPointer; private byte _argCount; + private byte _keyValueCount; private bool _isTruncated; public LogEvent(BufferSegment bufferSegment, int argCapacity) { argCapacity = Math.Min(argCapacity, _maxArgCapacity); _argPointers = new IntPtr[argCapacity]; + // Key value pairs consume two args, so we only can have x / 2 + 1 of them. The plus one is needed in case the last arg is a key + // because we ran out of _argPointers). + _keyValuePointers = new IntPtr[argCapacity / 2 + 1]; _strings = new string[argCapacity]; _startOfBuffer = bufferSegment.Data; @@ -50,6 +55,7 @@ public void Initialize(Level level, Log log, LogEventArgumentExhaustionStrategy Level = level; _log = log; _argCount = 0; + _keyValueCount = 0; _dataPointer = _startOfBuffer; _isTruncated = false; _argumentExhaustionStrategy = argumentExhaustionStrategy; @@ -95,6 +101,18 @@ public ILogEvent Append(string? s) return this; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILogEvent AppendKeyValue(string key, string? value) + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return Append(value); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendAsciiString(byte[]? bytes, int length) { @@ -284,15 +302,143 @@ public void WriteToStringBuffer(StringBuffer stringBuffer) while (dataPointer < endOfData) { - stringBuffer.Append(ref dataPointer, StringView.Empty, _strings, _argPointers, _argCount); + if (!ConsumeKeyValue(ref dataPointer, _keyValuePointers, ref _keyValueCount, endOfData)) + stringBuffer.Append(ref dataPointer, StringView.Empty, _strings, _argPointers, _argCount); } Debug.Assert(dataPointer == endOfData, "Buffer over-read"); + if (_keyValueCount > 0) + WriteJsonToStringBuffer(stringBuffer); + if (_isTruncated) stringBuffer.Append(LogManager.Config.TruncatedMessageSuffix); } + private static bool ConsumeKeyValue(ref byte* dataPointer, IntPtr[] keyValuePointers, ref byte keyValueCount, byte* endOfData) + { + var argumentType = (ArgumentType)(*dataPointer & ArgumentTypeMask.ArgumentType); + + if (argumentType != ArgumentType.KeyString) return false; + + // If the last item in the data is a key, that means there we ran out of space and couldn't include the value. + // In this case, skip the key, and don't use it to build JSON later. + if (dataPointer + sizeof(ArgumentType) + sizeof(byte) == endOfData) + { + SkipCurrentArgument(ref dataPointer); + return true; + } + + // Save a pointer to the key for later when we append the Key/Value JSON. + keyValuePointers[keyValueCount++] = new IntPtr(dataPointer); + + // Skip the key. + SkipCurrentArgument(ref dataPointer); + + // Skip the value. + SkipCurrentArgument(ref dataPointer); + + return true; + } + + private static void SkipCurrentArgument(ref byte* dataPointer) + { + var argumentType = (ArgumentType)(*dataPointer & ArgumentTypeMask.ArgumentType); + dataPointer += sizeof(ArgumentType); + switch (argumentType) + { + case ArgumentType.String: + case ArgumentType.KeyString: + case ArgumentType.Byte: + dataPointer += sizeof(byte); + break; + + case ArgumentType.AsciiString: + var length = *(int*)dataPointer; + dataPointer += sizeof(int) + length; + break; + + case ArgumentType.Boolean: + dataPointer += sizeof(bool); + break; + + case ArgumentType.Char: + dataPointer += sizeof(char); + break; + + case ArgumentType.Int16: + dataPointer += sizeof(short); + break; + + case ArgumentType.Int32: + dataPointer += sizeof(int); + break; + + case ArgumentType.Int64: + dataPointer += sizeof(long); + break; + + case ArgumentType.Single: + dataPointer += sizeof(float); + break; + + case ArgumentType.Double: + dataPointer += sizeof(double); + break; + + case ArgumentType.Decimal: + dataPointer += sizeof(decimal); + break; + + case ArgumentType.Guid: + dataPointer += sizeof(Guid); + break; + + case ArgumentType.DateTime: + dataPointer += sizeof(DateTime); + break; + + case ArgumentType.TimeSpan: + dataPointer += sizeof(TimeSpan); + break; + + case ArgumentType.Enum: + dataPointer += sizeof(EnumArg); + break; + + case ArgumentType.Null: + break; + case ArgumentType.FormatString: + case ArgumentType.Unmanaged: + throw new NotSupportedException($"Type is not supported {argumentType}"); + default: + throw new ArgumentOutOfRangeException(); + } + } + + private void WriteJsonToStringBuffer(StringBuffer stringBuffer) + { + stringBuffer.Append(" ~~ { "); + for (byte i = 0; i < _keyValueCount; i++) + { + var argPointer = (byte*)_keyValuePointers[i].ToPointer(); + var dataPointer = argPointer; + + // Key. + AppendJsonValue(stringBuffer, ref dataPointer); + + stringBuffer.Append(": "); + + // Value. + AppendJsonValue(stringBuffer, ref dataPointer); + + if (i != _keyValueCount - 1) + stringBuffer.Append(", "); + } + + stringBuffer.Append(" }"); + } + public void WriteToStringBufferUnformatted(StringBuffer stringBuffer) { var endOfData = _dataPointer; @@ -312,6 +458,44 @@ public void WriteToStringBufferUnformatted(StringBuffer stringBuffer) stringBuffer.Append(LogManager.Config.TruncatedMessageSuffix); } + private void AppendJsonValue(StringBuffer stringBuffer, ref byte* dataPointer) + { + var argument = *dataPointer; + dataPointer += sizeof(ArgumentType); + + var argumentType = (ArgumentType)(argument & ArgumentTypeMask.ArgumentType); + + switch (argumentType) + { + case ArgumentType.KeyString: + AppendUnformattedArgumentValue(stringBuffer, ArgumentType.String, ref dataPointer); + break; + case ArgumentType.Guid: + case ArgumentType.DateTime: + case ArgumentType.TimeSpan: + stringBuffer.Append('"'); + AppendUnformattedArgumentValue(stringBuffer, argumentType, ref dataPointer); + stringBuffer.Append('"'); + break; + case ArgumentType.Char: + stringBuffer.Append('"'); + stringBuffer.Append(*(char*)dataPointer); + stringBuffer.Append('"'); + dataPointer += sizeof(char); + break; + case ArgumentType.Boolean: + stringBuffer.Append(*(bool*)dataPointer ? "\"true\"" : "\"false\""); + dataPointer += sizeof(bool); + break; + case ArgumentType.Null: + stringBuffer.Append("\"null\""); + break; + default: + AppendUnformattedArgumentValue(stringBuffer, argumentType, ref dataPointer); + break; + } + } + private void AppendArgumentToStringBufferUnformatted(StringBuffer stringBuffer, ref byte* dataPointer) { var argument = *dataPointer; @@ -323,6 +507,11 @@ private void AppendArgumentToStringBufferUnformatted(StringBuffer stringBuffer, if (hasFormatSpecifier) dataPointer += sizeof(byte); // Skip it + AppendUnformattedArgumentValue(stringBuffer, argumentType, ref dataPointer); + } + + private void AppendUnformattedArgumentValue(StringBuffer stringBuffer, ArgumentType argumentType, ref byte* dataPointer) + { switch (argumentType) { case ArgumentType.String: @@ -449,6 +638,7 @@ private bool PrepareAppendSlow(int requestedBytes) { Array.Resize(ref _argPointers, newCapacity); Array.Resize(ref _strings, newCapacity); + Array.Resize(ref _keyValuePointers, newCapacity / 2 + 1); return true; } } diff --git a/src/ZeroLog/NoopLogEvent.cs b/src/ZeroLog/NoopLogEvent.cs index 5b483ba9..a7045fa5 100644 --- a/src/ZeroLog/NoopLogEvent.cs +++ b/src/ZeroLog/NoopLogEvent.cs @@ -35,6 +35,7 @@ public void AppendGeneric(T arg) public unsafe ILogEvent AppendAsciiString(byte* bytes, int length) => this; public ILogEvent AppendAsciiString(ReadOnlySpan bytes) => this; public ILogEvent AppendAsciiString(ReadOnlySpan chars) => this; + public ILogEvent AppendKeyValue(string key, string? value) => this; public ILogEvent AppendEnum(T value) where T : struct, Enum From aa51a6a68589d841eb322ba3b98f33bfe0100193 Mon Sep 17 00:00:00 2001 From: Lowell Manners Date: Sun, 4 Oct 2020 07:15:01 +0200 Subject: [PATCH 2/8] First round of improvements based on feedback. --- src/ZeroLog.Tests/LogEventTests.Append.cs | 78 ++--- .../LogEventTests.AppendWithFormat.cs | 24 +- src/ZeroLog.Tests/LogEventTests.EdgeCases.cs | 36 +- src/ZeroLog.Tests/LogEventTests.Enum.cs | 20 +- src/ZeroLog.Tests/LogEventTests.KeyValues.cs | 82 ++++- src/ZeroLog.Tests/LogEventTests.Unmanaged.cs | 48 +-- src/ZeroLog/Config/JsonConfigurator.cs | 5 + .../Config/ZeroLogJsonConfiguration.cs | 1 + src/ZeroLog/ForwardingLogEvent.cs | 3 +- src/ZeroLog/IInternalLogEvent.cs | 3 +- src/ZeroLog/JsonWriter.cs | 319 ++++++++++++++++++ src/ZeroLog/LogEvent.cs | 102 ++---- src/ZeroLog/LogManager.cs | 6 +- src/ZeroLog/NoopLogEvent.cs | 3 +- src/ZeroLog/ZeroLogConfig.cs | 12 +- 15 files changed, 535 insertions(+), 207 deletions(-) create mode 100644 src/ZeroLog/JsonWriter.cs diff --git a/src/ZeroLog.Tests/LogEventTests.Append.cs b/src/ZeroLog.Tests/LogEventTests.Append.cs index 967a0485..d9e99aa9 100644 --- a/src/ZeroLog.Tests/LogEventTests.Append.cs +++ b/src/ZeroLog.Tests/LogEventTests.Append.cs @@ -39,7 +39,7 @@ public void Teardown() public void should_append_string() { _logEvent.Append("abc"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("abc", _output.ToString()); } @@ -48,7 +48,7 @@ public void should_append_string() public void should_append_null_string() { _logEvent.Append((string)null); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); } @@ -58,7 +58,7 @@ public void should_append_byte_array() { var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes, bytes.Length); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("abc", _output.ToString()); } @@ -68,7 +68,7 @@ public void should_append_byte_span() { var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes.AsSpan()); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("abc", _output.ToString()); } @@ -77,7 +77,7 @@ public void should_append_byte_span() public void should_append_char_span() { _logEvent.AppendAsciiString("abc".AsSpan()); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("abc", _output.ToString()); } @@ -87,7 +87,7 @@ public void should_ignore_byte_array_with_negative_length() { var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes, -1); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("", _output.ToString()); } @@ -96,7 +96,7 @@ public void should_ignore_byte_array_with_negative_length() public void should_ignore_empty_byte_array() { _logEvent.AppendAsciiString(new byte[0], 0); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("", _output.ToString()); } @@ -105,7 +105,7 @@ public void should_ignore_empty_byte_array() public void should_ignore_empty_byte_span() { _logEvent.AppendAsciiString(ReadOnlySpan.Empty); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("", _output.ToString()); } @@ -114,7 +114,7 @@ public void should_ignore_empty_byte_span() public void should_ignore_empty_char_span() { _logEvent.AppendAsciiString(ReadOnlySpan.Empty); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("", _output.ToString()); } @@ -128,7 +128,7 @@ public void should_truncate_byte_array_after_too_many_args() var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes, bytes.Length); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -142,7 +142,7 @@ public void should_truncate_byte_span_after_too_many_args() var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes.AsSpan()); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -155,7 +155,7 @@ public void should_truncate_char_span_after_too_many_args() _logEvent.Append("."); _logEvent.AppendAsciiString("abc".AsSpan()); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -164,7 +164,7 @@ public void should_truncate_char_span_after_too_many_args() public void should_append_null_byte_array() { _logEvent.AppendAsciiString((byte[])null, 0); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); } @@ -178,7 +178,7 @@ public void should_append_unsafe_byte_array() _logEvent.AppendAsciiString(b, bytes.Length); } - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("abc", _output.ToString()); } @@ -197,7 +197,7 @@ public void should_truncate_unsafe_byte_array_after_too_many_args() _logEvent.AppendAsciiString(b, bytes.Length); } - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -206,7 +206,7 @@ public void should_truncate_unsafe_byte_array_after_too_many_args() public void should_append_null_unsafe_byte_array() { _logEvent.AppendAsciiString((byte*)null, 0); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); } @@ -215,7 +215,7 @@ public void should_append_null_unsafe_byte_array() public void should_append_true() { _logEvent.Append(true); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("True", _output.ToString()); } @@ -224,7 +224,7 @@ public void should_append_true() public void should_append_false() { _logEvent.Append(false); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("False", _output.ToString()); } @@ -233,7 +233,7 @@ public void should_append_false() public void should_append_byte() { _logEvent.Append((byte)255); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("255", _output.ToString()); } @@ -242,7 +242,7 @@ public void should_append_byte() public void should_append_char() { _logEvent.Append('€'); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("€", _output.ToString()); } @@ -251,7 +251,7 @@ public void should_append_char() public void should_append_short() { _logEvent.Append((short)4321); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("4321", _output.ToString()); } @@ -260,7 +260,7 @@ public void should_append_short() public void should_append_int() { _logEvent.Append(1234567890); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("1234567890", _output.ToString()); } @@ -269,7 +269,7 @@ public void should_append_int() public void should_append_long() { _logEvent.Append(1234567890123456789L); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("1234567890123456789", _output.ToString()); } @@ -278,7 +278,7 @@ public void should_append_long() public void should_append_float() { _logEvent.Append(0.123f); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("0.123", _output.ToString()); } @@ -287,7 +287,7 @@ public void should_append_float() public void should_append_double() { _logEvent.Append(0.123d); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("0.123", _output.ToString()); } @@ -296,7 +296,7 @@ public void should_append_double() public void should_append_decimal() { _logEvent.Append(792281625142643.37593543950335m); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("792281625142643.37593543950335", _output.ToString()); } @@ -305,7 +305,7 @@ public void should_append_decimal() public void should_append_guid() { _logEvent.Append(new Guid("129ac124-e588-47e5-9d3d-fa3a4d174e29")); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("129ac124-e588-47e5-9d3d-fa3a4d174e29", _output.ToString()); } @@ -314,7 +314,7 @@ public void should_append_guid() public void should_append_date_time() { _logEvent.Append(new DateTime(2017, 01, 12, 13, 14, 15)); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("2017-01-12 13:14:15.000", _output.ToString()); } @@ -323,7 +323,7 @@ public void should_append_date_time() public void should_append_time_span() { _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5)); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("1.02:03:04.0050000", _output.ToString()); } @@ -346,7 +346,7 @@ public void should_append_all_types() _logEvent.Append(new DateTime(2017, 01, 12, 13, 14, 15)); _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5)); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("AbCFalseTrue128£12345-128999999999999999999123.456789.012345.67890129ac124-e588-47e5-9d3d-fa3a4d174e292017-01-12 13:14:15.0001.02:03:04.0050000", _output.ToString()); } @@ -373,7 +373,7 @@ public void should_append_format() _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5)); _logEvent.AppendUnmanaged(new UnmanagedStruct() { A = 1, B = 2, C = 3 }); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("AbCFalseTrue128£12345-128999999999999999999123.456789.012345.67890129ac124-e588-47e5-9d3d-fa3a4d174e292017-01-12 13:14:15.0001.02:03:04.00500001-2-3", _output.ToString()); } @@ -390,7 +390,7 @@ public void should_append_format_multiple_times() _logEvent.Append(10); _logEvent.Append("foo"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("foo(bar42)[baz10]foo", _output.ToString()); } @@ -407,7 +407,7 @@ public void should_append_unmanaged_from_append_generic() C = 3 }); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -435,7 +435,7 @@ private void should_append_nullable() where T : struct { ((dynamic)_logEvent).Append((T?)null); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); @@ -443,7 +443,7 @@ private void should_append_nullable() _logEvent.Initialize(Level.Info, null, LogEventArgumentExhaustionStrategy.Default); ((dynamic)_logEvent).AppendGeneric((T?)null); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); @@ -451,7 +451,7 @@ private void should_append_nullable() _logEvent.Initialize(Level.Info, null, LogEventArgumentExhaustionStrategy.Default); ((dynamic)_logEvent).Append((T?)new T()); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreNotEqual("null", _output.ToString()); @@ -459,7 +459,7 @@ private void should_append_nullable() _logEvent.Initialize(Level.Info, null, LogEventArgumentExhaustionStrategy.Default); ((dynamic)_logEvent).AppendGeneric((T?)new T()); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreNotEqual("null", _output.ToString()); } @@ -473,7 +473,7 @@ public void should_truncate_log_message() _logEvent.Append("."); _logEvent.Append("!"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -487,7 +487,7 @@ public void should_not_truncate_log_message() _logEvent.Append("."); _logEvent.Append("!"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual(new string('.', _argCapacity * 2) + "!", _output.ToString()); } diff --git a/src/ZeroLog.Tests/LogEventTests.AppendWithFormat.cs b/src/ZeroLog.Tests/LogEventTests.AppendWithFormat.cs index f53b2d5a..73185b15 100644 --- a/src/ZeroLog.Tests/LogEventTests.AppendWithFormat.cs +++ b/src/ZeroLog.Tests/LogEventTests.AppendWithFormat.cs @@ -10,7 +10,7 @@ public partial class LogEventTests public void should_append_byte_with_format() { _logEvent.Append((byte)240, "X4"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("00F0", _output.ToString()); } @@ -19,7 +19,7 @@ public void should_append_byte_with_format() public void should_append_short_with_format() { _logEvent.Append((short)-23805, "X4"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("A303", _output.ToString()); } @@ -28,7 +28,7 @@ public void should_append_short_with_format() public void should_append_int_with_format() { _logEvent.Append(-16325, "X"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("FFFFC03B", _output.ToString()); } @@ -37,7 +37,7 @@ public void should_append_int_with_format() public void should_append_long_with_format() { _logEvent.Append(-16325L, "X"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("FFFFFFFFFFFFC03B", _output.ToString()); } @@ -46,7 +46,7 @@ public void should_append_long_with_format() public void should_append_float_with_format() { _logEvent.Append(1054.32179F, "E"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("1.054322E+003", _output.ToString()); } @@ -55,7 +55,7 @@ public void should_append_float_with_format() public void should_append_double_with_format() { _logEvent.Append(1054.32179d, "P3"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("105,432.179 %", _output.ToString()); } @@ -64,7 +64,7 @@ public void should_append_double_with_format() public void should_append_decimal_with_format() { _logEvent.Append(16325.62m, "E04"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("1.6326E+004", _output.ToString()); } @@ -73,7 +73,7 @@ public void should_append_decimal_with_format() public void should_append_guid_with_format() { _logEvent.Append(new Guid("129ac124-e588-47e5-9d3d-fa3a4d174e29"), "X"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("{0x129ac124,0xe588,0x47e5,{0x9d,0x3d,0xfa,0x3a,0x4d,0x17,0x4e,0x29}}", _output.ToString()); } @@ -82,7 +82,7 @@ public void should_append_guid_with_format() public void should_append_date_time_with_format() { _logEvent.Append(new DateTime(2017, 01, 12, 13, 14, 15), "yyyy-MM-dd"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("2017-01-12", _output.ToString()); } @@ -91,7 +91,7 @@ public void should_append_date_time_with_format() public void should_append_time_span_with_format() { _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5), "g"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.IsNotEmpty(_output.ToString()); @@ -119,7 +119,7 @@ private void should_append_nullable_with_format(string format) where T : struct { ((dynamic)_logEvent).Append((T?)new T(), format); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreNotEqual("null", _output.ToString()); @@ -127,7 +127,7 @@ private void should_append_nullable_with_format(string format) _logEvent.Initialize(Level.Info, null, LogEventArgumentExhaustionStrategy.Default); ((dynamic)_logEvent).Append((T?)null, format); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); } diff --git a/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs b/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs index a17162ec..b6b5d51e 100644 --- a/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs +++ b/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs @@ -34,7 +34,7 @@ public void should_truncate_ascii_string_if_buffer_is_not_large_enough() var asciiBytes = Encoding.ASCII.GetBytes(largeString); _logEvent.AppendAsciiString(asciiBytes, asciiBytes.Length); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(_output.ToString().Length).Equals(_bufferSize - _asciiHeaderSize + LogManager.Config.TruncatedMessageSuffix.Length); } @@ -52,7 +52,7 @@ public void should_ignore_ascii_string_if_buffer_is_not_large_enough_for_header( var asciiBytes2 = Encoding.ASCII.GetBytes(largeString2); _logEvent.AppendAsciiString(asciiBytes2, asciiBytes2.Length); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); var expectedTextLength = Math.Min(firstStringLength, _bufferSize - _asciiHeaderSize); Check.That(_output.ToString()).IsEqualTo(new string('a', expectedTextLength) + LogManager.Config.TruncatedMessageSuffix); @@ -69,7 +69,7 @@ public void should_truncate_raw_ascii_string_if_buffer_is_not_large_enough() _logEvent.AppendAsciiString(pAsciiBytes, asciiBytes.Length); } - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(_output.ToString().Length).Equals(_bufferSize - _asciiHeaderSize + LogManager.Config.TruncatedMessageSuffix.Length); } @@ -79,7 +79,7 @@ public void should_ignore_append_string_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append("abc"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -89,7 +89,7 @@ public void should_ignore_append_true_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(true); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -99,7 +99,7 @@ public void should_ignore_append_false_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(false); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -109,7 +109,7 @@ public void should_ignore_append_byte_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append((byte)255); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -119,7 +119,7 @@ public void should_ignore_append_char_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append('€'); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -129,7 +129,7 @@ public void should_ignore_append_short_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append((short)4321); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -139,7 +139,7 @@ public void should_ignore_append_int_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(1234567890); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -149,7 +149,7 @@ public void should_ignore_append_long_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(1234567890123456789L); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -159,7 +159,7 @@ public void should_ignore_append_float_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(0.123f); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -169,7 +169,7 @@ public void should_ignore_append_double_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(0.123d); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -179,7 +179,7 @@ public void should_ignore_append_decimal_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(792281625142643.37593543950335m); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -189,7 +189,7 @@ public void should_ignore_append_guid_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(new Guid("129ac124-e588-47e5-9d3d-fa3a4d174e29")); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -199,7 +199,7 @@ public void should_ignore_append_date_time_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(new DateTime(2017, 01, 12, 13, 14, 15)); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -209,7 +209,7 @@ public void should_ignore_append_time_span_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5)); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -221,7 +221,7 @@ public void should_ignore_append_key_values_if_buffer_is_full() _logEvent.AppendKeyValue("key1", (string)null) .AppendKeyValue("key2", "val2") .AppendKeyValue("key3", 3); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } diff --git a/src/ZeroLog.Tests/LogEventTests.Enum.cs b/src/ZeroLog.Tests/LogEventTests.Enum.cs index f0c189d3..de968153 100644 --- a/src/ZeroLog.Tests/LogEventTests.Enum.cs +++ b/src/ZeroLog.Tests/LogEventTests.Enum.cs @@ -12,7 +12,7 @@ public void should_append_enum() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendEnum(TestEnum.Bar); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("Bar", _output.ToString()); } @@ -23,7 +23,7 @@ public void should_append_nullable_enum() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendEnum((TestEnum?)TestEnum.Bar); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("Bar", _output.ToString()); } @@ -34,7 +34,7 @@ public void should_append_null_enum() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendEnum((TestEnum?)null); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); } @@ -45,7 +45,7 @@ public void should_append_enum_generic() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendGeneric(TestEnum.Baz); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("Baz", _output.ToString()); } @@ -56,7 +56,7 @@ public void should_append_nullable_enum_generic() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendGeneric((TestEnum?)TestEnum.Baz); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("Baz", _output.ToString()); } @@ -67,7 +67,7 @@ public void should_append_null_enum_generic() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendGeneric((TestEnum?)null); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); } @@ -77,7 +77,7 @@ public void should_append_null_enum_generic() public void should_append_unregistered_enum() { _logEvent.AppendEnum(UnregisteredEnum.Bar); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("1", _output.ToString()); } @@ -87,7 +87,7 @@ public void should_append_unregistered_enum() public void should_append_unregistered_enum_negative() { _logEvent.AppendEnum(UnregisteredEnum.Neg); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("-1", _output.ToString()); } @@ -97,7 +97,7 @@ public void should_append_unregistered_enum_negative() public void should_append_unregistered_enum_large() { _logEvent.AppendEnum(UnregisteredEnumLarge.LargeValue); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual(((ulong)UnregisteredEnumLarge.LargeValue).ToString(CultureInfo.InvariantCulture), _output.ToString()); } @@ -111,7 +111,7 @@ public void should_auto_register_enum() LogManager.Config.LazyRegisterEnums = true; _logEvent.AppendEnum(AutoRegisterEnum.Bar); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("Bar", _output.ToString()); } diff --git a/src/ZeroLog.Tests/LogEventTests.KeyValues.cs b/src/ZeroLog.Tests/LogEventTests.KeyValues.cs index c6f17686..2753fba9 100644 --- a/src/ZeroLog.Tests/LogEventTests.KeyValues.cs +++ b/src/ZeroLog.Tests/LogEventTests.KeyValues.cs @@ -9,7 +9,7 @@ public partial class LogEventTests public void should_append_single_key_value() { _logEvent.AppendKeyValue("myKey", "myValue"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual(" ~~ { \"myKey\": \"myValue\" }", _output.ToString()); } @@ -19,7 +19,7 @@ public void should_append_multiple_key_values() { _logEvent.AppendKeyValue("myKey", "myValue"); _logEvent.AppendKeyValue("otherKey", 2); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual(" ~~ { \"myKey\": \"myValue\", \"otherKey\": 2 }", _output.ToString()); } @@ -32,7 +32,7 @@ public void should_append_formatted_string_mixed_with_key_values() _logEvent.AppendFormat("Some {} message"); _logEvent.Append("formatted"); _logEvent.AppendKeyValue("otherKey", 2); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("Some formatted message ~~ { \"myKey\": \"myValue\", \"otherKey\": 2 }", _output.ToString()); } @@ -42,7 +42,7 @@ public void should_be_chainable() { _logEvent.AppendKeyValue("myKey", 1.1f).AppendKeyValue("otherKey", new Guid()); _logEvent.Append("message"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("message ~~ { \"myKey\": 1.1, \"otherKey\": \"00000000-0000-0000-0000-000000000000\" }", _output.ToString()); } @@ -51,7 +51,7 @@ public void should_be_chainable() public void should_support_char() { _logEvent.AppendKeyValue("key1", 'a'); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual(" ~~ { \"key1\": \"a\" }", _output.ToString()); } @@ -59,7 +59,7 @@ public void should_support_char() public void should_support_datetime() { _logEvent.AppendKeyValue("key1", DateTime.MinValue); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual(" ~~ { \"key1\": \"0001-01-01 00:00:00.000\" }", _output.ToString()); } @@ -67,16 +67,16 @@ public void should_support_datetime() public void should_support_boolean() { _logEvent.AppendKeyValue("key1", true).AppendKeyValue("key2", false); - _logEvent.WriteToStringBuffer(_output); - Assert.AreEqual(" ~~ { \"key1\": \"true\", \"key2\": \"false\" }", _output.ToString()); + _logEvent.WriteToStringBuffer(_output, null); + Assert.AreEqual(" ~~ { \"key1\": true, \"key2\": false }", _output.ToString()); } [TestCase] public void should_support_single_null_key_value() { _logEvent.AppendKeyValue("key1", (int?)null); - _logEvent.WriteToStringBuffer(_output); - Assert.AreEqual(" ~~ { \"key1\": \"null\" }", _output.ToString()); + _logEvent.WriteToStringBuffer(_output, null); + Assert.AreEqual(" ~~ { \"key1\": null }", _output.ToString()); } [TestCase] @@ -85,8 +85,8 @@ public void should_support_null_string_key_value() _logEvent.AppendKeyValue("key1", "val1") .AppendKeyValue("key2", (string)null) .AppendKeyValue("key3", 3); - _logEvent.WriteToStringBuffer(_output); - Assert.AreEqual(" ~~ { \"key1\": \"val1\", \"key2\": \"null\", \"key3\": 3 }", _output.ToString()); + _logEvent.WriteToStringBuffer(_output, null); + Assert.AreEqual(" ~~ { \"key1\": \"val1\", \"key2\": null, \"key3\": 3 }", _output.ToString()); } [TestCase] @@ -100,7 +100,7 @@ public void should_support_number_types() .AppendKeyValue("double", 6.6d) .AppendKeyValue("decimal", 6.6m); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual(" ~~ { \"byte\": 1, \"short\": 2, \"int\": 3, \"long\": 4, \"float\": 5.5, \"double\": 6.6, \"decimal\": 6.6 }", _output.ToString()); } @@ -114,7 +114,7 @@ public void should_handle_truncated_key_values() _logEvent.AppendKeyValue($"key{i}", $"value{i}"); } - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual( " ~~ { \"key0\": \"value0\", \"key1\": \"value1\", \"key2\": \"value2\", \"key3\": \"value3\", \"key4\": \"value4\" } [TRUNCATED]", _output.ToString()); @@ -128,12 +128,54 @@ public void should_allocate_space_for_more_key_values() _logEvent.AppendKeyValue($"key{i}", $"value{i}"); } - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual( " ~~ { \"key0\": \"value0\", \"key1\": \"value1\", \"key2\": \"value2\", \"key3\": \"value3\", \"key4\": \"value4\", \"key5\": \"value5\" }", _output.ToString()); } + [TestCase('/', "\\/")] + [TestCase('"', "\\\"")] + [TestCase('\u0000', "\\u0000")] + [TestCase('\u0000', "\\u0000")] + [TestCase('\u0001', "\\u0001")] + [TestCase('\u0002', "\\u0002")] + [TestCase('\u0003', "\\u0003")] + [TestCase('\u0004', "\\u0004")] + [TestCase('\u0005', "\\u0005")] + [TestCase('\u0006', "\\u0006")] + [TestCase('\u0007', "\\u0007")] + [TestCase('\u0008', "\\b")] + [TestCase('\u0009', "\\t")] + [TestCase('\u000A', "\\n")] + [TestCase('\u000B', "\\u000B")] + [TestCase('\u000C', "\\f")] + [TestCase('\u000D', "\\r")] + [TestCase('\u000E', "\\u000E")] + [TestCase('\u000F', "\\u000F")] + [TestCase('\u0010', "\\u0010")] + [TestCase('\u0011', "\\u0011")] + [TestCase('\u0012', "\\u0012")] + [TestCase('\u0013', "\\u0013")] + [TestCase('\u0014', "\\u0014")] + [TestCase('\u0015', "\\u0015")] + [TestCase('\u0016', "\\u0016")] + [TestCase('\u0017', "\\u0017")] + [TestCase('\u0018', "\\u0018")] + [TestCase('\u0019', "\\u0019")] + [TestCase('\u001A', "\\u001A")] + [TestCase('\u001B', "\\u001B")] + [TestCase('\u001C', "\\u001C")] + [TestCase('\u001D', "\\u001D")] + [TestCase('\u001E', "\\u001E")] + [TestCase('\u001F', "\\u001F")] + public void should_handle_escaped_characters(char character, string expected) + { + _logEvent.AppendKeyValue("myKey", character); + _logEvent.WriteToStringBuffer(_output, null); + Assert.AreEqual(" ~~ { \"myKey\": \"" + expected + "\" }", _output.ToString()); + } + [TestCase] public void should_handle_partially_truncated_key_value() { @@ -147,12 +189,20 @@ public void should_handle_partially_truncated_key_value() _logEvent.AppendKeyValue($"key{i}", $"value{i}"); } - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); // 'key4' is not present because there wasn't space for its value. Assert.AreEqual( "msg ~~ { \"key0\": \"value0\", \"key1\": \"value1\", \"key2\": \"value2\", \"key3\": \"value3\" } [TRUNCATED]", _output.ToString()); } + + [TestCase] + public void should_escape_strings_for_json() + { + _logEvent.AppendKeyValue("key / \" \t \n", "Hello \u0001 \0 there"); + _logEvent.WriteToStringBuffer(_output, null); + Assert.AreEqual(" ~~ { \"key \\/ \\\" \\t \\n\": \"Hello \\u0001 \\u0000 there\" }", _output.ToString()); + } } } diff --git a/src/ZeroLog.Tests/LogEventTests.Unmanaged.cs b/src/ZeroLog.Tests/LogEventTests.Unmanaged.cs index 03a255df..475900f8 100644 --- a/src/ZeroLog.Tests/LogEventTests.Unmanaged.cs +++ b/src/ZeroLog.Tests/LogEventTests.Unmanaged.cs @@ -38,7 +38,7 @@ public void should_append_unmanaged() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -56,7 +56,7 @@ public void should_append_unmanaged_byref() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -74,7 +74,7 @@ public void should_append_nullable_unmanaged() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -87,7 +87,7 @@ public void should_append_null_nullable_unmanaged() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); } @@ -105,7 +105,7 @@ public void should_append_nullable_unmanaged_byref() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -118,7 +118,7 @@ public void should_append_null_nullable_unmanaged_byref() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); } @@ -152,7 +152,7 @@ public void should_append_unmanaged_2() LogManager.RegisterUnmanaged(typeof(UnmanagedStruct2)); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -188,7 +188,7 @@ public void should_append_external_unmanaged() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("External(1-2-3)", _output.ToString()); } @@ -206,7 +206,7 @@ public void should_append_external_unmanaged_byref() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("External(1-2-3)", _output.ToString()); } @@ -224,7 +224,7 @@ public void should_append_nullable_external_unmanaged() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("External(1-2-3)", _output.ToString()); } @@ -237,7 +237,7 @@ public void should_append_null_nullable_external_unmanaged() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); } @@ -255,7 +255,7 @@ public void should_append_nullable_external_unmanaged_byref() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("External(1-2-3)", _output.ToString()); } @@ -268,7 +268,7 @@ public void should_append_null_nullable_external_unmanaged_byref() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); } @@ -291,7 +291,7 @@ public void should_append_unregistered_unmanaged() }; _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("Unmanaged(0x01000000000000000200000003000000)", _output.ToString()); } @@ -307,7 +307,7 @@ public void should_append_unregistered_unmanaged_byref() }; _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("Unmanaged(0x01000000000000000200000003000000)", _output.ToString()); } @@ -323,7 +323,7 @@ public void should_append_unregistered_nullable_unmanaged() }; _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("Unmanaged(0x01000000000000000200000003000000)", _output.ToString()); } @@ -334,7 +334,7 @@ public void should_append_null_unregistered_nullable_unmanaged() UnregisteredUnmanagedStruct? o = null; _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); } @@ -350,7 +350,7 @@ public void should_append_unregistered_nullable_unmanaged_byref() }; _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("Unmanaged(0x01000000000000000200000003000000)", _output.ToString()); } @@ -361,7 +361,7 @@ public void should_append_null_unregistered_nullable_unmanaged_byref() UnregisteredUnmanagedStruct? o = null; _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); } @@ -394,7 +394,7 @@ public void should_append_unmanaged_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o, "foo"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("42[foo]", _output.ToString()); } @@ -410,7 +410,7 @@ public void should_append_unmanaged_byref_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o, "foo"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("42[foo]", _output.ToString()); } @@ -426,7 +426,7 @@ public void should_append_nullable_unmanaged_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o, "foo"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("42[foo]", _output.ToString()); } @@ -439,7 +439,7 @@ public void should_append_null_unmanaged_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o, "foo"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("null", _output.ToString()); } @@ -455,7 +455,7 @@ public void should_append_nullable_unmanaged_byref_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o, "foo"); - _logEvent.WriteToStringBuffer(_output); + _logEvent.WriteToStringBuffer(_output, null); Assert.AreEqual("42[foo]", _output.ToString()); } diff --git a/src/ZeroLog/Config/JsonConfigurator.cs b/src/ZeroLog/Config/JsonConfigurator.cs index 740c5cdb..9ef69ed7 100644 --- a/src/ZeroLog/Config/JsonConfigurator.cs +++ b/src/ZeroLog/Config/JsonConfigurator.cs @@ -52,6 +52,11 @@ private static void ConfigureGlobal(ZeroLogJsonConfiguration config) if (config.NullDisplayString != null) LogManager.Config.NullDisplayString = config.NullDisplayString; + + if (config.JsonSeparator != null) + { + LogManager.Config.JsonSeparator = config.JsonSeparator; + } } private static ZeroLogJsonConfiguration ConfigureResolver(string configFileFullPath, HierarchicalResolver resolver) diff --git a/src/ZeroLog/Config/ZeroLogJsonConfiguration.cs b/src/ZeroLog/Config/ZeroLogJsonConfiguration.cs index 8c252805..a32750f6 100644 --- a/src/ZeroLog/Config/ZeroLogJsonConfiguration.cs +++ b/src/ZeroLog/Config/ZeroLogJsonConfiguration.cs @@ -7,6 +7,7 @@ public class ZeroLogJsonConfiguration : IHierarchicalConfiguration public int LogEventArgumentCapacity { get; set; } public bool LazyRegisterEnums { get; set; } public string? NullDisplayString { get; set; } + public string? JsonSeparator { get; set; } public AppenderDefinition[] Appenders { get; set; } = new AppenderDefinition[0]; diff --git a/src/ZeroLog/ForwardingLogEvent.cs b/src/ZeroLog/ForwardingLogEvent.cs index e8f04616..725024fd 100644 --- a/src/ZeroLog/ForwardingLogEvent.cs +++ b/src/ZeroLog/ForwardingLogEvent.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Text.Formatting; using JetBrains.Annotations; using ZeroLog.Appenders; @@ -58,7 +59,7 @@ public void Log() _log.Enqueue(_logEventToAppend); } - public void WriteToStringBuffer(StringBuffer stringBuffer) + public void WriteToStringBuffer(StringBuffer stringBuffer, IList? keyValuePtrList) { } diff --git a/src/ZeroLog/IInternalLogEvent.cs b/src/ZeroLog/IInternalLogEvent.cs index 450657aa..11209daf 100644 --- a/src/ZeroLog/IInternalLogEvent.cs +++ b/src/ZeroLog/IInternalLogEvent.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Text.Formatting; namespace ZeroLog @@ -9,7 +10,7 @@ internal interface IInternalLogEvent : ILogEvent void SetTimestamp(DateTime timestamp); void AppendFormat(string format); void AppendGeneric(T arg); - void WriteToStringBuffer(StringBuffer stringBuffer); + void WriteToStringBuffer(StringBuffer stringBuffer, IList? keyValuePtrList = null); void WriteToStringBufferUnformatted(StringBuffer stringBuffer); bool IsPooled { get; } } diff --git a/src/ZeroLog/JsonWriter.cs b/src/ZeroLog/JsonWriter.cs new file mode 100644 index 00000000..b3c553e2 --- /dev/null +++ b/src/ZeroLog/JsonWriter.cs @@ -0,0 +1,319 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text.Formatting; + +namespace ZeroLog +{ + public static unsafe class JsonWriter + { + public static void WriteJsonToStringBuffer(StringBuffer stringBuffer, IList keyValuePointers, + string[] strings) + { + stringBuffer.Append(LogManager.Config.JsonSeparator); + stringBuffer.Append("{ "); + for (var i = 0; i < keyValuePointers.Count; i++) + { + var argPointer = (byte*)keyValuePointers[i].ToPointer(); + var dataPointer = argPointer; + + // Key. + AppendJsonValue(stringBuffer, strings, ref dataPointer); + + stringBuffer.Append(": "); + + // Value. + AppendJsonValue(stringBuffer, strings, ref dataPointer); + + if (i != keyValuePointers.Count - 1) + stringBuffer.Append(", "); + } + + stringBuffer.Append(" }"); + } + + private static void AppendJsonValue(StringBuffer stringBuffer, IReadOnlyList strings, ref byte* dataPointer) + { + var argument = *dataPointer; + dataPointer += sizeof(ArgumentType); + + var argumentType = (ArgumentType)(argument & ArgumentTypeMask.ArgumentType); + + switch (argumentType) + { + case ArgumentType.KeyString: + case ArgumentType.String: + stringBuffer.Append('"'); + if (NeedsEscaping(strings[*dataPointer])) + { + // This might be kind of slow, but should be relatively rare. + foreach (var c in strings[*dataPointer]) + { + AppendEscapedJson(c, stringBuffer); + } + } + else + { + // There is nothing to escape, we can append the entire string in one go. + stringBuffer.Append(strings[*dataPointer]); + } + + stringBuffer.Append('"'); + dataPointer += sizeof(byte); + break; + + case ArgumentType.AsciiString: + var length = *(int*)dataPointer; + dataPointer += sizeof(int); + stringBuffer.Append('"'); + stringBuffer.Append(new AsciiString(dataPointer, length)); + stringBuffer.Append('"'); + dataPointer += length; + break; + + case ArgumentType.Boolean: + stringBuffer.Append(*(bool*)dataPointer ? "true" : "false"); + dataPointer += sizeof(bool); + break; + + case ArgumentType.Byte: + stringBuffer.Append(*dataPointer, StringView.Empty); + dataPointer += sizeof(byte); + break; + + case ArgumentType.Char: + stringBuffer.Append('"'); + AppendEscapedJson(*(char*)dataPointer, stringBuffer); + stringBuffer.Append('"'); + + dataPointer += sizeof(char); + break; + + case ArgumentType.Int16: + stringBuffer.Append(*(short*)dataPointer, StringView.Empty); + dataPointer += sizeof(short); + break; + + case ArgumentType.Int32: + stringBuffer.Append(*(int*)dataPointer, StringView.Empty); + dataPointer += sizeof(int); + break; + + case ArgumentType.Int64: + stringBuffer.Append(*(long*)dataPointer, StringView.Empty); + dataPointer += sizeof(long); + break; + + case ArgumentType.Single: + stringBuffer.Append(*(float*)dataPointer, StringView.Empty); + dataPointer += sizeof(float); + break; + + case ArgumentType.Double: + stringBuffer.Append(*(double*)dataPointer, StringView.Empty); + dataPointer += sizeof(double); + break; + + case ArgumentType.Decimal: + stringBuffer.Append(*(decimal*)dataPointer, StringView.Empty); + dataPointer += sizeof(decimal); + break; + + case ArgumentType.Guid: + stringBuffer.Append('"'); + stringBuffer.Append(*(Guid*)dataPointer, StringView.Empty); + stringBuffer.Append('"'); + dataPointer += sizeof(Guid); + break; + + case ArgumentType.DateTime: + stringBuffer.Append('"'); + stringBuffer.Append(*(DateTime*)dataPointer, StringView.Empty); + stringBuffer.Append('"'); + dataPointer += sizeof(DateTime); + break; + + case ArgumentType.TimeSpan: + stringBuffer.Append('"'); + stringBuffer.Append(*(TimeSpan*)dataPointer, StringView.Empty); + stringBuffer.Append('"'); + dataPointer += sizeof(TimeSpan); + break; + + case ArgumentType.Enum: + var enumArg = (EnumArg*)dataPointer; + dataPointer += sizeof(EnumArg); + enumArg->AppendTo(stringBuffer); + break; + + case ArgumentType.Null: + stringBuffer.Append("null"); + break; + + default: + throw new ArgumentOutOfRangeException(); + } + } + + private static bool NeedsEscaping(string s) + { + // Not using linq here since it (might) add overhead. + foreach (var c in s) + { + if (c < '\u001F' || c == '"' || c == '/') + { + return true; + } + } + + return false; + } + + private static void AppendEscapedJson(char c, StringBuffer stringBuffer) + { + // Escape characters based on https://tools.ietf.org/html/rfc7159 + switch (c) + { + case '/': + stringBuffer.Append("\\/"); + break; + + case '"': + stringBuffer.Append("\\\""); + break; + + case '\u0000': + stringBuffer.Append("\\u0000"); + break; + + case '\u0001': + stringBuffer.Append("\\u0001"); + break; + + case '\u0002': + stringBuffer.Append("\\u0002"); + break; + + case '\u0003': + stringBuffer.Append("\\u0003"); + break; + + case '\u0004': + stringBuffer.Append("\\u0004"); + break; + + case '\u0005': + stringBuffer.Append("\\u0005"); + break; + + case '\u0006': + stringBuffer.Append("\\u0006"); + break; + + case '\u0007': + stringBuffer.Append("\\u0007"); + break; + + case '\u0008': + stringBuffer.Append("\\b"); + break; + + case '\u0009': + stringBuffer.Append("\\t"); + break; + + case '\u000A': + stringBuffer.Append("\\n"); + break; + + case '\u000B': + stringBuffer.Append("\\u000B"); + break; + + case '\u000C': + stringBuffer.Append("\\f"); + break; + + case '\u000D': + stringBuffer.Append("\\r"); + break; + + case '\u000E': + stringBuffer.Append("\\u000E"); + break; + + case '\u000F': + stringBuffer.Append("\\u000F"); + break; + + case '\u0010': + stringBuffer.Append("\\u0010"); + break; + + case '\u0011': + stringBuffer.Append("\\u0011"); + break; + + case '\u0012': + stringBuffer.Append("\\u0012"); + break; + + case '\u0013': + stringBuffer.Append("\\u0013"); + break; + + case '\u0014': + stringBuffer.Append("\\u0014"); + break; + + case '\u0015': + stringBuffer.Append("\\u0015"); + break; + + case '\u0016': + stringBuffer.Append("\\u0016"); + break; + + case '\u0017': + stringBuffer.Append("\\u0017"); + break; + + case '\u0018': + stringBuffer.Append("\\u0018"); + break; + + case '\u0019': + stringBuffer.Append("\\u0019"); + break; + + case '\u001A': + stringBuffer.Append("\\u001A"); + break; + + case '\u001B': + stringBuffer.Append("\\u001B"); + break; + + case '\u001C': + stringBuffer.Append("\\u001C"); + break; + + case '\u001D': + stringBuffer.Append("\\u001D"); + break; + + case '\u001E': + stringBuffer.Append("\\u001E"); + break; + + case '\u001F': + stringBuffer.Append("\\u001F"); + break; + + default: + stringBuffer.Append(c); + break; + } + } + } +} diff --git a/src/ZeroLog/LogEvent.cs b/src/ZeroLog/LogEvent.cs index 3985943a..60ec1922 100644 --- a/src/ZeroLog/LogEvent.cs +++ b/src/ZeroLog/LogEvent.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Linq; using System.Runtime.CompilerServices; using System.Text.Formatting; using System.Threading; @@ -16,7 +18,6 @@ internal unsafe partial class LogEvent : IInternalLogEvent private const int _maxArgCapacity = byte.MaxValue; private string[] _strings; private IntPtr[] _argPointers; - private IntPtr[] _keyValuePointers; private Log _log; private LogEventArgumentExhaustionStrategy _argumentExhaustionStrategy; @@ -24,16 +25,12 @@ internal unsafe partial class LogEvent : IInternalLogEvent protected readonly byte* _endOfBuffer; protected byte* _dataPointer; private byte _argCount; - private byte _keyValueCount; private bool _isTruncated; public LogEvent(BufferSegment bufferSegment, int argCapacity) { argCapacity = Math.Min(argCapacity, _maxArgCapacity); _argPointers = new IntPtr[argCapacity]; - // Key value pairs consume two args, so we only can have x / 2 + 1 of them. The plus one is needed in case the last arg is a key - // because we ran out of _argPointers). - _keyValuePointers = new IntPtr[argCapacity / 2 + 1]; _strings = new string[argCapacity]; _startOfBuffer = bufferSegment.Data; @@ -55,7 +52,6 @@ public void Initialize(Level level, Log log, LogEventArgumentExhaustionStrategy Level = level; _log = log; _argCount = 0; - _keyValueCount = 0; _dataPointer = _startOfBuffer; _isTruncated = false; _argumentExhaustionStrategy = argumentExhaustionStrategy; @@ -295,27 +291,36 @@ public void Log() _log.Enqueue(this); } - public void WriteToStringBuffer(StringBuffer stringBuffer) + public void WriteToStringBuffer(StringBuffer stringBuffer, IList? keyValuePointers) { + if (keyValuePointers == null) + { + keyValuePointers = new List(); + } + else + { + keyValuePointers.Clear(); + } + var endOfData = _dataPointer; var dataPointer = _startOfBuffer; while (dataPointer < endOfData) { - if (!ConsumeKeyValue(ref dataPointer, _keyValuePointers, ref _keyValueCount, endOfData)) + if (!ConsumeKeyValue(ref dataPointer, keyValuePointers, endOfData)) stringBuffer.Append(ref dataPointer, StringView.Empty, _strings, _argPointers, _argCount); } Debug.Assert(dataPointer == endOfData, "Buffer over-read"); - if (_keyValueCount > 0) - WriteJsonToStringBuffer(stringBuffer); + if (keyValuePointers.Count > 0) + JsonWriter.WriteJsonToStringBuffer(stringBuffer, keyValuePointers, _strings); if (_isTruncated) stringBuffer.Append(LogManager.Config.TruncatedMessageSuffix); } - private static bool ConsumeKeyValue(ref byte* dataPointer, IntPtr[] keyValuePointers, ref byte keyValueCount, byte* endOfData) + private static bool ConsumeKeyValue(ref byte* dataPointer, ICollection keyValuePointers, byte* endOfData) { var argumentType = (ArgumentType)(*dataPointer & ArgumentTypeMask.ArgumentType); @@ -330,7 +335,7 @@ private static bool ConsumeKeyValue(ref byte* dataPointer, IntPtr[] keyValuePoin } // Save a pointer to the key for later when we append the Key/Value JSON. - keyValuePointers[keyValueCount++] = new IntPtr(dataPointer); + keyValuePointers.Add(new IntPtr(dataPointer)); // Skip the key. SkipCurrentArgument(ref dataPointer); @@ -416,29 +421,6 @@ private static void SkipCurrentArgument(ref byte* dataPointer) } } - private void WriteJsonToStringBuffer(StringBuffer stringBuffer) - { - stringBuffer.Append(" ~~ { "); - for (byte i = 0; i < _keyValueCount; i++) - { - var argPointer = (byte*)_keyValuePointers[i].ToPointer(); - var dataPointer = argPointer; - - // Key. - AppendJsonValue(stringBuffer, ref dataPointer); - - stringBuffer.Append(": "); - - // Value. - AppendJsonValue(stringBuffer, ref dataPointer); - - if (i != _keyValueCount - 1) - stringBuffer.Append(", "); - } - - stringBuffer.Append(" }"); - } - public void WriteToStringBufferUnformatted(StringBuffer stringBuffer) { var endOfData = _dataPointer; @@ -458,44 +440,6 @@ public void WriteToStringBufferUnformatted(StringBuffer stringBuffer) stringBuffer.Append(LogManager.Config.TruncatedMessageSuffix); } - private void AppendJsonValue(StringBuffer stringBuffer, ref byte* dataPointer) - { - var argument = *dataPointer; - dataPointer += sizeof(ArgumentType); - - var argumentType = (ArgumentType)(argument & ArgumentTypeMask.ArgumentType); - - switch (argumentType) - { - case ArgumentType.KeyString: - AppendUnformattedArgumentValue(stringBuffer, ArgumentType.String, ref dataPointer); - break; - case ArgumentType.Guid: - case ArgumentType.DateTime: - case ArgumentType.TimeSpan: - stringBuffer.Append('"'); - AppendUnformattedArgumentValue(stringBuffer, argumentType, ref dataPointer); - stringBuffer.Append('"'); - break; - case ArgumentType.Char: - stringBuffer.Append('"'); - stringBuffer.Append(*(char*)dataPointer); - stringBuffer.Append('"'); - dataPointer += sizeof(char); - break; - case ArgumentType.Boolean: - stringBuffer.Append(*(bool*)dataPointer ? "\"true\"" : "\"false\""); - dataPointer += sizeof(bool); - break; - case ArgumentType.Null: - stringBuffer.Append("\"null\""); - break; - default: - AppendUnformattedArgumentValue(stringBuffer, argumentType, ref dataPointer); - break; - } - } - private void AppendArgumentToStringBufferUnformatted(StringBuffer stringBuffer, ref byte* dataPointer) { var argument = *dataPointer; @@ -592,18 +536,13 @@ private void AppendUnformattedArgumentValue(StringBuffer stringBuffer, ArgumentT dataPointer += sizeof(TimeSpan); break; - case ArgumentType.FormatString: - var formatStringIndex = *dataPointer; - dataPointer += sizeof(byte) + sizeof(byte); - stringBuffer.Append('"'); - stringBuffer.Append(_strings[formatStringIndex]); - stringBuffer.Append('"'); - break; - + // TODO(lmanners): Add full support for enums. case ArgumentType.Enum: var enumArg = (EnumArg*)dataPointer; dataPointer += sizeof(EnumArg); + stringBuffer.Append('"'); enumArg->AppendTo(stringBuffer); + stringBuffer.Append('"'); break; case ArgumentType.Unmanaged: @@ -638,7 +577,6 @@ private bool PrepareAppendSlow(int requestedBytes) { Array.Resize(ref _argPointers, newCapacity); Array.Resize(ref _strings, newCapacity); - Array.Resize(ref _keyValuePointers, newCapacity / 2 + 1); return true; } } diff --git a/src/ZeroLog/LogManager.cs b/src/ZeroLog/LogManager.cs index d8a5b652..bb2ba33e 100644 --- a/src/ZeroLog/LogManager.cs +++ b/src/ZeroLog/LogManager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; @@ -33,6 +34,7 @@ public class LogManager : IInternalLogManager private bool _isRunning; private IAppender[] _appenders = Array.Empty(); + private readonly List _keyValuePointers = new List(byte.MaxValue); public static ZeroLogConfig Config { get; } = new ZeroLogConfig(); @@ -324,10 +326,10 @@ private static void WriteMessageLogToAppenders(byte[] destination, IInternalLogE } } - private static void FormatLogMessage(StringBuffer stringBuffer, IInternalLogEvent logEvent) + private void FormatLogMessage(StringBuffer stringBuffer, IInternalLogEvent logEvent) { stringBuffer.Clear(); - logEvent.WriteToStringBuffer(stringBuffer); + logEvent.WriteToStringBuffer(stringBuffer, _keyValuePointers); } private static unsafe int CopyStringBufferToByteArray(StringBuffer stringBuffer, byte[] destination) diff --git a/src/ZeroLog/NoopLogEvent.cs b/src/ZeroLog/NoopLogEvent.cs index a7045fa5..c7050015 100644 --- a/src/ZeroLog/NoopLogEvent.cs +++ b/src/ZeroLog/NoopLogEvent.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Text.Formatting; using ZeroLog.Appenders; @@ -53,7 +54,7 @@ public void Log() { } - public void WriteToStringBuffer(StringBuffer stringBuffer) + public void WriteToStringBuffer(StringBuffer stringBuffer, IList? keyValuePtrList) { } diff --git a/src/ZeroLog/ZeroLogConfig.cs b/src/ZeroLog/ZeroLogConfig.cs index 9fe70a94..c048e19b 100644 --- a/src/ZeroLog/ZeroLogConfig.cs +++ b/src/ZeroLog/ZeroLogConfig.cs @@ -1,9 +1,13 @@ -namespace ZeroLog +using System; +using JetBrains.Annotations; + +namespace ZeroLog { public class ZeroLogConfig { private string _nullDisplayString = "null"; private string _truncatedMessageSuffix = " [TRUNCATED]"; + private string _jsonSeparator = " ~~ "; public bool LazyRegisterEnums { get; set; } public bool FlushAppenders { get; set; } = true; @@ -20,6 +24,12 @@ public string TruncatedMessageSuffix set => _truncatedMessageSuffix = value ?? string.Empty; } + public string JsonSeparator + { + get => _jsonSeparator; + set => _jsonSeparator = value ?? string.Empty; + } + internal ZeroLogConfig() { } From 835d261b364a141d1b22abd6192f4de88cc1916b Mon Sep 17 00:00:00 2001 From: Lowell Manners Date: Mon, 5 Oct 2020 17:49:09 +0200 Subject: [PATCH 3/8] Fix test failures --- src/ZeroLog/JsonWriter.cs | 16 ++-------------- src/ZeroLog/LogEvent.cs | 20 +++++++++----------- src/ZeroLog/LogManager.cs | 1 + 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/src/ZeroLog/JsonWriter.cs b/src/ZeroLog/JsonWriter.cs index b3c553e2..8123286e 100644 --- a/src/ZeroLog/JsonWriter.cs +++ b/src/ZeroLog/JsonWriter.cs @@ -62,15 +62,7 @@ private static void AppendJsonValue(StringBuffer stringBuffer, IReadOnlyListAppendTo(stringBuffer); - break; + // TODO(lmanners): Support enum case ArgumentType.Null: stringBuffer.Append("null"); diff --git a/src/ZeroLog/LogEvent.cs b/src/ZeroLog/LogEvent.cs index 60ec1922..80cbd56a 100644 --- a/src/ZeroLog/LogEvent.cs +++ b/src/ZeroLog/LogEvent.cs @@ -293,14 +293,7 @@ public void Log() public void WriteToStringBuffer(StringBuffer stringBuffer, IList? keyValuePointers) { - if (keyValuePointers == null) - { - keyValuePointers = new List(); - } - else - { - keyValuePointers.Clear(); - } + keyValuePointers ??= new List(); var endOfData = _dataPointer; var dataPointer = _startOfBuffer; @@ -536,13 +529,18 @@ private void AppendUnformattedArgumentValue(StringBuffer stringBuffer, ArgumentT dataPointer += sizeof(TimeSpan); break; - // TODO(lmanners): Add full support for enums. + case ArgumentType.FormatString: + var formatStringIndex = *dataPointer; + dataPointer += sizeof(byte) + sizeof(byte); + stringBuffer.Append('"'); + stringBuffer.Append(_strings[formatStringIndex]); + stringBuffer.Append('"'); + break; + case ArgumentType.Enum: var enumArg = (EnumArg*)dataPointer; dataPointer += sizeof(EnumArg); - stringBuffer.Append('"'); enumArg->AppendTo(stringBuffer); - stringBuffer.Append('"'); break; case ArgumentType.Unmanaged: diff --git a/src/ZeroLog/LogManager.cs b/src/ZeroLog/LogManager.cs index bb2ba33e..ff0771fb 100644 --- a/src/ZeroLog/LogManager.cs +++ b/src/ZeroLog/LogManager.cs @@ -329,6 +329,7 @@ private static void WriteMessageLogToAppenders(byte[] destination, IInternalLogE private void FormatLogMessage(StringBuffer stringBuffer, IInternalLogEvent logEvent) { stringBuffer.Clear(); + _keyValuePointers.Clear(); logEvent.WriteToStringBuffer(stringBuffer, _keyValuePointers); } From d3e26cbba923aea57e8eb158246b3ae3a5f6aa02 Mon Sep 17 00:00:00 2001 From: Lowell Manners Date: Tue, 6 Oct 2020 11:45:40 +0200 Subject: [PATCH 4/8] Another round of fixes/improvements --- src/ZeroLog.Tests/LogEventTests.Append.cs | 78 +++++++++---------- .../LogEventTests.AppendWithFormat.cs | 24 +++--- src/ZeroLog.Tests/LogEventTests.EdgeCases.cs | 36 ++++----- src/ZeroLog.Tests/LogEventTests.Enum.cs | 53 ++++++++++--- src/ZeroLog.Tests/LogEventTests.KeyValues.cs | 36 ++++----- src/ZeroLog.Tests/LogEventTests.Unmanaged.cs | 48 ++++++------ src/ZeroLog/ForwardingLogEvent.cs | 12 ++- src/ZeroLog/IInternalLogEvent.cs | 2 +- src/ZeroLog/ILogEvent.cs | 7 ++ src/ZeroLog/JsonWriter.cs | 71 ++++++++--------- src/ZeroLog/KeyValuePointerBuffer.cs | 27 +++++++ src/ZeroLog/LogEvent.cs | 36 +++++++-- src/ZeroLog/LogManager.cs | 6 +- src/ZeroLog/NoopLogEvent.cs | 12 ++- 14 files changed, 275 insertions(+), 173 deletions(-) create mode 100644 src/ZeroLog/KeyValuePointerBuffer.cs diff --git a/src/ZeroLog.Tests/LogEventTests.Append.cs b/src/ZeroLog.Tests/LogEventTests.Append.cs index d9e99aa9..21f80f1e 100644 --- a/src/ZeroLog.Tests/LogEventTests.Append.cs +++ b/src/ZeroLog.Tests/LogEventTests.Append.cs @@ -39,7 +39,7 @@ public void Teardown() public void should_append_string() { _logEvent.Append("abc"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("abc", _output.ToString()); } @@ -48,7 +48,7 @@ public void should_append_string() public void should_append_null_string() { _logEvent.Append((string)null); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); } @@ -58,7 +58,7 @@ public void should_append_byte_array() { var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes, bytes.Length); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("abc", _output.ToString()); } @@ -68,7 +68,7 @@ public void should_append_byte_span() { var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes.AsSpan()); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("abc", _output.ToString()); } @@ -77,7 +77,7 @@ public void should_append_byte_span() public void should_append_char_span() { _logEvent.AppendAsciiString("abc".AsSpan()); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("abc", _output.ToString()); } @@ -87,7 +87,7 @@ public void should_ignore_byte_array_with_negative_length() { var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes, -1); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("", _output.ToString()); } @@ -96,7 +96,7 @@ public void should_ignore_byte_array_with_negative_length() public void should_ignore_empty_byte_array() { _logEvent.AppendAsciiString(new byte[0], 0); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("", _output.ToString()); } @@ -105,7 +105,7 @@ public void should_ignore_empty_byte_array() public void should_ignore_empty_byte_span() { _logEvent.AppendAsciiString(ReadOnlySpan.Empty); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("", _output.ToString()); } @@ -114,7 +114,7 @@ public void should_ignore_empty_byte_span() public void should_ignore_empty_char_span() { _logEvent.AppendAsciiString(ReadOnlySpan.Empty); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("", _output.ToString()); } @@ -128,7 +128,7 @@ public void should_truncate_byte_array_after_too_many_args() var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes, bytes.Length); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -142,7 +142,7 @@ public void should_truncate_byte_span_after_too_many_args() var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes.AsSpan()); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -155,7 +155,7 @@ public void should_truncate_char_span_after_too_many_args() _logEvent.Append("."); _logEvent.AppendAsciiString("abc".AsSpan()); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -164,7 +164,7 @@ public void should_truncate_char_span_after_too_many_args() public void should_append_null_byte_array() { _logEvent.AppendAsciiString((byte[])null, 0); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); } @@ -178,7 +178,7 @@ public void should_append_unsafe_byte_array() _logEvent.AppendAsciiString(b, bytes.Length); } - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("abc", _output.ToString()); } @@ -197,7 +197,7 @@ public void should_truncate_unsafe_byte_array_after_too_many_args() _logEvent.AppendAsciiString(b, bytes.Length); } - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -206,7 +206,7 @@ public void should_truncate_unsafe_byte_array_after_too_many_args() public void should_append_null_unsafe_byte_array() { _logEvent.AppendAsciiString((byte*)null, 0); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); } @@ -215,7 +215,7 @@ public void should_append_null_unsafe_byte_array() public void should_append_true() { _logEvent.Append(true); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("True", _output.ToString()); } @@ -224,7 +224,7 @@ public void should_append_true() public void should_append_false() { _logEvent.Append(false); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("False", _output.ToString()); } @@ -233,7 +233,7 @@ public void should_append_false() public void should_append_byte() { _logEvent.Append((byte)255); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("255", _output.ToString()); } @@ -242,7 +242,7 @@ public void should_append_byte() public void should_append_char() { _logEvent.Append('€'); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("€", _output.ToString()); } @@ -251,7 +251,7 @@ public void should_append_char() public void should_append_short() { _logEvent.Append((short)4321); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("4321", _output.ToString()); } @@ -260,7 +260,7 @@ public void should_append_short() public void should_append_int() { _logEvent.Append(1234567890); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("1234567890", _output.ToString()); } @@ -269,7 +269,7 @@ public void should_append_int() public void should_append_long() { _logEvent.Append(1234567890123456789L); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("1234567890123456789", _output.ToString()); } @@ -278,7 +278,7 @@ public void should_append_long() public void should_append_float() { _logEvent.Append(0.123f); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("0.123", _output.ToString()); } @@ -287,7 +287,7 @@ public void should_append_float() public void should_append_double() { _logEvent.Append(0.123d); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("0.123", _output.ToString()); } @@ -296,7 +296,7 @@ public void should_append_double() public void should_append_decimal() { _logEvent.Append(792281625142643.37593543950335m); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("792281625142643.37593543950335", _output.ToString()); } @@ -305,7 +305,7 @@ public void should_append_decimal() public void should_append_guid() { _logEvent.Append(new Guid("129ac124-e588-47e5-9d3d-fa3a4d174e29")); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("129ac124-e588-47e5-9d3d-fa3a4d174e29", _output.ToString()); } @@ -314,7 +314,7 @@ public void should_append_guid() public void should_append_date_time() { _logEvent.Append(new DateTime(2017, 01, 12, 13, 14, 15)); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("2017-01-12 13:14:15.000", _output.ToString()); } @@ -323,7 +323,7 @@ public void should_append_date_time() public void should_append_time_span() { _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5)); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("1.02:03:04.0050000", _output.ToString()); } @@ -346,7 +346,7 @@ public void should_append_all_types() _logEvent.Append(new DateTime(2017, 01, 12, 13, 14, 15)); _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5)); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("AbCFalseTrue128£12345-128999999999999999999123.456789.012345.67890129ac124-e588-47e5-9d3d-fa3a4d174e292017-01-12 13:14:15.0001.02:03:04.0050000", _output.ToString()); } @@ -373,7 +373,7 @@ public void should_append_format() _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5)); _logEvent.AppendUnmanaged(new UnmanagedStruct() { A = 1, B = 2, C = 3 }); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("AbCFalseTrue128£12345-128999999999999999999123.456789.012345.67890129ac124-e588-47e5-9d3d-fa3a4d174e292017-01-12 13:14:15.0001.02:03:04.00500001-2-3", _output.ToString()); } @@ -390,7 +390,7 @@ public void should_append_format_multiple_times() _logEvent.Append(10); _logEvent.Append("foo"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("foo(bar42)[baz10]foo", _output.ToString()); } @@ -407,7 +407,7 @@ public void should_append_unmanaged_from_append_generic() C = 3 }); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -435,7 +435,7 @@ private void should_append_nullable() where T : struct { ((dynamic)_logEvent).Append((T?)null); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); @@ -443,7 +443,7 @@ private void should_append_nullable() _logEvent.Initialize(Level.Info, null, LogEventArgumentExhaustionStrategy.Default); ((dynamic)_logEvent).AppendGeneric((T?)null); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); @@ -451,7 +451,7 @@ private void should_append_nullable() _logEvent.Initialize(Level.Info, null, LogEventArgumentExhaustionStrategy.Default); ((dynamic)_logEvent).Append((T?)new T()); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreNotEqual("null", _output.ToString()); @@ -459,7 +459,7 @@ private void should_append_nullable() _logEvent.Initialize(Level.Info, null, LogEventArgumentExhaustionStrategy.Default); ((dynamic)_logEvent).AppendGeneric((T?)new T()); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreNotEqual("null", _output.ToString()); } @@ -473,7 +473,7 @@ public void should_truncate_log_message() _logEvent.Append("."); _logEvent.Append("!"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -487,7 +487,7 @@ public void should_not_truncate_log_message() _logEvent.Append("."); _logEvent.Append("!"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(new string('.', _argCapacity * 2) + "!", _output.ToString()); } diff --git a/src/ZeroLog.Tests/LogEventTests.AppendWithFormat.cs b/src/ZeroLog.Tests/LogEventTests.AppendWithFormat.cs index 73185b15..cb30864f 100644 --- a/src/ZeroLog.Tests/LogEventTests.AppendWithFormat.cs +++ b/src/ZeroLog.Tests/LogEventTests.AppendWithFormat.cs @@ -10,7 +10,7 @@ public partial class LogEventTests public void should_append_byte_with_format() { _logEvent.Append((byte)240, "X4"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("00F0", _output.ToString()); } @@ -19,7 +19,7 @@ public void should_append_byte_with_format() public void should_append_short_with_format() { _logEvent.Append((short)-23805, "X4"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("A303", _output.ToString()); } @@ -28,7 +28,7 @@ public void should_append_short_with_format() public void should_append_int_with_format() { _logEvent.Append(-16325, "X"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("FFFFC03B", _output.ToString()); } @@ -37,7 +37,7 @@ public void should_append_int_with_format() public void should_append_long_with_format() { _logEvent.Append(-16325L, "X"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("FFFFFFFFFFFFC03B", _output.ToString()); } @@ -46,7 +46,7 @@ public void should_append_long_with_format() public void should_append_float_with_format() { _logEvent.Append(1054.32179F, "E"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("1.054322E+003", _output.ToString()); } @@ -55,7 +55,7 @@ public void should_append_float_with_format() public void should_append_double_with_format() { _logEvent.Append(1054.32179d, "P3"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("105,432.179 %", _output.ToString()); } @@ -64,7 +64,7 @@ public void should_append_double_with_format() public void should_append_decimal_with_format() { _logEvent.Append(16325.62m, "E04"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("1.6326E+004", _output.ToString()); } @@ -73,7 +73,7 @@ public void should_append_decimal_with_format() public void should_append_guid_with_format() { _logEvent.Append(new Guid("129ac124-e588-47e5-9d3d-fa3a4d174e29"), "X"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("{0x129ac124,0xe588,0x47e5,{0x9d,0x3d,0xfa,0x3a,0x4d,0x17,0x4e,0x29}}", _output.ToString()); } @@ -82,7 +82,7 @@ public void should_append_guid_with_format() public void should_append_date_time_with_format() { _logEvent.Append(new DateTime(2017, 01, 12, 13, 14, 15), "yyyy-MM-dd"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("2017-01-12", _output.ToString()); } @@ -91,7 +91,7 @@ public void should_append_date_time_with_format() public void should_append_time_span_with_format() { _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5), "g"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.IsNotEmpty(_output.ToString()); @@ -119,7 +119,7 @@ private void should_append_nullable_with_format(string format) where T : struct { ((dynamic)_logEvent).Append((T?)new T(), format); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreNotEqual("null", _output.ToString()); @@ -127,7 +127,7 @@ private void should_append_nullable_with_format(string format) _logEvent.Initialize(Level.Info, null, LogEventArgumentExhaustionStrategy.Default); ((dynamic)_logEvent).Append((T?)null, format); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); } diff --git a/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs b/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs index b6b5d51e..eb710f51 100644 --- a/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs +++ b/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs @@ -34,7 +34,7 @@ public void should_truncate_ascii_string_if_buffer_is_not_large_enough() var asciiBytes = Encoding.ASCII.GetBytes(largeString); _logEvent.AppendAsciiString(asciiBytes, asciiBytes.Length); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(_output.ToString().Length).Equals(_bufferSize - _asciiHeaderSize + LogManager.Config.TruncatedMessageSuffix.Length); } @@ -52,7 +52,7 @@ public void should_ignore_ascii_string_if_buffer_is_not_large_enough_for_header( var asciiBytes2 = Encoding.ASCII.GetBytes(largeString2); _logEvent.AppendAsciiString(asciiBytes2, asciiBytes2.Length); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); var expectedTextLength = Math.Min(firstStringLength, _bufferSize - _asciiHeaderSize); Check.That(_output.ToString()).IsEqualTo(new string('a', expectedTextLength) + LogManager.Config.TruncatedMessageSuffix); @@ -69,7 +69,7 @@ public void should_truncate_raw_ascii_string_if_buffer_is_not_large_enough() _logEvent.AppendAsciiString(pAsciiBytes, asciiBytes.Length); } - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(_output.ToString().Length).Equals(_bufferSize - _asciiHeaderSize + LogManager.Config.TruncatedMessageSuffix.Length); } @@ -79,7 +79,7 @@ public void should_ignore_append_string_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append("abc"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -89,7 +89,7 @@ public void should_ignore_append_true_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(true); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -99,7 +99,7 @@ public void should_ignore_append_false_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(false); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -109,7 +109,7 @@ public void should_ignore_append_byte_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append((byte)255); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -119,7 +119,7 @@ public void should_ignore_append_char_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append('€'); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -129,7 +129,7 @@ public void should_ignore_append_short_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append((short)4321); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -139,7 +139,7 @@ public void should_ignore_append_int_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(1234567890); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -149,7 +149,7 @@ public void should_ignore_append_long_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(1234567890123456789L); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -159,7 +159,7 @@ public void should_ignore_append_float_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(0.123f); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -169,7 +169,7 @@ public void should_ignore_append_double_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(0.123d); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -179,7 +179,7 @@ public void should_ignore_append_decimal_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(792281625142643.37593543950335m); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -189,7 +189,7 @@ public void should_ignore_append_guid_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(new Guid("129ac124-e588-47e5-9d3d-fa3a4d174e29")); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -199,7 +199,7 @@ public void should_ignore_append_date_time_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(new DateTime(2017, 01, 12, 13, 14, 15)); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -209,7 +209,7 @@ public void should_ignore_append_time_span_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5)); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -221,7 +221,7 @@ public void should_ignore_append_key_values_if_buffer_is_full() _logEvent.AppendKeyValue("key1", (string)null) .AppendKeyValue("key2", "val2") .AppendKeyValue("key3", 3); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } diff --git a/src/ZeroLog.Tests/LogEventTests.Enum.cs b/src/ZeroLog.Tests/LogEventTests.Enum.cs index de968153..cb815edb 100644 --- a/src/ZeroLog.Tests/LogEventTests.Enum.cs +++ b/src/ZeroLog.Tests/LogEventTests.Enum.cs @@ -12,7 +12,7 @@ public void should_append_enum() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendEnum(TestEnum.Bar); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("Bar", _output.ToString()); } @@ -23,7 +23,7 @@ public void should_append_nullable_enum() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendEnum((TestEnum?)TestEnum.Bar); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("Bar", _output.ToString()); } @@ -34,18 +34,51 @@ public void should_append_null_enum() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendEnum((TestEnum?)null); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); } + [Test] + public void should_append_enum_key_value() + { + LogManager.RegisterEnum(typeof(TestEnum)); + + _logEvent.AppendKeyValue("myKey", TestEnum.Bar); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + + Assert.AreEqual(" ~~ { \"myKey\": \"Bar\" }", _output.ToString()); + } + + [Test] + public void should_append_nullable_enum_key_value() + { + LogManager.RegisterEnum(typeof(TestEnum)); + + _logEvent.AppendKeyValue("myKey", (TestEnum?)TestEnum.Bar); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + + Assert.AreEqual(" ~~ { \"myKey\": \"Bar\" }", _output.ToString()); + } + + [Test] + public void should_append_null_enum_key_value() + { + LogManager.RegisterEnum(typeof(TestEnum)); + + _logEvent.AppendKeyValue("myKey", (TestEnum?)null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + + Assert.AreEqual(" ~~ { \"myKey\": null }", _output.ToString()); + } + [Test] public void should_append_enum_generic() { LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendGeneric(TestEnum.Baz); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("Baz", _output.ToString()); } @@ -56,7 +89,7 @@ public void should_append_nullable_enum_generic() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendGeneric((TestEnum?)TestEnum.Baz); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("Baz", _output.ToString()); } @@ -67,7 +100,7 @@ public void should_append_null_enum_generic() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendGeneric((TestEnum?)null); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); } @@ -77,7 +110,7 @@ public void should_append_null_enum_generic() public void should_append_unregistered_enum() { _logEvent.AppendEnum(UnregisteredEnum.Bar); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("1", _output.ToString()); } @@ -87,7 +120,7 @@ public void should_append_unregistered_enum() public void should_append_unregistered_enum_negative() { _logEvent.AppendEnum(UnregisteredEnum.Neg); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("-1", _output.ToString()); } @@ -97,7 +130,7 @@ public void should_append_unregistered_enum_negative() public void should_append_unregistered_enum_large() { _logEvent.AppendEnum(UnregisteredEnumLarge.LargeValue); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(((ulong)UnregisteredEnumLarge.LargeValue).ToString(CultureInfo.InvariantCulture), _output.ToString()); } @@ -111,7 +144,7 @@ public void should_auto_register_enum() LogManager.Config.LazyRegisterEnums = true; _logEvent.AppendEnum(AutoRegisterEnum.Bar); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("Bar", _output.ToString()); } diff --git a/src/ZeroLog.Tests/LogEventTests.KeyValues.cs b/src/ZeroLog.Tests/LogEventTests.KeyValues.cs index 2753fba9..ae81d4fd 100644 --- a/src/ZeroLog.Tests/LogEventTests.KeyValues.cs +++ b/src/ZeroLog.Tests/LogEventTests.KeyValues.cs @@ -9,7 +9,7 @@ public partial class LogEventTests public void should_append_single_key_value() { _logEvent.AppendKeyValue("myKey", "myValue"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(" ~~ { \"myKey\": \"myValue\" }", _output.ToString()); } @@ -19,7 +19,7 @@ public void should_append_multiple_key_values() { _logEvent.AppendKeyValue("myKey", "myValue"); _logEvent.AppendKeyValue("otherKey", 2); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(" ~~ { \"myKey\": \"myValue\", \"otherKey\": 2 }", _output.ToString()); } @@ -32,7 +32,7 @@ public void should_append_formatted_string_mixed_with_key_values() _logEvent.AppendFormat("Some {} message"); _logEvent.Append("formatted"); _logEvent.AppendKeyValue("otherKey", 2); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("Some formatted message ~~ { \"myKey\": \"myValue\", \"otherKey\": 2 }", _output.ToString()); } @@ -42,7 +42,7 @@ public void should_be_chainable() { _logEvent.AppendKeyValue("myKey", 1.1f).AppendKeyValue("otherKey", new Guid()); _logEvent.Append("message"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("message ~~ { \"myKey\": 1.1, \"otherKey\": \"00000000-0000-0000-0000-000000000000\" }", _output.ToString()); } @@ -51,7 +51,7 @@ public void should_be_chainable() public void should_support_char() { _logEvent.AppendKeyValue("key1", 'a'); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(" ~~ { \"key1\": \"a\" }", _output.ToString()); } @@ -59,7 +59,7 @@ public void should_support_char() public void should_support_datetime() { _logEvent.AppendKeyValue("key1", DateTime.MinValue); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(" ~~ { \"key1\": \"0001-01-01 00:00:00.000\" }", _output.ToString()); } @@ -67,7 +67,7 @@ public void should_support_datetime() public void should_support_boolean() { _logEvent.AppendKeyValue("key1", true).AppendKeyValue("key2", false); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(" ~~ { \"key1\": true, \"key2\": false }", _output.ToString()); } @@ -75,7 +75,7 @@ public void should_support_boolean() public void should_support_single_null_key_value() { _logEvent.AppendKeyValue("key1", (int?)null); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(" ~~ { \"key1\": null }", _output.ToString()); } @@ -85,7 +85,7 @@ public void should_support_null_string_key_value() _logEvent.AppendKeyValue("key1", "val1") .AppendKeyValue("key2", (string)null) .AppendKeyValue("key3", 3); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(" ~~ { \"key1\": \"val1\", \"key2\": null, \"key3\": 3 }", _output.ToString()); } @@ -100,7 +100,7 @@ public void should_support_number_types() .AppendKeyValue("double", 6.6d) .AppendKeyValue("decimal", 6.6m); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(" ~~ { \"byte\": 1, \"short\": 2, \"int\": 3, \"long\": 4, \"float\": 5.5, \"double\": 6.6, \"decimal\": 6.6 }", _output.ToString()); } @@ -114,7 +114,7 @@ public void should_handle_truncated_key_values() _logEvent.AppendKeyValue($"key{i}", $"value{i}"); } - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual( " ~~ { \"key0\": \"value0\", \"key1\": \"value1\", \"key2\": \"value2\", \"key3\": \"value3\", \"key4\": \"value4\" } [TRUNCATED]", _output.ToString()); @@ -128,13 +128,13 @@ public void should_allocate_space_for_more_key_values() _logEvent.AppendKeyValue($"key{i}", $"value{i}"); } - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual( " ~~ { \"key0\": \"value0\", \"key1\": \"value1\", \"key2\": \"value2\", \"key3\": \"value3\", \"key4\": \"value4\", \"key5\": \"value5\" }", _output.ToString()); } - [TestCase('/', "\\/")] + [TestCase('\\', "\\\\")] [TestCase('"', "\\\"")] [TestCase('\u0000', "\\u0000")] [TestCase('\u0000', "\\u0000")] @@ -172,7 +172,7 @@ public void should_allocate_space_for_more_key_values() public void should_handle_escaped_characters(char character, string expected) { _logEvent.AppendKeyValue("myKey", character); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual(" ~~ { \"myKey\": \"" + expected + "\" }", _output.ToString()); } @@ -189,7 +189,7 @@ public void should_handle_partially_truncated_key_value() _logEvent.AppendKeyValue($"key{i}", $"value{i}"); } - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); // 'key4' is not present because there wasn't space for its value. Assert.AreEqual( @@ -200,9 +200,9 @@ public void should_handle_partially_truncated_key_value() [TestCase] public void should_escape_strings_for_json() { - _logEvent.AppendKeyValue("key / \" \t \n", "Hello \u0001 \0 there"); - _logEvent.WriteToStringBuffer(_output, null); - Assert.AreEqual(" ~~ { \"key \\/ \\\" \\t \\n\": \"Hello \\u0001 \\u0000 there\" }", _output.ToString()); + _logEvent.AppendKeyValue("key \\ \" \t \n", "Hello \u0001 \0 there"); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + Assert.AreEqual(" ~~ { \"key \\\\ \\\" \\t \\n\": \"Hello \\u0001 \\u0000 there\" }", _output.ToString()); } } } diff --git a/src/ZeroLog.Tests/LogEventTests.Unmanaged.cs b/src/ZeroLog.Tests/LogEventTests.Unmanaged.cs index 475900f8..5572c7a8 100644 --- a/src/ZeroLog.Tests/LogEventTests.Unmanaged.cs +++ b/src/ZeroLog.Tests/LogEventTests.Unmanaged.cs @@ -38,7 +38,7 @@ public void should_append_unmanaged() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -56,7 +56,7 @@ public void should_append_unmanaged_byref() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -74,7 +74,7 @@ public void should_append_nullable_unmanaged() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -87,7 +87,7 @@ public void should_append_null_nullable_unmanaged() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); } @@ -105,7 +105,7 @@ public void should_append_nullable_unmanaged_byref() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -118,7 +118,7 @@ public void should_append_null_nullable_unmanaged_byref() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); } @@ -152,7 +152,7 @@ public void should_append_unmanaged_2() LogManager.RegisterUnmanaged(typeof(UnmanagedStruct2)); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -188,7 +188,7 @@ public void should_append_external_unmanaged() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("External(1-2-3)", _output.ToString()); } @@ -206,7 +206,7 @@ public void should_append_external_unmanaged_byref() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("External(1-2-3)", _output.ToString()); } @@ -224,7 +224,7 @@ public void should_append_nullable_external_unmanaged() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("External(1-2-3)", _output.ToString()); } @@ -237,7 +237,7 @@ public void should_append_null_nullable_external_unmanaged() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); } @@ -255,7 +255,7 @@ public void should_append_nullable_external_unmanaged_byref() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("External(1-2-3)", _output.ToString()); } @@ -268,7 +268,7 @@ public void should_append_null_nullable_external_unmanaged_byref() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); } @@ -291,7 +291,7 @@ public void should_append_unregistered_unmanaged() }; _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("Unmanaged(0x01000000000000000200000003000000)", _output.ToString()); } @@ -307,7 +307,7 @@ public void should_append_unregistered_unmanaged_byref() }; _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("Unmanaged(0x01000000000000000200000003000000)", _output.ToString()); } @@ -323,7 +323,7 @@ public void should_append_unregistered_nullable_unmanaged() }; _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("Unmanaged(0x01000000000000000200000003000000)", _output.ToString()); } @@ -334,7 +334,7 @@ public void should_append_null_unregistered_nullable_unmanaged() UnregisteredUnmanagedStruct? o = null; _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); } @@ -350,7 +350,7 @@ public void should_append_unregistered_nullable_unmanaged_byref() }; _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("Unmanaged(0x01000000000000000200000003000000)", _output.ToString()); } @@ -361,7 +361,7 @@ public void should_append_null_unregistered_nullable_unmanaged_byref() UnregisteredUnmanagedStruct? o = null; _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); } @@ -394,7 +394,7 @@ public void should_append_unmanaged_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o, "foo"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("42[foo]", _output.ToString()); } @@ -410,7 +410,7 @@ public void should_append_unmanaged_byref_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o, "foo"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("42[foo]", _output.ToString()); } @@ -426,7 +426,7 @@ public void should_append_nullable_unmanaged_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o, "foo"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("42[foo]", _output.ToString()); } @@ -439,7 +439,7 @@ public void should_append_null_unmanaged_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o, "foo"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("null", _output.ToString()); } @@ -455,7 +455,7 @@ public void should_append_nullable_unmanaged_byref_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o, "foo"); - _logEvent.WriteToStringBuffer(_output, null); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); Assert.AreEqual("42[foo]", _output.ToString()); } diff --git a/src/ZeroLog/ForwardingLogEvent.cs b/src/ZeroLog/ForwardingLogEvent.cs index 725024fd..3eaca27f 100644 --- a/src/ZeroLog/ForwardingLogEvent.cs +++ b/src/ZeroLog/ForwardingLogEvent.cs @@ -42,6 +42,16 @@ public void AppendGeneric(T arg) public ILogEvent AppendAsciiString(ReadOnlySpan chars) => this; public ILogEvent AppendKeyValue(string key, string? value) => this; + public ILogEvent AppendKeyValue(string key, T value) where T : struct, Enum + { + return this; + } + + public ILogEvent AppendKeyValue(string key, T? value) where T : struct, Enum + { + return this; + } + public ILogEvent AppendEnum(T value) where T : struct, Enum { @@ -59,7 +69,7 @@ public void Log() _log.Enqueue(_logEventToAppend); } - public void WriteToStringBuffer(StringBuffer stringBuffer, IList? keyValuePtrList) + public void WriteToStringBuffer(StringBuffer stringBuffer, KeyValuePointerBuffer keyValuePointerBuffer) { } diff --git a/src/ZeroLog/IInternalLogEvent.cs b/src/ZeroLog/IInternalLogEvent.cs index 11209daf..7854a824 100644 --- a/src/ZeroLog/IInternalLogEvent.cs +++ b/src/ZeroLog/IInternalLogEvent.cs @@ -10,7 +10,7 @@ internal interface IInternalLogEvent : ILogEvent void SetTimestamp(DateTime timestamp); void AppendFormat(string format); void AppendGeneric(T arg); - void WriteToStringBuffer(StringBuffer stringBuffer, IList? keyValuePtrList = null); + void WriteToStringBuffer(StringBuffer stringBuffer, KeyValuePointerBuffer keyValuePointerBuffer); void WriteToStringBufferUnformatted(StringBuffer stringBuffer); bool IsPooled { get; } } diff --git a/src/ZeroLog/ILogEvent.cs b/src/ZeroLog/ILogEvent.cs index f37e832e..68d2e354 100644 --- a/src/ZeroLog/ILogEvent.cs +++ b/src/ZeroLog/ILogEvent.cs @@ -21,6 +21,13 @@ ILogEvent AppendEnum(T? value) ILogEvent AppendKeyValue(string key, string? value); + ILogEvent AppendKeyValue(string key, T value) + where T : struct, Enum; + + ILogEvent AppendKeyValue(string key, T? value) + where T : struct, Enum; + + void Log(); } } diff --git a/src/ZeroLog/JsonWriter.cs b/src/ZeroLog/JsonWriter.cs index 8123286e..182738ed 100644 --- a/src/ZeroLog/JsonWriter.cs +++ b/src/ZeroLog/JsonWriter.cs @@ -1,20 +1,19 @@ using System; using System.Collections.Generic; -using System.Runtime.CompilerServices; using System.Text.Formatting; namespace ZeroLog { - public static unsafe class JsonWriter + internal static unsafe class JsonWriter { - public static void WriteJsonToStringBuffer(StringBuffer stringBuffer, IList keyValuePointers, + public static void WriteJsonToStringBuffer(StringBuffer stringBuffer, KeyValuePointerBuffer keyValuePointerBuffer, string[] strings) { stringBuffer.Append(LogManager.Config.JsonSeparator); stringBuffer.Append("{ "); - for (var i = 0; i < keyValuePointers.Count; i++) + for (var i = 0; i < keyValuePointerBuffer.PointerCount; i++) { - var argPointer = (byte*)keyValuePointers[i].ToPointer(); + var argPointer = keyValuePointerBuffer.GetUnsafePointer(i); var dataPointer = argPointer; // Key. @@ -25,7 +24,7 @@ public static void WriteJsonToStringBuffer(StringBuffer stringBuffer, IListAppendTo(stringBuffer); + stringBuffer.Append('"'); + dataPointer += sizeof(EnumArg); + break; case ArgumentType.Null: stringBuffer.Append("null"); @@ -143,33 +139,31 @@ private static void AppendJsonValue(StringBuffer stringBuffer, IReadOnlyList _keyValuePointers = new List(byte.MaxValue); + + public int PointerCount => _keyValuePointers.Count; + + public unsafe byte* GetUnsafePointer(int index) + { + return (byte*)_keyValuePointers[index].ToPointer(); + } + + public unsafe void AddUnsafePointer(byte* pointer) + { + _keyValuePointers.Add(new IntPtr(pointer)); + } + + public void Clear() + { + _keyValuePointers.Clear(); + } + } +} diff --git a/src/ZeroLog/LogEvent.cs b/src/ZeroLog/LogEvent.cs index 80cbd56a..a6115a4b 100644 --- a/src/ZeroLog/LogEvent.cs +++ b/src/ZeroLog/LogEvent.cs @@ -109,6 +109,28 @@ public ILogEvent AppendKeyValue(string key, string? value) return Append(value); } + public ILogEvent AppendKeyValue(string key, T value) where T : struct, Enum + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return AppendEnum(value); + } + + public ILogEvent AppendKeyValue(string key, T? value) where T : struct, Enum + { + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + return this; + + AppendArgumentType(ArgumentType.KeyString); + AppendString(key); + + return AppendEnum(value); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendAsciiString(byte[]? bytes, int length) { @@ -291,29 +313,27 @@ public void Log() _log.Enqueue(this); } - public void WriteToStringBuffer(StringBuffer stringBuffer, IList? keyValuePointers) + public void WriteToStringBuffer(StringBuffer stringBuffer, KeyValuePointerBuffer keyValuePointerBuffer) { - keyValuePointers ??= new List(); - var endOfData = _dataPointer; var dataPointer = _startOfBuffer; while (dataPointer < endOfData) { - if (!ConsumeKeyValue(ref dataPointer, keyValuePointers, endOfData)) + if (!ConsumeKeyValue(ref dataPointer, keyValuePointerBuffer, endOfData)) stringBuffer.Append(ref dataPointer, StringView.Empty, _strings, _argPointers, _argCount); } Debug.Assert(dataPointer == endOfData, "Buffer over-read"); - if (keyValuePointers.Count > 0) - JsonWriter.WriteJsonToStringBuffer(stringBuffer, keyValuePointers, _strings); + if (keyValuePointerBuffer.PointerCount > 0) + JsonWriter.WriteJsonToStringBuffer(stringBuffer, keyValuePointerBuffer, _strings); if (_isTruncated) stringBuffer.Append(LogManager.Config.TruncatedMessageSuffix); } - private static bool ConsumeKeyValue(ref byte* dataPointer, ICollection keyValuePointers, byte* endOfData) + private static bool ConsumeKeyValue(ref byte* dataPointer, KeyValuePointerBuffer keyValuePointerBuffer, byte* endOfData) { var argumentType = (ArgumentType)(*dataPointer & ArgumentTypeMask.ArgumentType); @@ -328,7 +348,7 @@ private static bool ConsumeKeyValue(ref byte* dataPointer, ICollection k } // Save a pointer to the key for later when we append the Key/Value JSON. - keyValuePointers.Add(new IntPtr(dataPointer)); + keyValuePointerBuffer.AddUnsafePointer(dataPointer); // Skip the key. SkipCurrentArgument(ref dataPointer); diff --git a/src/ZeroLog/LogManager.cs b/src/ZeroLog/LogManager.cs index ff0771fb..ec404d13 100644 --- a/src/ZeroLog/LogManager.cs +++ b/src/ZeroLog/LogManager.cs @@ -34,7 +34,7 @@ public class LogManager : IInternalLogManager private bool _isRunning; private IAppender[] _appenders = Array.Empty(); - private readonly List _keyValuePointers = new List(byte.MaxValue); + private readonly KeyValuePointerBuffer _keyValuePointerBuffer = new KeyValuePointerBuffer(); public static ZeroLogConfig Config { get; } = new ZeroLogConfig(); @@ -329,8 +329,8 @@ private static void WriteMessageLogToAppenders(byte[] destination, IInternalLogE private void FormatLogMessage(StringBuffer stringBuffer, IInternalLogEvent logEvent) { stringBuffer.Clear(); - _keyValuePointers.Clear(); - logEvent.WriteToStringBuffer(stringBuffer, _keyValuePointers); + _keyValuePointerBuffer.Clear(); + logEvent.WriteToStringBuffer(stringBuffer, _keyValuePointerBuffer); } private static unsafe int CopyStringBufferToByteArray(StringBuffer stringBuffer, byte[] destination) diff --git a/src/ZeroLog/NoopLogEvent.cs b/src/ZeroLog/NoopLogEvent.cs index c7050015..d3bb6496 100644 --- a/src/ZeroLog/NoopLogEvent.cs +++ b/src/ZeroLog/NoopLogEvent.cs @@ -38,6 +38,16 @@ public void AppendGeneric(T arg) public ILogEvent AppendAsciiString(ReadOnlySpan chars) => this; public ILogEvent AppendKeyValue(string key, string? value) => this; + public ILogEvent AppendKeyValue(string key, T value) where T : struct, Enum + { + return this; + } + + public ILogEvent AppendKeyValue(string key, T? value) where T : struct, Enum + { + return this; + } + public ILogEvent AppendEnum(T value) where T : struct, Enum { @@ -54,7 +64,7 @@ public void Log() { } - public void WriteToStringBuffer(StringBuffer stringBuffer, IList? keyValuePtrList) + public void WriteToStringBuffer(StringBuffer stringBuffer, KeyValuePointerBuffer keyValuePointerBuffer) { } From ad28dded8f215a14538dee6a77f1132973749510 Mon Sep 17 00:00:00 2001 From: Lucas Trzesniewski Date: Wed, 7 Oct 2020 11:56:44 +0200 Subject: [PATCH 5/8] Cleanup --- src/ZeroLog.Tests/LogEventTests.KeyValues.cs | 18 +- src/ZeroLog/ForwardingLogEvent.cs | 6 +- src/ZeroLog/ILogEvent.cs | 5 +- src/ZeroLog/JsonWriter.cs | 179 ++++--------------- src/ZeroLog/KeyValuePointerBuffer.cs | 20 +-- src/ZeroLog/LogEvent.cs | 14 +- src/ZeroLog/NoopLogEvent.cs | 6 +- 7 files changed, 69 insertions(+), 179 deletions(-) diff --git a/src/ZeroLog.Tests/LogEventTests.KeyValues.cs b/src/ZeroLog.Tests/LogEventTests.KeyValues.cs index ae81d4fd..ec13ea87 100644 --- a/src/ZeroLog.Tests/LogEventTests.KeyValues.cs +++ b/src/ZeroLog.Tests/LogEventTests.KeyValues.cs @@ -148,11 +148,11 @@ public void should_allocate_space_for_more_key_values() [TestCase('\u0008', "\\b")] [TestCase('\u0009', "\\t")] [TestCase('\u000A', "\\n")] - [TestCase('\u000B', "\\u000B")] + [TestCase('\u000B', "\\u000b")] [TestCase('\u000C', "\\f")] [TestCase('\u000D', "\\r")] - [TestCase('\u000E', "\\u000E")] - [TestCase('\u000F', "\\u000F")] + [TestCase('\u000E', "\\u000e")] + [TestCase('\u000F', "\\u000f")] [TestCase('\u0010', "\\u0010")] [TestCase('\u0011', "\\u0011")] [TestCase('\u0012', "\\u0012")] @@ -163,12 +163,12 @@ public void should_allocate_space_for_more_key_values() [TestCase('\u0017', "\\u0017")] [TestCase('\u0018', "\\u0018")] [TestCase('\u0019', "\\u0019")] - [TestCase('\u001A', "\\u001A")] - [TestCase('\u001B', "\\u001B")] - [TestCase('\u001C', "\\u001C")] - [TestCase('\u001D', "\\u001D")] - [TestCase('\u001E', "\\u001E")] - [TestCase('\u001F', "\\u001F")] + [TestCase('\u001A', "\\u001a")] + [TestCase('\u001B', "\\u001b")] + [TestCase('\u001C', "\\u001c")] + [TestCase('\u001D', "\\u001d")] + [TestCase('\u001E', "\\u001e")] + [TestCase('\u001F', "\\u001f")] public void should_handle_escaped_characters(char character, string expected) { _logEvent.AppendKeyValue("myKey", character); diff --git a/src/ZeroLog/ForwardingLogEvent.cs b/src/ZeroLog/ForwardingLogEvent.cs index 3eaca27f..a6fc1f73 100644 --- a/src/ZeroLog/ForwardingLogEvent.cs +++ b/src/ZeroLog/ForwardingLogEvent.cs @@ -42,12 +42,14 @@ public void AppendGeneric(T arg) public ILogEvent AppendAsciiString(ReadOnlySpan chars) => this; public ILogEvent AppendKeyValue(string key, string? value) => this; - public ILogEvent AppendKeyValue(string key, T value) where T : struct, Enum + public ILogEvent AppendKeyValue(string key, T value) + where T : struct, Enum { return this; } - public ILogEvent AppendKeyValue(string key, T? value) where T : struct, Enum + public ILogEvent AppendKeyValue(string key, T? value) + where T : struct, Enum { return this; } diff --git a/src/ZeroLog/ILogEvent.cs b/src/ZeroLog/ILogEvent.cs index 68d2e354..d81543ec 100644 --- a/src/ZeroLog/ILogEvent.cs +++ b/src/ZeroLog/ILogEvent.cs @@ -21,13 +21,12 @@ ILogEvent AppendEnum(T? value) ILogEvent AppendKeyValue(string key, string? value); - ILogEvent AppendKeyValue(string key, T value) - where T : struct, Enum; + ILogEvent AppendKeyValue(string key, T value) + where T : struct, Enum; ILogEvent AppendKeyValue(string key, T? value) where T : struct, Enum; - void Log(); } } diff --git a/src/ZeroLog/JsonWriter.cs b/src/ZeroLog/JsonWriter.cs index 182738ed..1e5bf804 100644 --- a/src/ZeroLog/JsonWriter.cs +++ b/src/ZeroLog/JsonWriter.cs @@ -1,20 +1,24 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Text.Formatting; +using ZeroLog.Utils; namespace ZeroLog { internal static unsafe class JsonWriter { - public static void WriteJsonToStringBuffer(StringBuffer stringBuffer, KeyValuePointerBuffer keyValuePointerBuffer, - string[] strings) + public static void WriteJsonToStringBuffer(StringBuffer stringBuffer, KeyValuePointerBuffer keyValuePointerBuffer, string[] strings) { stringBuffer.Append(LogManager.Config.JsonSeparator); stringBuffer.Append("{ "); - for (var i = 0; i < keyValuePointerBuffer.PointerCount; i++) + + for (var i = 0; i < keyValuePointerBuffer.KeyPointerCount; i++) { - var argPointer = keyValuePointerBuffer.GetUnsafePointer(i); - var dataPointer = argPointer; + if (i != 0) + stringBuffer.Append(", "); + + var dataPointer = keyValuePointerBuffer.GetKeyPointer(i); // Key. AppendJsonValue(stringBuffer, strings, ref dataPointer); @@ -23,9 +27,6 @@ public static void WriteJsonToStringBuffer(StringBuffer stringBuffer, KeyValuePo // Value. AppendJsonValue(stringBuffer, strings, ref dataPointer); - - if (i != keyValuePointerBuffer.PointerCount - 1) - stringBuffer.Append(", "); } stringBuffer.Append(" }"); @@ -33,11 +34,9 @@ public static void WriteJsonToStringBuffer(StringBuffer stringBuffer, KeyValuePo private static void AppendJsonValue(StringBuffer stringBuffer, IReadOnlyList strings, ref byte* dataPointer) { - var argument = *dataPointer; + var argumentType = (ArgumentType)(*dataPointer & ArgumentTypeMask.ArgumentType); dataPointer += sizeof(ArgumentType); - var argumentType = (ArgumentType)(argument & ArgumentTypeMask.ArgumentType); - switch (argumentType) { case ArgumentType.KeyString: @@ -45,9 +44,7 @@ private static void AppendJsonValue(StringBuffer stringBuffer, IReadOnlyList _keyValuePointers = new List(byte.MaxValue); + private readonly List _keyPointers = new List(byte.MaxValue); - public int PointerCount => _keyValuePointers.Count; + public int KeyPointerCount => _keyPointers.Count; - public unsafe byte* GetUnsafePointer(int index) - { - return (byte*)_keyValuePointers[index].ToPointer(); - } + public unsafe byte* GetKeyPointer(int index) + => (byte*)_keyPointers[index].ToPointer(); - public unsafe void AddUnsafePointer(byte* pointer) - { - _keyValuePointers.Add(new IntPtr(pointer)); - } + public unsafe void AddKeyPointer(byte* pointer) + => _keyPointers.Add(new IntPtr(pointer)); public void Clear() - { - _keyValuePointers.Clear(); - } + => _keyPointers.Clear(); } } diff --git a/src/ZeroLog/LogEvent.cs b/src/ZeroLog/LogEvent.cs index a6115a4b..5f32c2f0 100644 --- a/src/ZeroLog/LogEvent.cs +++ b/src/ZeroLog/LogEvent.cs @@ -109,7 +109,8 @@ public ILogEvent AppendKeyValue(string key, string? value) return Append(value); } - public ILogEvent AppendKeyValue(string key, T value) where T : struct, Enum + public ILogEvent AppendKeyValue(string key, T value) + where T : struct, Enum { if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) return this; @@ -120,7 +121,8 @@ public ILogEvent AppendKeyValue(string key, T value) where T : struct, Enum return AppendEnum(value); } - public ILogEvent AppendKeyValue(string key, T? value) where T : struct, Enum + public ILogEvent AppendKeyValue(string key, T? value) + where T : struct, Enum { if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) return this; @@ -326,7 +328,7 @@ public void WriteToStringBuffer(StringBuffer stringBuffer, KeyValuePointerBuffer Debug.Assert(dataPointer == endOfData, "Buffer over-read"); - if (keyValuePointerBuffer.PointerCount > 0) + if (keyValuePointerBuffer.KeyPointerCount > 0) JsonWriter.WriteJsonToStringBuffer(stringBuffer, keyValuePointerBuffer, _strings); if (_isTruncated) @@ -337,7 +339,8 @@ private static bool ConsumeKeyValue(ref byte* dataPointer, KeyValuePointerBuffer { var argumentType = (ArgumentType)(*dataPointer & ArgumentTypeMask.ArgumentType); - if (argumentType != ArgumentType.KeyString) return false; + if (argumentType != ArgumentType.KeyString) + return false; // If the last item in the data is a key, that means there we ran out of space and couldn't include the value. // In this case, skip the key, and don't use it to build JSON later. @@ -348,7 +351,7 @@ private static bool ConsumeKeyValue(ref byte* dataPointer, KeyValuePointerBuffer } // Save a pointer to the key for later when we append the Key/Value JSON. - keyValuePointerBuffer.AddUnsafePointer(dataPointer); + keyValuePointerBuffer.AddKeyPointer(dataPointer); // Skip the key. SkipCurrentArgument(ref dataPointer); @@ -363,6 +366,7 @@ private static void SkipCurrentArgument(ref byte* dataPointer) { var argumentType = (ArgumentType)(*dataPointer & ArgumentTypeMask.ArgumentType); dataPointer += sizeof(ArgumentType); + switch (argumentType) { case ArgumentType.String: diff --git a/src/ZeroLog/NoopLogEvent.cs b/src/ZeroLog/NoopLogEvent.cs index d3bb6496..9237cd57 100644 --- a/src/ZeroLog/NoopLogEvent.cs +++ b/src/ZeroLog/NoopLogEvent.cs @@ -38,12 +38,14 @@ public void AppendGeneric(T arg) public ILogEvent AppendAsciiString(ReadOnlySpan chars) => this; public ILogEvent AppendKeyValue(string key, string? value) => this; - public ILogEvent AppendKeyValue(string key, T value) where T : struct, Enum + public ILogEvent AppendKeyValue(string key, T value) + where T : struct, Enum { return this; } - public ILogEvent AppendKeyValue(string key, T? value) where T : struct, Enum + public ILogEvent AppendKeyValue(string key, T? value) + where T : struct, Enum { return this; } From f193db568b96c38af1f023a52e98f306515b8ccc Mon Sep 17 00:00:00 2001 From: Lucas Trzesniewski Date: Wed, 7 Oct 2020 12:22:13 +0200 Subject: [PATCH 6/8] Make key/value appends atomic --- src/ZeroLog/LogEvent.Append.cs | 338 +++++++++++++++++------- src/ZeroLog/LogEvent.Append.tt | 29 +- src/ZeroLog/LogEvent.AppendUnmanaged.cs | 16 +- src/ZeroLog/LogEvent.AppendUnmanaged.tt | 2 +- src/ZeroLog/LogEvent.cs | 62 +++-- 5 files changed, 305 insertions(+), 142 deletions(-) diff --git a/src/ZeroLog/LogEvent.Append.cs b/src/ZeroLog/LogEvent.Append.cs index 50fa2686..99f3e97c 100644 --- a/src/ZeroLog/LogEvent.Append.cs +++ b/src/ZeroLog/LogEvent.Append.cs @@ -156,7 +156,7 @@ public void AppendGeneric(T arg) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(bool value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(bool))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(bool), 1)) return this; AppendArgumentType(ArgumentType.Boolean); @@ -168,7 +168,7 @@ public ILogEvent Append(bool value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(bool? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(bool))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(bool), 1)) return this; if (value == null) @@ -186,31 +186,43 @@ public ILogEvent Append(bool? value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, bool value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(bool), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + AppendArgumentType(ArgumentType.Boolean); + *(bool*)_dataPointer = value; + _dataPointer += sizeof(bool); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, bool? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(bool), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + + AppendArgumentType(ArgumentType.Boolean); + *(bool*)_dataPointer = value.GetValueOrDefault(); + _dataPointer += sizeof(bool); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(byte value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte), 1)) return this; AppendArgumentType(ArgumentType.Byte); @@ -222,7 +234,7 @@ public ILogEvent Append(byte value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(byte? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte), 1)) return this; if (value == null) @@ -240,32 +252,43 @@ public ILogEvent Append(byte? value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, byte value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(byte), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + AppendArgumentType(ArgumentType.Byte); + *(byte*)_dataPointer = value; + _dataPointer += sizeof(byte); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, byte? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(byte), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); - } + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + AppendArgumentType(ArgumentType.Byte); + *(byte*)_dataPointer = value.GetValueOrDefault(); + _dataPointer += sizeof(byte); + return this; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(byte value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(byte), 1)) return this; AppendArgumentTypeWithFormat(ArgumentType.Byte); @@ -278,7 +301,7 @@ public ILogEvent Append(byte value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(byte? value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(byte), 1)) return this; if (value == null) @@ -297,7 +320,7 @@ public ILogEvent Append(byte? value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(char value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(char))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(char), 1)) return this; AppendArgumentType(ArgumentType.Char); @@ -309,7 +332,7 @@ public ILogEvent Append(char value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(char? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(char))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(char), 1)) return this; if (value == null) @@ -327,31 +350,43 @@ public ILogEvent Append(char? value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, char value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(char), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + AppendArgumentType(ArgumentType.Char); + *(char*)_dataPointer = value; + _dataPointer += sizeof(char); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, char? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(char), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + + AppendArgumentType(ArgumentType.Char); + *(char*)_dataPointer = value.GetValueOrDefault(); + _dataPointer += sizeof(char); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(short value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(short))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(short), 1)) return this; AppendArgumentType(ArgumentType.Int16); @@ -363,7 +398,7 @@ public ILogEvent Append(short value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(short? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(short))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(short), 1)) return this; if (value == null) @@ -381,32 +416,43 @@ public ILogEvent Append(short? value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, short value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(short), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + AppendArgumentType(ArgumentType.Int16); + *(short*)_dataPointer = value; + _dataPointer += sizeof(short); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, short? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(short), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); - } + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + AppendArgumentType(ArgumentType.Int16); + *(short*)_dataPointer = value.GetValueOrDefault(); + _dataPointer += sizeof(short); + return this; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(short value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(short))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(short), 1)) return this; AppendArgumentTypeWithFormat(ArgumentType.Int16); @@ -419,7 +465,7 @@ public ILogEvent Append(short value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(short? value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(short))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(short), 1)) return this; if (value == null) @@ -438,7 +484,7 @@ public ILogEvent Append(short? value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(int value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(int))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(int), 1)) return this; AppendArgumentType(ArgumentType.Int32); @@ -450,7 +496,7 @@ public ILogEvent Append(int value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(int? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(int))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(int), 1)) return this; if (value == null) @@ -468,32 +514,43 @@ public ILogEvent Append(int? value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, int value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(int), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + AppendArgumentType(ArgumentType.Int32); + *(int*)_dataPointer = value; + _dataPointer += sizeof(int); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, int? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(int), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); - } + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + AppendArgumentType(ArgumentType.Int32); + *(int*)_dataPointer = value.GetValueOrDefault(); + _dataPointer += sizeof(int); + return this; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(int value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(int))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(int), 1)) return this; AppendArgumentTypeWithFormat(ArgumentType.Int32); @@ -506,7 +563,7 @@ public ILogEvent Append(int value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(int? value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(int))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(int), 1)) return this; if (value == null) @@ -525,7 +582,7 @@ public ILogEvent Append(int? value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(long value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(long))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(long), 1)) return this; AppendArgumentType(ArgumentType.Int64); @@ -537,7 +594,7 @@ public ILogEvent Append(long value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(long? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(long))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(long), 1)) return this; if (value == null) @@ -555,32 +612,43 @@ public ILogEvent Append(long? value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, long value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(long), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + AppendArgumentType(ArgumentType.Int64); + *(long*)_dataPointer = value; + _dataPointer += sizeof(long); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, long? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(long), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); - } + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + AppendArgumentType(ArgumentType.Int64); + *(long*)_dataPointer = value.GetValueOrDefault(); + _dataPointer += sizeof(long); + return this; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(long value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(long))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(long), 1)) return this; AppendArgumentTypeWithFormat(ArgumentType.Int64); @@ -593,7 +661,7 @@ public ILogEvent Append(long value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(long? value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(long))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(long), 1)) return this; if (value == null) @@ -612,7 +680,7 @@ public ILogEvent Append(long? value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(float value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(float))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(float), 1)) return this; AppendArgumentType(ArgumentType.Single); @@ -624,7 +692,7 @@ public ILogEvent Append(float value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(float? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(float))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(float), 1)) return this; if (value == null) @@ -642,32 +710,43 @@ public ILogEvent Append(float? value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, float value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(float), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + AppendArgumentType(ArgumentType.Single); + *(float*)_dataPointer = value; + _dataPointer += sizeof(float); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, float? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(float), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); - } + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + AppendArgumentType(ArgumentType.Single); + *(float*)_dataPointer = value.GetValueOrDefault(); + _dataPointer += sizeof(float); + return this; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(float value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(float))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(float), 1)) return this; AppendArgumentTypeWithFormat(ArgumentType.Single); @@ -680,7 +759,7 @@ public ILogEvent Append(float value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(float? value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(float))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(float), 1)) return this; if (value == null) @@ -699,7 +778,7 @@ public ILogEvent Append(float? value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(double value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(double))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(double), 1)) return this; AppendArgumentType(ArgumentType.Double); @@ -711,7 +790,7 @@ public ILogEvent Append(double value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(double? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(double))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(double), 1)) return this; if (value == null) @@ -729,32 +808,43 @@ public ILogEvent Append(double? value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, double value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(double), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + AppendArgumentType(ArgumentType.Double); + *(double*)_dataPointer = value; + _dataPointer += sizeof(double); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, double? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(double), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); - } + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + AppendArgumentType(ArgumentType.Double); + *(double*)_dataPointer = value.GetValueOrDefault(); + _dataPointer += sizeof(double); + return this; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(double value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(double))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(double), 1)) return this; AppendArgumentTypeWithFormat(ArgumentType.Double); @@ -767,7 +857,7 @@ public ILogEvent Append(double value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(double? value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(double))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(double), 1)) return this; if (value == null) @@ -786,7 +876,7 @@ public ILogEvent Append(double? value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(decimal value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(decimal))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(decimal), 1)) return this; AppendArgumentType(ArgumentType.Decimal); @@ -798,7 +888,7 @@ public ILogEvent Append(decimal value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(decimal? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(decimal))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(decimal), 1)) return this; if (value == null) @@ -816,32 +906,43 @@ public ILogEvent Append(decimal? value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, decimal value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(decimal), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + AppendArgumentType(ArgumentType.Decimal); + *(decimal*)_dataPointer = value; + _dataPointer += sizeof(decimal); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, decimal? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(decimal), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); - } + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + AppendArgumentType(ArgumentType.Decimal); + *(decimal*)_dataPointer = value.GetValueOrDefault(); + _dataPointer += sizeof(decimal); + return this; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(decimal value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(decimal))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(decimal), 1)) return this; AppendArgumentTypeWithFormat(ArgumentType.Decimal); @@ -854,7 +955,7 @@ public ILogEvent Append(decimal value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(decimal? value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(decimal))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(decimal), 1)) return this; if (value == null) @@ -873,7 +974,7 @@ public ILogEvent Append(decimal? value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(Guid value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(Guid))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(Guid), 1)) return this; AppendArgumentType(ArgumentType.Guid); @@ -885,7 +986,7 @@ public ILogEvent Append(Guid value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(Guid? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(Guid))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(Guid), 1)) return this; if (value == null) @@ -903,32 +1004,43 @@ public ILogEvent Append(Guid? value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, Guid value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(Guid), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + AppendArgumentType(ArgumentType.Guid); + *(Guid*)_dataPointer = value; + _dataPointer += sizeof(Guid); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, Guid? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(Guid), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); - } + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + AppendArgumentType(ArgumentType.Guid); + *(Guid*)_dataPointer = value.GetValueOrDefault(); + _dataPointer += sizeof(Guid); + return this; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(Guid value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(Guid))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(Guid), 1)) return this; AppendArgumentTypeWithFormat(ArgumentType.Guid); @@ -941,7 +1053,7 @@ public ILogEvent Append(Guid value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(Guid? value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(Guid))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(Guid), 1)) return this; if (value == null) @@ -960,7 +1072,7 @@ public ILogEvent Append(Guid? value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(DateTime value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(DateTime))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(DateTime), 1)) return this; AppendArgumentType(ArgumentType.DateTime); @@ -972,7 +1084,7 @@ public ILogEvent Append(DateTime value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(DateTime? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(DateTime))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(DateTime), 1)) return this; if (value == null) @@ -990,32 +1102,43 @@ public ILogEvent Append(DateTime? value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, DateTime value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(DateTime), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + AppendArgumentType(ArgumentType.DateTime); + *(DateTime*)_dataPointer = value; + _dataPointer += sizeof(DateTime); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, DateTime? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(DateTime), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); - } + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + AppendArgumentType(ArgumentType.DateTime); + *(DateTime*)_dataPointer = value.GetValueOrDefault(); + _dataPointer += sizeof(DateTime); + return this; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(DateTime value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(DateTime))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(DateTime), 1)) return this; AppendArgumentTypeWithFormat(ArgumentType.DateTime); @@ -1028,7 +1151,7 @@ public ILogEvent Append(DateTime value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(DateTime? value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(DateTime))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(DateTime), 1)) return this; if (value == null) @@ -1047,7 +1170,7 @@ public ILogEvent Append(DateTime? value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(TimeSpan value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(TimeSpan))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(TimeSpan), 1)) return this; AppendArgumentType(ArgumentType.TimeSpan); @@ -1059,7 +1182,7 @@ public ILogEvent Append(TimeSpan value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(TimeSpan? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(TimeSpan))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(TimeSpan), 1)) return this; if (value == null) @@ -1077,32 +1200,43 @@ public ILogEvent Append(TimeSpan? value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, TimeSpan value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(TimeSpan), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + AppendArgumentType(ArgumentType.TimeSpan); + *(TimeSpan*)_dataPointer = value; + _dataPointer += sizeof(TimeSpan); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, TimeSpan? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(TimeSpan), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); - } + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + AppendArgumentType(ArgumentType.TimeSpan); + *(TimeSpan*)_dataPointer = value.GetValueOrDefault(); + _dataPointer += sizeof(TimeSpan); + return this; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(TimeSpan value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(TimeSpan))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(TimeSpan), 1)) return this; AppendArgumentTypeWithFormat(ArgumentType.TimeSpan); @@ -1115,7 +1249,7 @@ public ILogEvent Append(TimeSpan value, string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(TimeSpan? value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(TimeSpan))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(TimeSpan), 1)) return this; if (value == null) diff --git a/src/ZeroLog/LogEvent.Append.tt b/src/ZeroLog/LogEvent.Append.tt index c905b188..c2b9b4c8 100644 --- a/src/ZeroLog/LogEvent.Append.tt +++ b/src/ZeroLog/LogEvent.Append.tt @@ -96,7 +96,7 @@ namespace ZeroLog [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(<#= type.name #> value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(<#= type.name #>))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(<#= type.name #>), 1)) return this; AppendArgumentType(ArgumentType.<#= type.argType #>); @@ -108,7 +108,7 @@ namespace ZeroLog [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(<#= type.name #>? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(<#= type.name #>))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(<#= type.name #>), 1)) return this; if (value == null) @@ -126,36 +126,47 @@ namespace ZeroLog [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, <#= type.name #> value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(<#= type.name #>), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + AppendArgumentType(ArgumentType.<#= type.argType #>); + *(<#= type.name #>*)_dataPointer = value; + _dataPointer += sizeof(<#= type.name #>); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, <#= type.name #>? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(<#= type.name #>), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + + AppendArgumentType(ArgumentType.<#= type.argType #>); + *(<#= type.name #>*)_dataPointer = value.GetValueOrDefault(); + _dataPointer += sizeof(<#= type.name #>); + return this; } <# if (type.isFormattable) { #> - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(<#= type.name #> value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(<#= type.name #>))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(<#= type.name #>), 1)) return this; AppendArgumentTypeWithFormat(ArgumentType.<#= type.argType #>); @@ -168,7 +179,7 @@ namespace ZeroLog [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(<#= type.name #>? value, string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(<#= type.name #>))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(<#= type.name #>), 1)) return this; if (value == null) diff --git a/src/ZeroLog/LogEvent.AppendUnmanaged.cs b/src/ZeroLog/LogEvent.AppendUnmanaged.cs index fdb43119..e62287db 100644 --- a/src/ZeroLog/LogEvent.AppendUnmanaged.cs +++ b/src/ZeroLog/LogEvent.AppendUnmanaged.cs @@ -46,7 +46,7 @@ unsafe partial class LogEvent public ILogEvent AppendUnmanaged(T value) where T : unmanaged { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(UnmanagedArgHeader) + sizeof(T))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(UnmanagedArgHeader) + sizeof(T), 1)) return this; AppendArgumentType(ArgumentType.Unmanaged); @@ -61,7 +61,7 @@ public ILogEvent AppendUnmanaged(T value) public ILogEvent AppendUnmanaged(T value, string format) where T : unmanaged { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(UnmanagedArgHeader) + sizeof(T))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(UnmanagedArgHeader) + sizeof(T), 1)) return this; AppendArgumentTypeWithFormat(ArgumentType.Unmanaged); @@ -77,7 +77,7 @@ public ILogEvent AppendUnmanaged(T value, string format) public ILogEvent AppendUnmanaged(ref T value) where T : unmanaged { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(UnmanagedArgHeader) + sizeof(T))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(UnmanagedArgHeader) + sizeof(T), 1)) return this; AppendArgumentType(ArgumentType.Unmanaged); @@ -92,7 +92,7 @@ public ILogEvent AppendUnmanaged(ref T value) public ILogEvent AppendUnmanaged(ref T value, string format) where T : unmanaged { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(UnmanagedArgHeader) + sizeof(T))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(UnmanagedArgHeader) + sizeof(T), 1)) return this; AppendArgumentTypeWithFormat(ArgumentType.Unmanaged); @@ -108,7 +108,7 @@ public ILogEvent AppendUnmanaged(ref T value, string format) public ILogEvent AppendUnmanaged(T? value) where T : unmanaged { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(UnmanagedArgHeader) + sizeof(T))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(UnmanagedArgHeader) + sizeof(T), 1)) return this; if (value == null) @@ -129,7 +129,7 @@ public ILogEvent AppendUnmanaged(T? value) public ILogEvent AppendUnmanaged(T? value, string format) where T : unmanaged { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(UnmanagedArgHeader) + sizeof(T))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(UnmanagedArgHeader) + sizeof(T), 1)) return this; if (value == null) @@ -151,7 +151,7 @@ public ILogEvent AppendUnmanaged(T? value, string format) public ILogEvent AppendUnmanaged(ref T? value) where T : unmanaged { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(UnmanagedArgHeader) + sizeof(T))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(UnmanagedArgHeader) + sizeof(T), 1)) return this; if (value == null) @@ -172,7 +172,7 @@ public ILogEvent AppendUnmanaged(ref T? value) public ILogEvent AppendUnmanaged(ref T? value, string format) where T : unmanaged { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(UnmanagedArgHeader) + sizeof(T))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(UnmanagedArgHeader) + sizeof(T), 1)) return this; if (value == null) diff --git a/src/ZeroLog/LogEvent.AppendUnmanaged.tt b/src/ZeroLog/LogEvent.AppendUnmanaged.tt index d3abd947..18a37388 100644 --- a/src/ZeroLog/LogEvent.AppendUnmanaged.tt +++ b/src/ZeroLog/LogEvent.AppendUnmanaged.tt @@ -53,7 +53,7 @@ namespace ZeroLog public <#= GetSignature(isNullable, isRef, isFormattable) #> where T : unmanaged { - if (!PrepareAppend(sizeof(ArgumentType)<#= isFormattable ? " + sizeof(byte)" : "" #> + sizeof(UnmanagedArgHeader) + sizeof(T))) + if (!PrepareAppend(sizeof(ArgumentType)<#= isFormattable ? " + sizeof(byte)" : "" #> + sizeof(UnmanagedArgHeader) + sizeof(T), 1)) return this; <# diff --git a/src/ZeroLog/LogEvent.cs b/src/ZeroLog/LogEvent.cs index 5f32c2f0..24f00756 100644 --- a/src/ZeroLog/LogEvent.cs +++ b/src/ZeroLog/LogEvent.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.Linq; using System.Runtime.CompilerServices; using System.Text.Formatting; using System.Threading; @@ -72,7 +70,7 @@ private void AppendGenericSlow(T arg) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AppendFormat(string format) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(byte), 1)) return; AppendArgumentType(ArgumentType.FormatString); @@ -83,7 +81,7 @@ public void AppendFormat(string format) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent Append(string? s) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte), 1)) return this; if (s == null) @@ -100,37 +98,57 @@ public ILogEvent Append(string? s) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ILogEvent AppendKeyValue(string key, string? value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(byte), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return Append(value); + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + + AppendArgumentType(ArgumentType.String); + AppendString(value); + return this; } public ILogEvent AppendKeyValue(string key, T value) where T : struct, Enum { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(EnumArg), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return AppendEnum(value); + AppendArgumentType(ArgumentType.Enum); + *(EnumArg*)_dataPointer = new EnumArg(TypeUtil.TypeHandle, EnumCache.ToUInt64(value)); + _dataPointer += sizeof(EnumArg); + return this; } public ILogEvent AppendKeyValue(string key, T? value) where T : struct, Enum { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(byte) + sizeof(ArgumentType) + sizeof(EnumArg), 2)) return this; AppendArgumentType(ArgumentType.KeyString); AppendString(key); - return AppendEnum(value); + if (value == null) + { + AppendArgumentType(ArgumentType.Null); + return this; + } + + AppendArgumentType(ArgumentType.Enum); + *(EnumArg*)_dataPointer = new EnumArg(TypeUtil.TypeHandle, EnumCache.ToUInt64(value.GetValueOrDefault())); + _dataPointer += sizeof(EnumArg); + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -138,7 +156,7 @@ public ILogEvent AppendAsciiString(byte[]? bytes, int length) { if (bytes == null) { - if (PrepareAppend(sizeof(ArgumentType))) + if (PrepareAppend(sizeof(ArgumentType), 1)) AppendArgumentType(ArgumentType.Null); return this; @@ -153,7 +171,7 @@ public ILogEvent AppendAsciiString(byte[]? bytes, int length) length = remainingBytes; } - if (length <= 0 || !PrepareAppend(sizeof(ArgumentType) + sizeof(int) + length)) + if (length <= 0 || !PrepareAppend(sizeof(ArgumentType) + sizeof(int) + length, 1)) return this; AppendArgumentType(ArgumentType.AsciiString); @@ -167,7 +185,7 @@ public ILogEvent AppendAsciiString(byte* bytes, int length) { if (bytes == null) { - if (PrepareAppend(sizeof(ArgumentType))) + if (PrepareAppend(sizeof(ArgumentType), 1)) AppendArgumentType(ArgumentType.Null); return this; @@ -182,7 +200,7 @@ public ILogEvent AppendAsciiString(byte* bytes, int length) length = remainingBytes; } - if (length <= 0 || !PrepareAppend(sizeof(ArgumentType) + sizeof(int) + length)) + if (length <= 0 || !PrepareAppend(sizeof(ArgumentType) + sizeof(int) + length, 1)) return this; AppendArgumentType(ArgumentType.AsciiString); @@ -205,7 +223,7 @@ public ILogEvent AppendAsciiString(ReadOnlySpan bytes) length = remainingBytes; } - if (length <= 0 || !PrepareAppend(sizeof(ArgumentType) + sizeof(int) + length)) + if (length <= 0 || !PrepareAppend(sizeof(ArgumentType) + sizeof(int) + length, 1)) return this; AppendArgumentType(ArgumentType.AsciiString); @@ -228,7 +246,7 @@ public ILogEvent AppendAsciiString(ReadOnlySpan chars) length = remainingBytes; } - if (length <= 0 || !PrepareAppend(sizeof(ArgumentType) + sizeof(int) + length)) + if (length <= 0 || !PrepareAppend(sizeof(ArgumentType) + sizeof(int) + length, 1)) return this; AppendArgumentType(ArgumentType.AsciiString); @@ -253,7 +271,7 @@ public ILogEvent AppendEnum(T? value) { if (value == null) { - if (PrepareAppend(sizeof(ArgumentType))) + if (PrepareAppend(sizeof(ArgumentType), 1)) AppendArgumentType(ArgumentType.Null); return this; @@ -265,7 +283,7 @@ public ILogEvent AppendEnum(T? value) [MethodImpl(MethodImplOptions.AggressiveInlining)] private ILogEvent AppendEnumInternal(T value) { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(EnumArg))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(EnumArg), 1)) return this; AppendArgumentType(ArgumentType.Enum); @@ -277,7 +295,7 @@ private ILogEvent AppendEnumInternal(T value) [MethodImpl(MethodImplOptions.NoInlining)] private void AppendNullableEnumInternal(T value) // T = Nullable { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(EnumArg))) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(EnumArg), 1)) return; var enumValue = EnumCache.ToUInt64Nullable(value); @@ -295,7 +313,7 @@ private void AppendNullableEnumInternal(T value) // T = Nullable [MethodImpl(MethodImplOptions.NoInlining)] private void AppendUnmanagedInternal(T arg) // T = unmanaged or Nullable { - if (!PrepareAppend(sizeof(ArgumentType) + sizeof(UnmanagedArgHeader) + UnsafeTools.SizeOf())) + if (!PrepareAppend(sizeof(ArgumentType) + sizeof(UnmanagedArgHeader) + UnsafeTools.SizeOf(), 1)) return; // If T is a Nullable, we copy it as-is and let the formatter deal with it. @@ -584,9 +602,9 @@ private void AppendUnformattedArgumentValue(StringBuffer stringBuffer, ArgumentT } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool PrepareAppend(int requestedBytes) + private bool PrepareAppend(int requestedBytes, int requestedArgSlots) => _dataPointer + requestedBytes <= _endOfBuffer - && _argCount < _argPointers.Length + && _argCount + requestedArgSlots <= _argPointers.Length || PrepareAppendSlow(requestedBytes); [MethodImpl(MethodImplOptions.NoInlining)] From cf931cc73f900a9cda600cf02630a0d30603dd94 Mon Sep 17 00:00:00 2001 From: Lucas Trzesniewski Date: Wed, 7 Oct 2020 14:42:57 +0200 Subject: [PATCH 7/8] Escape enum strings in JSON --- src/ZeroLog.Tests/LogEventTests.Enum.cs | 11 ++++++ src/ZeroLog/EnumArg.cs | 46 +++++++++++++------------ src/ZeroLog/JsonWriter.cs | 37 +++++++++++++++----- 3 files changed, 64 insertions(+), 30 deletions(-) diff --git a/src/ZeroLog.Tests/LogEventTests.Enum.cs b/src/ZeroLog.Tests/LogEventTests.Enum.cs index cb815edb..a51dd72b 100644 --- a/src/ZeroLog.Tests/LogEventTests.Enum.cs +++ b/src/ZeroLog.Tests/LogEventTests.Enum.cs @@ -72,6 +72,17 @@ public void should_append_null_enum_key_value() Assert.AreEqual(" ~~ { \"myKey\": null }", _output.ToString()); } + [Test] + public void should_append_unknown_enum_key_value() + { + LogManager.RegisterEnum(typeof(TestEnum)); + + _logEvent.AppendKeyValue("myKey", (TestEnum)(-42)); + _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + + Assert.AreEqual(" ~~ { \"myKey\": -42 }", _output.ToString()); + } + [Test] public void should_append_enum_generic() { diff --git a/src/ZeroLog/EnumArg.cs b/src/ZeroLog/EnumArg.cs index bac13649..16c2da3f 100644 --- a/src/ZeroLog/EnumArg.cs +++ b/src/ZeroLog/EnumArg.cs @@ -23,34 +23,17 @@ public EnumArg(IntPtr typeHandle, ulong value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AppendTo(StringBuffer stringBuffer) { - var enumString = EnumCache.GetString(_typeHandle, _value, out var enumRegistered); + var enumString = GetString(); + if (enumString != null) - { stringBuffer.Append(enumString); - return; - } - - AppendToSlow(stringBuffer, enumRegistered); + else + AppendNumericValue(stringBuffer); } [MethodImpl(MethodImplOptions.NoInlining)] - private void AppendToSlow(StringBuffer stringBuffer, bool enumRegistered) + public void AppendNumericValue(StringBuffer stringBuffer) { - if (!enumRegistered && LogManager.Config.LazyRegisterEnums) - { - var type = TypeUtil.GetTypeFromHandle(_typeHandle); - if (type is null) - return; - - LogManager.RegisterEnum(type); - var enumString = EnumCache.GetString(_typeHandle, _value, out _); - if (enumString != null) - { - stringBuffer.Append(enumString); - return; - } - } - if (_value <= long.MaxValue) { stringBuffer.Append(_value, StringView.Empty); @@ -62,5 +45,24 @@ private void AppendToSlow(StringBuffer stringBuffer, bool enumRegistered) else stringBuffer.Append(_value, StringView.Empty); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public string? GetString() + => EnumCache.GetString(_typeHandle, _value, out var enumRegistered) + ?? GetStringSlow(enumRegistered); + + [MethodImpl(MethodImplOptions.NoInlining)] + private string? GetStringSlow(bool enumRegistered) + { + if (enumRegistered || !LogManager.Config.LazyRegisterEnums) + return null; + + var type = TypeUtil.GetTypeFromHandle(_typeHandle); + if (type is null) + return null; + + LogManager.RegisterEnum(type); + return EnumCache.GetString(_typeHandle, _value, out _); + } } } diff --git a/src/ZeroLog/JsonWriter.cs b/src/ZeroLog/JsonWriter.cs index 1e5bf804..cd9ac07c 100644 --- a/src/ZeroLog/JsonWriter.cs +++ b/src/ZeroLog/JsonWriter.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Text.Formatting; using ZeroLog.Utils; @@ -32,7 +31,7 @@ public static void WriteJsonToStringBuffer(StringBuffer stringBuffer, KeyValuePo stringBuffer.Append(" }"); } - private static void AppendJsonValue(StringBuffer stringBuffer, IReadOnlyList strings, ref byte* dataPointer) + private static void AppendJsonValue(StringBuffer stringBuffer, string[] strings, ref byte* dataPointer) { var argumentType = (ArgumentType)(*dataPointer & ArgumentTypeMask.ArgumentType); dataPointer += sizeof(ArgumentType); @@ -41,13 +40,20 @@ private static void AppendJsonValue(StringBuffer stringBuffer, IReadOnlyListAppendTo(stringBuffer); - stringBuffer.Append('"'); + var enumString = enumArg->GetString(); + + if (enumString != null) + AppendString(enumString, stringBuffer); + else + enumArg->AppendNumericValue(stringBuffer); + dataPointer += sizeof(EnumArg); break; @@ -136,6 +146,17 @@ private static void AppendJsonValue(StringBuffer stringBuffer, IReadOnlyList Date: Wed, 7 Oct 2020 15:53:53 +0200 Subject: [PATCH 8/8] Cleanup --- src/ZeroLog.Tests/Extensions.cs | 10 +++ src/ZeroLog.Tests/LogEventTests.Append.cs | 78 +++++++++---------- .../LogEventTests.AppendWithFormat.cs | 24 +++--- src/ZeroLog.Tests/LogEventTests.EdgeCases.cs | 36 ++++----- src/ZeroLog.Tests/LogEventTests.Enum.cs | 28 +++---- src/ZeroLog.Tests/LogEventTests.KeyValues.cs | 30 +++---- src/ZeroLog.Tests/LogEventTests.Unmanaged.cs | 48 ++++++------ src/ZeroLog/Config/JsonConfigurator.cs | 2 - src/ZeroLog/ForwardingLogEvent.cs | 2 - src/ZeroLog/LogEvent.cs | 23 ++---- src/ZeroLog/LogManager.cs | 18 ++--- src/ZeroLog/NoopLogEvent.cs | 1 - 12 files changed, 144 insertions(+), 156 deletions(-) create mode 100644 src/ZeroLog.Tests/Extensions.cs diff --git a/src/ZeroLog.Tests/Extensions.cs b/src/ZeroLog.Tests/Extensions.cs new file mode 100644 index 00000000..f982d295 --- /dev/null +++ b/src/ZeroLog.Tests/Extensions.cs @@ -0,0 +1,10 @@ +using System.Text.Formatting; + +namespace ZeroLog.Tests +{ + internal static class Extensions + { + public static void WriteToStringBuffer(this IInternalLogEvent logEvent, StringBuffer stringBuffer) + => logEvent.WriteToStringBuffer(stringBuffer, new KeyValuePointerBuffer()); + } +} diff --git a/src/ZeroLog.Tests/LogEventTests.Append.cs b/src/ZeroLog.Tests/LogEventTests.Append.cs index 21f80f1e..967a0485 100644 --- a/src/ZeroLog.Tests/LogEventTests.Append.cs +++ b/src/ZeroLog.Tests/LogEventTests.Append.cs @@ -39,7 +39,7 @@ public void Teardown() public void should_append_string() { _logEvent.Append("abc"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("abc", _output.ToString()); } @@ -48,7 +48,7 @@ public void should_append_string() public void should_append_null_string() { _logEvent.Append((string)null); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); } @@ -58,7 +58,7 @@ public void should_append_byte_array() { var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes, bytes.Length); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("abc", _output.ToString()); } @@ -68,7 +68,7 @@ public void should_append_byte_span() { var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes.AsSpan()); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("abc", _output.ToString()); } @@ -77,7 +77,7 @@ public void should_append_byte_span() public void should_append_char_span() { _logEvent.AppendAsciiString("abc".AsSpan()); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("abc", _output.ToString()); } @@ -87,7 +87,7 @@ public void should_ignore_byte_array_with_negative_length() { var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes, -1); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("", _output.ToString()); } @@ -96,7 +96,7 @@ public void should_ignore_byte_array_with_negative_length() public void should_ignore_empty_byte_array() { _logEvent.AppendAsciiString(new byte[0], 0); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("", _output.ToString()); } @@ -105,7 +105,7 @@ public void should_ignore_empty_byte_array() public void should_ignore_empty_byte_span() { _logEvent.AppendAsciiString(ReadOnlySpan.Empty); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("", _output.ToString()); } @@ -114,7 +114,7 @@ public void should_ignore_empty_byte_span() public void should_ignore_empty_char_span() { _logEvent.AppendAsciiString(ReadOnlySpan.Empty); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("", _output.ToString()); } @@ -128,7 +128,7 @@ public void should_truncate_byte_array_after_too_many_args() var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes, bytes.Length); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -142,7 +142,7 @@ public void should_truncate_byte_span_after_too_many_args() var bytes = Encoding.Default.GetBytes("abc"); _logEvent.AppendAsciiString(bytes.AsSpan()); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -155,7 +155,7 @@ public void should_truncate_char_span_after_too_many_args() _logEvent.Append("."); _logEvent.AppendAsciiString("abc".AsSpan()); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -164,7 +164,7 @@ public void should_truncate_char_span_after_too_many_args() public void should_append_null_byte_array() { _logEvent.AppendAsciiString((byte[])null, 0); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); } @@ -178,7 +178,7 @@ public void should_append_unsafe_byte_array() _logEvent.AppendAsciiString(b, bytes.Length); } - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("abc", _output.ToString()); } @@ -197,7 +197,7 @@ public void should_truncate_unsafe_byte_array_after_too_many_args() _logEvent.AppendAsciiString(b, bytes.Length); } - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -206,7 +206,7 @@ public void should_truncate_unsafe_byte_array_after_too_many_args() public void should_append_null_unsafe_byte_array() { _logEvent.AppendAsciiString((byte*)null, 0); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); } @@ -215,7 +215,7 @@ public void should_append_null_unsafe_byte_array() public void should_append_true() { _logEvent.Append(true); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("True", _output.ToString()); } @@ -224,7 +224,7 @@ public void should_append_true() public void should_append_false() { _logEvent.Append(false); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("False", _output.ToString()); } @@ -233,7 +233,7 @@ public void should_append_false() public void should_append_byte() { _logEvent.Append((byte)255); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("255", _output.ToString()); } @@ -242,7 +242,7 @@ public void should_append_byte() public void should_append_char() { _logEvent.Append('€'); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("€", _output.ToString()); } @@ -251,7 +251,7 @@ public void should_append_char() public void should_append_short() { _logEvent.Append((short)4321); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("4321", _output.ToString()); } @@ -260,7 +260,7 @@ public void should_append_short() public void should_append_int() { _logEvent.Append(1234567890); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("1234567890", _output.ToString()); } @@ -269,7 +269,7 @@ public void should_append_int() public void should_append_long() { _logEvent.Append(1234567890123456789L); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("1234567890123456789", _output.ToString()); } @@ -278,7 +278,7 @@ public void should_append_long() public void should_append_float() { _logEvent.Append(0.123f); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("0.123", _output.ToString()); } @@ -287,7 +287,7 @@ public void should_append_float() public void should_append_double() { _logEvent.Append(0.123d); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("0.123", _output.ToString()); } @@ -296,7 +296,7 @@ public void should_append_double() public void should_append_decimal() { _logEvent.Append(792281625142643.37593543950335m); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("792281625142643.37593543950335", _output.ToString()); } @@ -305,7 +305,7 @@ public void should_append_decimal() public void should_append_guid() { _logEvent.Append(new Guid("129ac124-e588-47e5-9d3d-fa3a4d174e29")); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("129ac124-e588-47e5-9d3d-fa3a4d174e29", _output.ToString()); } @@ -314,7 +314,7 @@ public void should_append_guid() public void should_append_date_time() { _logEvent.Append(new DateTime(2017, 01, 12, 13, 14, 15)); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("2017-01-12 13:14:15.000", _output.ToString()); } @@ -323,7 +323,7 @@ public void should_append_date_time() public void should_append_time_span() { _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5)); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("1.02:03:04.0050000", _output.ToString()); } @@ -346,7 +346,7 @@ public void should_append_all_types() _logEvent.Append(new DateTime(2017, 01, 12, 13, 14, 15)); _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5)); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("AbCFalseTrue128£12345-128999999999999999999123.456789.012345.67890129ac124-e588-47e5-9d3d-fa3a4d174e292017-01-12 13:14:15.0001.02:03:04.0050000", _output.ToString()); } @@ -373,7 +373,7 @@ public void should_append_format() _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5)); _logEvent.AppendUnmanaged(new UnmanagedStruct() { A = 1, B = 2, C = 3 }); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("AbCFalseTrue128£12345-128999999999999999999123.456789.012345.67890129ac124-e588-47e5-9d3d-fa3a4d174e292017-01-12 13:14:15.0001.02:03:04.00500001-2-3", _output.ToString()); } @@ -390,7 +390,7 @@ public void should_append_format_multiple_times() _logEvent.Append(10); _logEvent.Append("foo"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("foo(bar42)[baz10]foo", _output.ToString()); } @@ -407,7 +407,7 @@ public void should_append_unmanaged_from_append_generic() C = 3 }); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -435,7 +435,7 @@ private void should_append_nullable() where T : struct { ((dynamic)_logEvent).Append((T?)null); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); @@ -443,7 +443,7 @@ private void should_append_nullable() _logEvent.Initialize(Level.Info, null, LogEventArgumentExhaustionStrategy.Default); ((dynamic)_logEvent).AppendGeneric((T?)null); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); @@ -451,7 +451,7 @@ private void should_append_nullable() _logEvent.Initialize(Level.Info, null, LogEventArgumentExhaustionStrategy.Default); ((dynamic)_logEvent).Append((T?)new T()); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreNotEqual("null", _output.ToString()); @@ -459,7 +459,7 @@ private void should_append_nullable() _logEvent.Initialize(Level.Info, null, LogEventArgumentExhaustionStrategy.Default); ((dynamic)_logEvent).AppendGeneric((T?)new T()); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreNotEqual("null", _output.ToString()); } @@ -473,7 +473,7 @@ public void should_truncate_log_message() _logEvent.Append("."); _logEvent.Append("!"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(new string('.', _argCapacity) + LogManager.Config.TruncatedMessageSuffix, _output.ToString()); } @@ -487,7 +487,7 @@ public void should_not_truncate_log_message() _logEvent.Append("."); _logEvent.Append("!"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(new string('.', _argCapacity * 2) + "!", _output.ToString()); } diff --git a/src/ZeroLog.Tests/LogEventTests.AppendWithFormat.cs b/src/ZeroLog.Tests/LogEventTests.AppendWithFormat.cs index cb30864f..f53b2d5a 100644 --- a/src/ZeroLog.Tests/LogEventTests.AppendWithFormat.cs +++ b/src/ZeroLog.Tests/LogEventTests.AppendWithFormat.cs @@ -10,7 +10,7 @@ public partial class LogEventTests public void should_append_byte_with_format() { _logEvent.Append((byte)240, "X4"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("00F0", _output.ToString()); } @@ -19,7 +19,7 @@ public void should_append_byte_with_format() public void should_append_short_with_format() { _logEvent.Append((short)-23805, "X4"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("A303", _output.ToString()); } @@ -28,7 +28,7 @@ public void should_append_short_with_format() public void should_append_int_with_format() { _logEvent.Append(-16325, "X"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("FFFFC03B", _output.ToString()); } @@ -37,7 +37,7 @@ public void should_append_int_with_format() public void should_append_long_with_format() { _logEvent.Append(-16325L, "X"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("FFFFFFFFFFFFC03B", _output.ToString()); } @@ -46,7 +46,7 @@ public void should_append_long_with_format() public void should_append_float_with_format() { _logEvent.Append(1054.32179F, "E"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("1.054322E+003", _output.ToString()); } @@ -55,7 +55,7 @@ public void should_append_float_with_format() public void should_append_double_with_format() { _logEvent.Append(1054.32179d, "P3"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("105,432.179 %", _output.ToString()); } @@ -64,7 +64,7 @@ public void should_append_double_with_format() public void should_append_decimal_with_format() { _logEvent.Append(16325.62m, "E04"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("1.6326E+004", _output.ToString()); } @@ -73,7 +73,7 @@ public void should_append_decimal_with_format() public void should_append_guid_with_format() { _logEvent.Append(new Guid("129ac124-e588-47e5-9d3d-fa3a4d174e29"), "X"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("{0x129ac124,0xe588,0x47e5,{0x9d,0x3d,0xfa,0x3a,0x4d,0x17,0x4e,0x29}}", _output.ToString()); } @@ -82,7 +82,7 @@ public void should_append_guid_with_format() public void should_append_date_time_with_format() { _logEvent.Append(new DateTime(2017, 01, 12, 13, 14, 15), "yyyy-MM-dd"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("2017-01-12", _output.ToString()); } @@ -91,7 +91,7 @@ public void should_append_date_time_with_format() public void should_append_time_span_with_format() { _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5), "g"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.IsNotEmpty(_output.ToString()); @@ -119,7 +119,7 @@ private void should_append_nullable_with_format(string format) where T : struct { ((dynamic)_logEvent).Append((T?)new T(), format); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreNotEqual("null", _output.ToString()); @@ -127,7 +127,7 @@ private void should_append_nullable_with_format(string format) _logEvent.Initialize(Level.Info, null, LogEventArgumentExhaustionStrategy.Default); ((dynamic)_logEvent).Append((T?)null, format); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); } diff --git a/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs b/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs index eb710f51..a17162ec 100644 --- a/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs +++ b/src/ZeroLog.Tests/LogEventTests.EdgeCases.cs @@ -34,7 +34,7 @@ public void should_truncate_ascii_string_if_buffer_is_not_large_enough() var asciiBytes = Encoding.ASCII.GetBytes(largeString); _logEvent.AppendAsciiString(asciiBytes, asciiBytes.Length); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(_output.ToString().Length).Equals(_bufferSize - _asciiHeaderSize + LogManager.Config.TruncatedMessageSuffix.Length); } @@ -52,7 +52,7 @@ public void should_ignore_ascii_string_if_buffer_is_not_large_enough_for_header( var asciiBytes2 = Encoding.ASCII.GetBytes(largeString2); _logEvent.AppendAsciiString(asciiBytes2, asciiBytes2.Length); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); var expectedTextLength = Math.Min(firstStringLength, _bufferSize - _asciiHeaderSize); Check.That(_output.ToString()).IsEqualTo(new string('a', expectedTextLength) + LogManager.Config.TruncatedMessageSuffix); @@ -69,7 +69,7 @@ public void should_truncate_raw_ascii_string_if_buffer_is_not_large_enough() _logEvent.AppendAsciiString(pAsciiBytes, asciiBytes.Length); } - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(_output.ToString().Length).Equals(_bufferSize - _asciiHeaderSize + LogManager.Config.TruncatedMessageSuffix.Length); } @@ -79,7 +79,7 @@ public void should_ignore_append_string_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append("abc"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -89,7 +89,7 @@ public void should_ignore_append_true_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(true); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -99,7 +99,7 @@ public void should_ignore_append_false_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(false); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -109,7 +109,7 @@ public void should_ignore_append_byte_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append((byte)255); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -119,7 +119,7 @@ public void should_ignore_append_char_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append('€'); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -129,7 +129,7 @@ public void should_ignore_append_short_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append((short)4321); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -139,7 +139,7 @@ public void should_ignore_append_int_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(1234567890); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -149,7 +149,7 @@ public void should_ignore_append_long_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(1234567890123456789L); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -159,7 +159,7 @@ public void should_ignore_append_float_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(0.123f); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -169,7 +169,7 @@ public void should_ignore_append_double_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(0.123d); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -179,7 +179,7 @@ public void should_ignore_append_decimal_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(792281625142643.37593543950335m); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -189,7 +189,7 @@ public void should_ignore_append_guid_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(new Guid("129ac124-e588-47e5-9d3d-fa3a4d174e29")); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -199,7 +199,7 @@ public void should_ignore_append_date_time_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(new DateTime(2017, 01, 12, 13, 14, 15)); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -209,7 +209,7 @@ public void should_ignore_append_time_span_if_buffer_is_full() { FillBufferWithWhiteSpaces(); _logEvent.Append(new TimeSpan(1, 2, 3, 4, 5)); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } @@ -221,7 +221,7 @@ public void should_ignore_append_key_values_if_buffer_is_full() _logEvent.AppendKeyValue("key1", (string)null) .AppendKeyValue("key2", "val2") .AppendKeyValue("key3", 3); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Check.That(string.IsNullOrWhiteSpace(_output.ToString())); } diff --git a/src/ZeroLog.Tests/LogEventTests.Enum.cs b/src/ZeroLog.Tests/LogEventTests.Enum.cs index a51dd72b..8a291bfa 100644 --- a/src/ZeroLog.Tests/LogEventTests.Enum.cs +++ b/src/ZeroLog.Tests/LogEventTests.Enum.cs @@ -12,7 +12,7 @@ public void should_append_enum() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendEnum(TestEnum.Bar); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("Bar", _output.ToString()); } @@ -23,7 +23,7 @@ public void should_append_nullable_enum() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendEnum((TestEnum?)TestEnum.Bar); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("Bar", _output.ToString()); } @@ -34,7 +34,7 @@ public void should_append_null_enum() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendEnum((TestEnum?)null); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); } @@ -45,7 +45,7 @@ public void should_append_enum_key_value() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendKeyValue("myKey", TestEnum.Bar); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(" ~~ { \"myKey\": \"Bar\" }", _output.ToString()); } @@ -56,7 +56,7 @@ public void should_append_nullable_enum_key_value() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendKeyValue("myKey", (TestEnum?)TestEnum.Bar); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(" ~~ { \"myKey\": \"Bar\" }", _output.ToString()); } @@ -67,7 +67,7 @@ public void should_append_null_enum_key_value() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendKeyValue("myKey", (TestEnum?)null); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(" ~~ { \"myKey\": null }", _output.ToString()); } @@ -78,7 +78,7 @@ public void should_append_unknown_enum_key_value() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendKeyValue("myKey", (TestEnum)(-42)); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(" ~~ { \"myKey\": -42 }", _output.ToString()); } @@ -89,7 +89,7 @@ public void should_append_enum_generic() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendGeneric(TestEnum.Baz); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("Baz", _output.ToString()); } @@ -100,7 +100,7 @@ public void should_append_nullable_enum_generic() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendGeneric((TestEnum?)TestEnum.Baz); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("Baz", _output.ToString()); } @@ -111,7 +111,7 @@ public void should_append_null_enum_generic() LogManager.RegisterEnum(typeof(TestEnum)); _logEvent.AppendGeneric((TestEnum?)null); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); } @@ -121,7 +121,7 @@ public void should_append_null_enum_generic() public void should_append_unregistered_enum() { _logEvent.AppendEnum(UnregisteredEnum.Bar); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("1", _output.ToString()); } @@ -131,7 +131,7 @@ public void should_append_unregistered_enum() public void should_append_unregistered_enum_negative() { _logEvent.AppendEnum(UnregisteredEnum.Neg); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("-1", _output.ToString()); } @@ -141,7 +141,7 @@ public void should_append_unregistered_enum_negative() public void should_append_unregistered_enum_large() { _logEvent.AppendEnum(UnregisteredEnumLarge.LargeValue); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(((ulong)UnregisteredEnumLarge.LargeValue).ToString(CultureInfo.InvariantCulture), _output.ToString()); } @@ -155,7 +155,7 @@ public void should_auto_register_enum() LogManager.Config.LazyRegisterEnums = true; _logEvent.AppendEnum(AutoRegisterEnum.Bar); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("Bar", _output.ToString()); } diff --git a/src/ZeroLog.Tests/LogEventTests.KeyValues.cs b/src/ZeroLog.Tests/LogEventTests.KeyValues.cs index ec13ea87..d2843f7c 100644 --- a/src/ZeroLog.Tests/LogEventTests.KeyValues.cs +++ b/src/ZeroLog.Tests/LogEventTests.KeyValues.cs @@ -9,7 +9,7 @@ public partial class LogEventTests public void should_append_single_key_value() { _logEvent.AppendKeyValue("myKey", "myValue"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(" ~~ { \"myKey\": \"myValue\" }", _output.ToString()); } @@ -19,7 +19,7 @@ public void should_append_multiple_key_values() { _logEvent.AppendKeyValue("myKey", "myValue"); _logEvent.AppendKeyValue("otherKey", 2); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(" ~~ { \"myKey\": \"myValue\", \"otherKey\": 2 }", _output.ToString()); } @@ -32,7 +32,7 @@ public void should_append_formatted_string_mixed_with_key_values() _logEvent.AppendFormat("Some {} message"); _logEvent.Append("formatted"); _logEvent.AppendKeyValue("otherKey", 2); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("Some formatted message ~~ { \"myKey\": \"myValue\", \"otherKey\": 2 }", _output.ToString()); } @@ -42,7 +42,7 @@ public void should_be_chainable() { _logEvent.AppendKeyValue("myKey", 1.1f).AppendKeyValue("otherKey", new Guid()); _logEvent.Append("message"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("message ~~ { \"myKey\": 1.1, \"otherKey\": \"00000000-0000-0000-0000-000000000000\" }", _output.ToString()); } @@ -51,7 +51,7 @@ public void should_be_chainable() public void should_support_char() { _logEvent.AppendKeyValue("key1", 'a'); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(" ~~ { \"key1\": \"a\" }", _output.ToString()); } @@ -59,7 +59,7 @@ public void should_support_char() public void should_support_datetime() { _logEvent.AppendKeyValue("key1", DateTime.MinValue); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(" ~~ { \"key1\": \"0001-01-01 00:00:00.000\" }", _output.ToString()); } @@ -67,7 +67,7 @@ public void should_support_datetime() public void should_support_boolean() { _logEvent.AppendKeyValue("key1", true).AppendKeyValue("key2", false); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(" ~~ { \"key1\": true, \"key2\": false }", _output.ToString()); } @@ -75,7 +75,7 @@ public void should_support_boolean() public void should_support_single_null_key_value() { _logEvent.AppendKeyValue("key1", (int?)null); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(" ~~ { \"key1\": null }", _output.ToString()); } @@ -85,7 +85,7 @@ public void should_support_null_string_key_value() _logEvent.AppendKeyValue("key1", "val1") .AppendKeyValue("key2", (string)null) .AppendKeyValue("key3", 3); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(" ~~ { \"key1\": \"val1\", \"key2\": null, \"key3\": 3 }", _output.ToString()); } @@ -100,7 +100,7 @@ public void should_support_number_types() .AppendKeyValue("double", 6.6d) .AppendKeyValue("decimal", 6.6m); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(" ~~ { \"byte\": 1, \"short\": 2, \"int\": 3, \"long\": 4, \"float\": 5.5, \"double\": 6.6, \"decimal\": 6.6 }", _output.ToString()); } @@ -114,7 +114,7 @@ public void should_handle_truncated_key_values() _logEvent.AppendKeyValue($"key{i}", $"value{i}"); } - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual( " ~~ { \"key0\": \"value0\", \"key1\": \"value1\", \"key2\": \"value2\", \"key3\": \"value3\", \"key4\": \"value4\" } [TRUNCATED]", _output.ToString()); @@ -128,7 +128,7 @@ public void should_allocate_space_for_more_key_values() _logEvent.AppendKeyValue($"key{i}", $"value{i}"); } - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual( " ~~ { \"key0\": \"value0\", \"key1\": \"value1\", \"key2\": \"value2\", \"key3\": \"value3\", \"key4\": \"value4\", \"key5\": \"value5\" }", _output.ToString()); @@ -172,7 +172,7 @@ public void should_allocate_space_for_more_key_values() public void should_handle_escaped_characters(char character, string expected) { _logEvent.AppendKeyValue("myKey", character); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(" ~~ { \"myKey\": \"" + expected + "\" }", _output.ToString()); } @@ -189,7 +189,7 @@ public void should_handle_partially_truncated_key_value() _logEvent.AppendKeyValue($"key{i}", $"value{i}"); } - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); // 'key4' is not present because there wasn't space for its value. Assert.AreEqual( @@ -201,7 +201,7 @@ public void should_handle_partially_truncated_key_value() public void should_escape_strings_for_json() { _logEvent.AppendKeyValue("key \\ \" \t \n", "Hello \u0001 \0 there"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual(" ~~ { \"key \\\\ \\\" \\t \\n\": \"Hello \\u0001 \\u0000 there\" }", _output.ToString()); } } diff --git a/src/ZeroLog.Tests/LogEventTests.Unmanaged.cs b/src/ZeroLog.Tests/LogEventTests.Unmanaged.cs index 5572c7a8..87842598 100644 --- a/src/ZeroLog.Tests/LogEventTests.Unmanaged.cs +++ b/src/ZeroLog.Tests/LogEventTests.Unmanaged.cs @@ -38,7 +38,7 @@ public void should_append_unmanaged() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -56,7 +56,7 @@ public void should_append_unmanaged_byref() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -74,7 +74,7 @@ public void should_append_nullable_unmanaged() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -87,7 +87,7 @@ public void should_append_null_nullable_unmanaged() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); } @@ -105,7 +105,7 @@ public void should_append_nullable_unmanaged_byref() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -118,7 +118,7 @@ public void should_append_null_nullable_unmanaged_byref() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); } @@ -152,7 +152,7 @@ public void should_append_unmanaged_2() LogManager.RegisterUnmanaged(typeof(UnmanagedStruct2)); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("1-2-3", _output.ToString()); } @@ -188,7 +188,7 @@ public void should_append_external_unmanaged() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("External(1-2-3)", _output.ToString()); } @@ -206,7 +206,7 @@ public void should_append_external_unmanaged_byref() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("External(1-2-3)", _output.ToString()); } @@ -224,7 +224,7 @@ public void should_append_nullable_external_unmanaged() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("External(1-2-3)", _output.ToString()); } @@ -237,7 +237,7 @@ public void should_append_null_nullable_external_unmanaged() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); } @@ -255,7 +255,7 @@ public void should_append_nullable_external_unmanaged_byref() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("External(1-2-3)", _output.ToString()); } @@ -268,7 +268,7 @@ public void should_append_null_nullable_external_unmanaged_byref() LogManager.RegisterUnmanaged(ExternalUnmanagedStructFormatter); _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); } @@ -291,7 +291,7 @@ public void should_append_unregistered_unmanaged() }; _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("Unmanaged(0x01000000000000000200000003000000)", _output.ToString()); } @@ -307,7 +307,7 @@ public void should_append_unregistered_unmanaged_byref() }; _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("Unmanaged(0x01000000000000000200000003000000)", _output.ToString()); } @@ -323,7 +323,7 @@ public void should_append_unregistered_nullable_unmanaged() }; _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("Unmanaged(0x01000000000000000200000003000000)", _output.ToString()); } @@ -334,7 +334,7 @@ public void should_append_null_unregistered_nullable_unmanaged() UnregisteredUnmanagedStruct? o = null; _logEvent.AppendUnmanaged(o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); } @@ -350,7 +350,7 @@ public void should_append_unregistered_nullable_unmanaged_byref() }; _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("Unmanaged(0x01000000000000000200000003000000)", _output.ToString()); } @@ -361,7 +361,7 @@ public void should_append_null_unregistered_nullable_unmanaged_byref() UnregisteredUnmanagedStruct? o = null; _logEvent.AppendUnmanaged(ref o); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); } @@ -394,7 +394,7 @@ public void should_append_unmanaged_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o, "foo"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("42[foo]", _output.ToString()); } @@ -410,7 +410,7 @@ public void should_append_unmanaged_byref_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o, "foo"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("42[foo]", _output.ToString()); } @@ -426,7 +426,7 @@ public void should_append_nullable_unmanaged_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o, "foo"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("42[foo]", _output.ToString()); } @@ -439,7 +439,7 @@ public void should_append_null_unmanaged_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(o, "foo"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("null", _output.ToString()); } @@ -455,7 +455,7 @@ public void should_append_nullable_unmanaged_byref_with_format() LogManager.RegisterUnmanaged(); _logEvent.AppendUnmanaged(ref o, "foo"); - _logEvent.WriteToStringBuffer(_output, new KeyValuePointerBuffer()); + _logEvent.WriteToStringBuffer(_output); Assert.AreEqual("42[foo]", _output.ToString()); } diff --git a/src/ZeroLog/Config/JsonConfigurator.cs b/src/ZeroLog/Config/JsonConfigurator.cs index 9ef69ed7..7d409ab6 100644 --- a/src/ZeroLog/Config/JsonConfigurator.cs +++ b/src/ZeroLog/Config/JsonConfigurator.cs @@ -54,9 +54,7 @@ private static void ConfigureGlobal(ZeroLogJsonConfiguration config) LogManager.Config.NullDisplayString = config.NullDisplayString; if (config.JsonSeparator != null) - { LogManager.Config.JsonSeparator = config.JsonSeparator; - } } private static ZeroLogJsonConfiguration ConfigureResolver(string configFileFullPath, HierarchicalResolver resolver) diff --git a/src/ZeroLog/ForwardingLogEvent.cs b/src/ZeroLog/ForwardingLogEvent.cs index a6fc1f73..bb464e20 100644 --- a/src/ZeroLog/ForwardingLogEvent.cs +++ b/src/ZeroLog/ForwardingLogEvent.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Text.Formatting; -using JetBrains.Annotations; using ZeroLog.Appenders; namespace ZeroLog diff --git a/src/ZeroLog/LogEvent.cs b/src/ZeroLog/LogEvent.cs index 24f00756..725719eb 100644 --- a/src/ZeroLog/LogEvent.cs +++ b/src/ZeroLog/LogEvent.cs @@ -338,9 +338,11 @@ public void WriteToStringBuffer(StringBuffer stringBuffer, KeyValuePointerBuffer var endOfData = _dataPointer; var dataPointer = _startOfBuffer; + keyValuePointerBuffer.Clear(); + while (dataPointer < endOfData) { - if (!ConsumeKeyValue(ref dataPointer, keyValuePointerBuffer, endOfData)) + if (!ConsumeKeyValue(ref dataPointer, keyValuePointerBuffer)) stringBuffer.Append(ref dataPointer, StringView.Empty, _strings, _argPointers, _argCount); } @@ -353,21 +355,12 @@ public void WriteToStringBuffer(StringBuffer stringBuffer, KeyValuePointerBuffer stringBuffer.Append(LogManager.Config.TruncatedMessageSuffix); } - private static bool ConsumeKeyValue(ref byte* dataPointer, KeyValuePointerBuffer keyValuePointerBuffer, byte* endOfData) + private static bool ConsumeKeyValue(ref byte* dataPointer, KeyValuePointerBuffer keyValuePointerBuffer) { var argumentType = (ArgumentType)(*dataPointer & ArgumentTypeMask.ArgumentType); - if (argumentType != ArgumentType.KeyString) return false; - // If the last item in the data is a key, that means there we ran out of space and couldn't include the value. - // In this case, skip the key, and don't use it to build JSON later. - if (dataPointer + sizeof(ArgumentType) + sizeof(byte) == endOfData) - { - SkipCurrentArgument(ref dataPointer); - return true; - } - // Save a pointer to the key for later when we append the Key/Value JSON. keyValuePointerBuffer.AddKeyPointer(dataPointer); @@ -448,9 +441,11 @@ private static void SkipCurrentArgument(ref byte* dataPointer) case ArgumentType.Null: break; + case ArgumentType.FormatString: case ArgumentType.Unmanaged: throw new NotSupportedException($"Type is not supported {argumentType}"); + default: throw new ArgumentOutOfRangeException(); } @@ -486,14 +481,10 @@ private void AppendArgumentToStringBufferUnformatted(StringBuffer stringBuffer, if (hasFormatSpecifier) dataPointer += sizeof(byte); // Skip it - AppendUnformattedArgumentValue(stringBuffer, argumentType, ref dataPointer); - } - - private void AppendUnformattedArgumentValue(StringBuffer stringBuffer, ArgumentType argumentType, ref byte* dataPointer) - { switch (argumentType) { case ArgumentType.String: + case ArgumentType.KeyString: stringBuffer.Append('"'); stringBuffer.Append(_strings[*dataPointer]); stringBuffer.Append('"'); diff --git a/src/ZeroLog/LogManager.cs b/src/ZeroLog/LogManager.cs index ec404d13..37110c6d 100644 --- a/src/ZeroLog/LogManager.cs +++ b/src/ZeroLog/LogManager.cs @@ -1,13 +1,11 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Text.Formatting; using System.Threading; -using JetBrains.Annotations; using ZeroLog.Appenders; using ZeroLog.ConfigResolvers; using ZeroLog.Utils; @@ -34,7 +32,6 @@ public class LogManager : IInternalLogManager private bool _isRunning; private IAppender[] _appenders = Array.Empty(); - private readonly KeyValuePointerBuffer _keyValuePointerBuffer = new KeyValuePointerBuffer(); public static ZeroLogConfig Config { get; } = new ZeroLogConfig(); @@ -234,11 +231,12 @@ private void WriteToAppenders() var spinWait = new SpinWait(); var stringBuffer = new StringBuffer(OutputBufferSize); var destination = new byte[OutputBufferSize]; + var keyValuePointerBuffer = new KeyValuePointerBuffer(); var flush = false; while (_isRunning || !_queue.IsEmpty) { - if (TryToProcessQueue(stringBuffer, destination)) + if (TryToProcessQueue(stringBuffer, destination, keyValuePointerBuffer)) { spinWait.Reset(); flush = true; @@ -259,7 +257,7 @@ private void WriteToAppenders() FlushAppenders(); } - private bool TryToProcessQueue(StringBuffer stringBuffer, byte[] destination) + private bool TryToProcessQueue(StringBuffer stringBuffer, byte[] destination, KeyValuePointerBuffer keyValuePointerBuffer) { if (!_queue.TryDequeue(out var logEvent)) return false; @@ -276,7 +274,8 @@ private bool TryToProcessQueue(StringBuffer stringBuffer, byte[] destination) try { - FormatLogMessage(stringBuffer, logEvent); + stringBuffer.Clear(); + logEvent.WriteToStringBuffer(stringBuffer, keyValuePointerBuffer); bytesWritten = CopyStringBufferToByteArray(stringBuffer, destination); } catch (Exception ex) @@ -326,13 +325,6 @@ private static void WriteMessageLogToAppenders(byte[] destination, IInternalLogE } } - private void FormatLogMessage(StringBuffer stringBuffer, IInternalLogEvent logEvent) - { - stringBuffer.Clear(); - _keyValuePointerBuffer.Clear(); - logEvent.WriteToStringBuffer(stringBuffer, _keyValuePointerBuffer); - } - private static unsafe int CopyStringBufferToByteArray(StringBuffer stringBuffer, byte[] destination) { fixed (byte* dest = &destination[0]) diff --git a/src/ZeroLog/NoopLogEvent.cs b/src/ZeroLog/NoopLogEvent.cs index 9237cd57..c891a4b8 100644 --- a/src/ZeroLog/NoopLogEvent.cs +++ b/src/ZeroLog/NoopLogEvent.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Text.Formatting; using ZeroLog.Appenders;