Browse Source

Logging performance improved.

pull/426/head
Sebastian Stehle 6 years ago
parent
commit
4d1a20288d
  1. 76
      src/Squidex.Infrastructure/Log/JsonLogWriter.cs
  2. 11
      src/Squidex.Infrastructure/Log/JsonLogWriterFactory.cs
  3. 1
      src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
  4. 7
      src/Squidex/Config/Logging.cs
  5. 4
      tests/Squidex.Infrastructure.Tests/Log/JsonLogWriterTests.cs

76
src/Squidex.Infrastructure/Log/JsonLogWriter.cs

@ -7,137 +7,136 @@
using System; using System;
using System.IO; using System.IO;
using Newtonsoft.Json; using System.Text;
using System.Text.Json;
using NodaTime; using NodaTime;
namespace Squidex.Infrastructure.Log namespace Squidex.Infrastructure.Log
{ {
public sealed class JsonLogWriter : IObjectWriter, IArrayWriter public sealed class JsonLogWriter : IObjectWriter, IArrayWriter
{ {
private readonly Formatting formatting; private readonly JsonWriterOptions formatting;
private readonly bool formatLine; private readonly bool formatLine;
private readonly StringWriter textWriter = new StringWriter(); private readonly MemoryStream stream = new MemoryStream();
private JsonWriter jsonWriter; private readonly StreamReader streamReader;
private Utf8JsonWriter jsonWriter;
public int BufferSize public long BufferSize
{ {
get { return textWriter.GetStringBuilder().Capacity; } get { return stream.Length; }
} }
internal JsonLogWriter(Formatting formatting, bool formatLine) internal JsonLogWriter(JsonWriterOptions formatting, bool formatLine)
{ {
this.formatLine = formatLine; this.formatLine = formatLine;
this.formatting = formatting; this.formatting = formatting;
streamReader = new StreamReader(stream, Encoding.UTF8);
Start(); Start();
} }
private void Start() private void Start()
{ {
jsonWriter = new JsonTextWriter(textWriter) { Formatting = formatting }; jsonWriter = new Utf8JsonWriter(stream, formatting);
jsonWriter.WriteStartObject(); jsonWriter.WriteStartObject();
} }
internal void Reset() internal void Reset()
{ {
textWriter.GetStringBuilder().Clear(); stream.Position = 0;
stream.SetLength(0);
Start(); Start();
} }
IArrayWriter IArrayWriter.WriteValue(string value) IArrayWriter IArrayWriter.WriteValue(string value)
{ {
jsonWriter.WriteValue(value); jsonWriter.WriteStringValue(value);
return this; return this;
} }
IArrayWriter IArrayWriter.WriteValue(double value) IArrayWriter IArrayWriter.WriteValue(double value)
{ {
jsonWriter.WriteValue(value); jsonWriter.WriteNumberValue(value);
return this; return this;
} }
IArrayWriter IArrayWriter.WriteValue(long value) IArrayWriter IArrayWriter.WriteValue(long value)
{ {
jsonWriter.WriteValue(value); jsonWriter.WriteNumberValue(value);
return this; return this;
} }
IArrayWriter IArrayWriter.WriteValue(bool value) IArrayWriter IArrayWriter.WriteValue(bool value)
{ {
jsonWriter.WriteValue(value); jsonWriter.WriteBooleanValue(value);
return this; return this;
} }
IArrayWriter IArrayWriter.WriteValue(Instant value) IArrayWriter IArrayWriter.WriteValue(Instant value)
{ {
jsonWriter.WriteValue(value.ToString()); jsonWriter.WriteStringValue(value.ToString());
return this; return this;
} }
IArrayWriter IArrayWriter.WriteValue(TimeSpan value) IArrayWriter IArrayWriter.WriteValue(TimeSpan value)
{ {
jsonWriter.WriteValue(value.ToString()); jsonWriter.WriteStringValue(value.ToString());
return this; return this;
} }
IObjectWriter IObjectWriter.WriteProperty(string property, string value) IObjectWriter IObjectWriter.WriteProperty(string property, string value)
{ {
jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteString(property, value);
jsonWriter.WriteValue(value);
return this; return this;
} }
IObjectWriter IObjectWriter.WriteProperty(string property, double value) IObjectWriter IObjectWriter.WriteProperty(string property, double value)
{ {
jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteNumber(property, value);
jsonWriter.WriteValue(value);
return this; return this;
} }
IObjectWriter IObjectWriter.WriteProperty(string property, long value) IObjectWriter IObjectWriter.WriteProperty(string property, long value)
{ {
jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteNumber(property, value);
jsonWriter.WriteValue(value);
return this; return this;
} }
IObjectWriter IObjectWriter.WriteProperty(string property, bool value) IObjectWriter IObjectWriter.WriteProperty(string property, bool value)
{ {
jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteBoolean(property, value);
jsonWriter.WriteValue(value);
return this; return this;
} }
IObjectWriter IObjectWriter.WriteProperty(string property, Instant value) IObjectWriter IObjectWriter.WriteProperty(string property, Instant value)
{ {
jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteString(property, value.ToString());
jsonWriter.WriteValue(value.ToString());
return this; return this;
} }
IObjectWriter IObjectWriter.WriteProperty(string property, TimeSpan value) IObjectWriter IObjectWriter.WriteProperty(string property, TimeSpan value)
{ {
jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteString(property, value.ToString());
jsonWriter.WriteValue(value.ToString());
return this; return this;
} }
IObjectWriter IObjectWriter.WriteObject(string property, Action<IObjectWriter> objectWriter) IObjectWriter IObjectWriter.WriteObject(string property, Action<IObjectWriter> objectWriter)
{ {
jsonWriter.WritePropertyName(Format(property)); jsonWriter.WritePropertyName(property);
jsonWriter.WriteStartObject(); jsonWriter.WriteStartObject();
objectWriter?.Invoke(this); objectWriter?.Invoke(this);
@ -149,7 +148,7 @@ namespace Squidex.Infrastructure.Log
IObjectWriter IObjectWriter.WriteObject<T>(string property, T context, Action<T, IObjectWriter> objectWriter) IObjectWriter IObjectWriter.WriteObject<T>(string property, T context, Action<T, IObjectWriter> objectWriter)
{ {
jsonWriter.WritePropertyName(Format(property)); jsonWriter.WritePropertyName(property);
jsonWriter.WriteStartObject(); jsonWriter.WriteStartObject();
objectWriter?.Invoke(context, this); objectWriter?.Invoke(context, this);
@ -161,7 +160,7 @@ namespace Squidex.Infrastructure.Log
IObjectWriter IObjectWriter.WriteArray(string property, Action<IArrayWriter> arrayWriter) IObjectWriter IObjectWriter.WriteArray(string property, Action<IArrayWriter> arrayWriter)
{ {
jsonWriter.WritePropertyName(Format(property)); jsonWriter.WritePropertyName(property);
jsonWriter.WriteStartArray(); jsonWriter.WriteStartArray();
arrayWriter?.Invoke(this); arrayWriter?.Invoke(this);
@ -173,7 +172,7 @@ namespace Squidex.Infrastructure.Log
IObjectWriter IObjectWriter.WriteArray<T>(string property, T context, Action<T, IArrayWriter> arrayWriter) IObjectWriter IObjectWriter.WriteArray<T>(string property, T context, Action<T, IArrayWriter> arrayWriter)
{ {
jsonWriter.WritePropertyName(Format(property)); jsonWriter.WritePropertyName(property);
jsonWriter.WriteStartArray(); jsonWriter.WriteStartArray();
arrayWriter?.Invoke(context, this); arrayWriter?.Invoke(context, this);
@ -205,21 +204,22 @@ namespace Squidex.Infrastructure.Log
return this; return this;
} }
private static string Format(string property)
{
return property;
}
public override string ToString() public override string ToString()
{ {
jsonWriter.WriteEndObject(); jsonWriter.WriteEndObject();
jsonWriter.Flush();
stream.Position = 0;
streamReader.DiscardBufferedData();
var json = streamReader.ReadToEnd();
if (formatLine) if (formatLine)
{ {
textWriter.WriteLine(); json += Environment.NewLine;
} }
return textWriter.ToString(); return json;
} }
} }
} }

11
src/Squidex.Infrastructure/Log/JsonLogWriterFactory.cs

@ -6,7 +6,7 @@
// ========================================================================== // ==========================================================================
using System.Collections.Concurrent; using System.Collections.Concurrent;
using Newtonsoft.Json; using System.Text.Json;
namespace Squidex.Infrastructure.Log namespace Squidex.Infrastructure.Log
{ {
@ -15,12 +15,13 @@ namespace Squidex.Infrastructure.Log
private const int MaxPoolSize = 10; private const int MaxPoolSize = 10;
private const int MaxCapacity = 5000; private const int MaxCapacity = 5000;
private readonly ConcurrentStack<JsonLogWriter> pool = new ConcurrentStack<JsonLogWriter>(); private readonly ConcurrentStack<JsonLogWriter> pool = new ConcurrentStack<JsonLogWriter>();
private readonly Formatting formatting; private readonly JsonWriterOptions formatting;
private readonly bool formatLine; private readonly bool formatLine;
public JsonLogWriterFactory(Formatting formatting = Formatting.None, bool formatLine = false) public JsonLogWriterFactory(bool indended = false, bool formatLine = false)
{ {
this.formatting = formatting; formatting.Indented = indended;
this.formatLine = formatLine; this.formatLine = formatLine;
} }
@ -31,7 +32,7 @@ namespace Squidex.Infrastructure.Log
public static JsonLogWriterFactory Readable() public static JsonLogWriterFactory Readable()
{ {
return new JsonLogWriterFactory(Formatting.Indented, true); return new JsonLogWriterFactory(true, true);
} }
public IObjectWriter Create() public IObjectWriter Create()

1
src/Squidex.Infrastructure/Squidex.Infrastructure.csproj

@ -32,6 +32,7 @@
<PackageReference Include="System.Reactive" Version="4.1.6" /> <PackageReference Include="System.Reactive" Version="4.1.6" />
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.5.1" /> <PackageReference Include="System.Reflection.TypeExtensions" Version="4.5.1" />
<PackageReference Include="System.Security.Claims" Version="4.3.0" /> <PackageReference Include="System.Security.Claims" Version="4.3.0" />
<PackageReference Include="System.Text.Json" Version="4.6.0" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="4.9.0" /> <PackageReference Include="System.Threading.Tasks.Dataflow" Version="4.9.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" /> <PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup> </ItemGroup>

7
src/Squidex/Config/Logging.cs

@ -18,6 +18,11 @@ namespace Squidex.Config
{ {
builder.AddFilter((category, level) => builder.AddFilter((category, level) =>
{ {
if (level < LogLevel.Information)
{
return false;
}
if (category.StartsWith("Orleans.", StringComparison.OrdinalIgnoreCase)) if (category.StartsWith("Orleans.", StringComparison.OrdinalIgnoreCase))
{ {
var subCategory = category.AsSpan().Slice(8); var subCategory = category.AsSpan().Slice(8);
@ -55,7 +60,7 @@ namespace Squidex.Config
return true; return true;
} }
#endif #endif
return level >= LogLevel.Information; return true;
}); });
} }
} }

4
tests/Squidex.Infrastructure.Tests/Log/JsonLogWriterTests.cs

@ -159,7 +159,7 @@ namespace Squidex.Infrastructure.Log
[Fact] [Fact]
public void Should_write_pretty_json() public void Should_write_pretty_json()
{ {
var prettySut = new JsonLogWriterFactory(Formatting.Indented).Create(); var prettySut = new JsonLogWriterFactory(true).Create();
var result = prettySut.WriteProperty("property", 1.5).ToString(); var result = prettySut.WriteProperty("property", 1.5).ToString();
@ -169,7 +169,7 @@ namespace Squidex.Infrastructure.Log
[Fact] [Fact]
public void Should_write_extra_line_after_object() public void Should_write_extra_line_after_object()
{ {
var prettySut = new JsonLogWriterFactory(Formatting.None, true).Create(); var prettySut = new JsonLogWriterFactory(false, true).Create();
var result = prettySut.WriteProperty("property", 1.5).ToString(); var result = prettySut.WriteProperty("property", 1.5).ToString();

Loading…
Cancel
Save