Skip to content

Commit

Permalink
Merge pull request #60 from serilog/cleanup
Browse files Browse the repository at this point in the history
cleanup
  • Loading branch information
nblumhardt authored Sep 27, 2022
2 parents 7ce1441 + 7ac5c58 commit ce315cf
Show file tree
Hide file tree
Showing 32 changed files with 1,639 additions and 1,697 deletions.
20 changes: 20 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project>
<!-- Workaround for https://github.com/dotnet/sdk/pull/908 -->
<Target Name="GetPackagingOutputs" />
<PropertyGroup>
<LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../../assets/Serilog.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="all" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
</Project>
7 changes: 7 additions & 0 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Project>

<ItemGroup>
<Using Remove="System.Net.Http" />
</ItemGroup>

</Project>
1 change: 1 addition & 0 deletions serilog-sinks-periodicbatching.sln
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sln", "sln", "{E49CF29C-764
README.md = README.md
RunPerfTests.ps1 = RunPerfTests.ps1
global.json = global.json
Directory.Build.props = Directory.Build.props
EndProjectSection
EndProject
Global
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Reflection;
using System.Reflection;
using System.Runtime.CompilerServices;

[assembly: AssemblyVersion("3.0.0.0")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,13 @@
<TargetFrameworks>net45;netstandard1.1;netstandard1.2;netstandard2.0;netstandard2.1</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<RootNamespace>Serilog</RootNamespace>
<AssemblyOriginatorKeyFile>../../assets/Serilog.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageTags>serilog;batching;timer</PackageTags>
<PackageIcon>icon.png</PackageIcon>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/serilog/serilog-sinks-periodicbatching</PackageProjectUrl>
<RepositoryUrl>https://github.com/serilog/serilog-sinks-periodicbatching</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.2' ">
Expand All @@ -40,7 +33,6 @@
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="all" />
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,84 +12,81 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using System;

namespace Serilog.Sinks.PeriodicBatching
namespace Serilog.Sinks.PeriodicBatching;

/// <summary>
/// Manages reconnection period and transient fault response for <see cref="PeriodicBatchingSink"/>.
/// During normal operation an object of this type will simply echo the configured batch transmission
/// period. When availability fluctuates, the class tracks the number of failed attempts, each time
/// increasing the interval before reconnection is attempted (up to a set maximum) and at predefined
/// points indicating that either the current batch, or entire waiting queue, should be dropped. This
/// Serves two purposes - first, a loaded receiver may need a temporary reduction in traffic while coming
/// back online. Second, the sender needs to account for both bad batches (the first fault response) and
/// also overproduction (the second, queue-dropping response). In combination these should provide a
/// reasonable delivery effort but ultimately protect the sender from memory exhaustion.
/// </summary>
/// <remarks>
/// Currently used only by <see cref="PeriodicBatchingSink"/>, but may
/// provide the basis for a "smart" exponential backoff timer. There are other factors to consider
/// including the desire to send batches "when full" rather than continuing to buffer, and so-on.
/// </remarks>
class BatchedConnectionStatus
{
/// <summary>
/// Manages reconnection period and transient fault response for <see cref="PeriodicBatchingSink"/>.
/// During normal operation an object of this type will simply echo the configured batch transmission
/// period. When availability fluctuates, the class tracks the number of failed attempts, each time
/// increasing the interval before reconnection is attempted (up to a set maximum) and at predefined
/// points indicating that either the current batch, or entire waiting queue, should be dropped. This
/// Serves two purposes - first, a loaded receiver may need a temporary reduction in traffic while coming
/// back online. Second, the sender needs to account for both bad batches (the first fault response) and
/// also overproduction (the second, queue-dropping response). In combination these should provide a
/// reasonable delivery effort but ultimately protect the sender from memory exhaustion.
/// </summary>
/// <remarks>
/// Currently used only by <see cref="PeriodicBatchingSink"/>, but may
/// provide the basis for a "smart" exponential backoff timer. There are other factors to consider
/// including the desire to send batches "when full" rather than continuing to buffer, and so-on.
/// </remarks>
class BatchedConnectionStatus
{
static readonly TimeSpan MinimumBackoffPeriod = TimeSpan.FromSeconds(5);
static readonly TimeSpan MaximumBackoffInterval = TimeSpan.FromMinutes(10);
static readonly TimeSpan MinimumBackoffPeriod = TimeSpan.FromSeconds(5);
static readonly TimeSpan MaximumBackoffInterval = TimeSpan.FromMinutes(10);

const int FailuresBeforeDroppingBatch = 8;
const int FailuresBeforeDroppingQueue = 10;
const int FailuresBeforeDroppingBatch = 8;
const int FailuresBeforeDroppingQueue = 10;

readonly TimeSpan _period;
readonly TimeSpan _period;

int _failuresSinceSuccessfulBatch;
int _failuresSinceSuccessfulBatch;

public BatchedConnectionStatus(TimeSpan period)
{
if (period < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(period), "The batching period must be a positive timespan");
public BatchedConnectionStatus(TimeSpan period)
{
if (period < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(period), "The batching period must be a positive timespan");

_period = period;
}
_period = period;
}

public void MarkSuccess()
{
_failuresSinceSuccessfulBatch = 0;
}
public void MarkSuccess()
{
_failuresSinceSuccessfulBatch = 0;
}

public void MarkFailure()
{
++_failuresSinceSuccessfulBatch;
}
public void MarkFailure()
{
++_failuresSinceSuccessfulBatch;
}

public TimeSpan NextInterval
public TimeSpan NextInterval
{
get
{
get
{
// Available, and first failure, just try the batch interval
if (_failuresSinceSuccessfulBatch <= 1) return _period;
// Available, and first failure, just try the batch interval
if (_failuresSinceSuccessfulBatch <= 1) return _period;

// Second failure, start ramping up the interval - first 2x, then 4x, ...
var backoffFactor = Math.Pow(2, (_failuresSinceSuccessfulBatch - 1));
// Second failure, start ramping up the interval - first 2x, then 4x, ...
var backoffFactor = Math.Pow(2, _failuresSinceSuccessfulBatch - 1);

// If the period is ridiculously short, give it a boost so we get some
// visible backoff.
var backoffPeriod = Math.Max(_period.Ticks, MinimumBackoffPeriod.Ticks);
// If the period is ridiculously short, give it a boost so we get some
// visible backoff.
var backoffPeriod = Math.Max(_period.Ticks, MinimumBackoffPeriod.Ticks);

// The "ideal" interval
var backedOff = (long) (backoffPeriod * backoffFactor);
// The "ideal" interval
var backedOff = (long) (backoffPeriod * backoffFactor);

// Capped to the maximum interval
var cappedBackoff = Math.Min(MaximumBackoffInterval.Ticks, backedOff);
// Capped to the maximum interval
var cappedBackoff = Math.Min(MaximumBackoffInterval.Ticks, backedOff);

// Unless that's shorter than the period, in which case we'll just apply the period
var actual = Math.Max(_period.Ticks, cappedBackoff);
// Unless that's shorter than the period, in which case we'll just apply the period
var actual = Math.Max(_period.Ticks, cappedBackoff);

return TimeSpan.FromTicks(actual);
}
return TimeSpan.FromTicks(actual);
}
}

public bool ShouldDropBatch => _failuresSinceSuccessfulBatch >= FailuresBeforeDroppingBatch;
public bool ShouldDropBatch => _failuresSinceSuccessfulBatch >= FailuresBeforeDroppingBatch;

public bool ShouldDropQueue => _failuresSinceSuccessfulBatch >= FailuresBeforeDroppingQueue;
}
}
public bool ShouldDropQueue => _failuresSinceSuccessfulBatch >= FailuresBeforeDroppingQueue;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,76 +12,73 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Collections.Concurrent;
using System.Threading;

namespace Serilog.Sinks.PeriodicBatching
namespace Serilog.Sinks.PeriodicBatching;

class BoundedConcurrentQueue<T>
{
class BoundedConcurrentQueue<T>
{
const int Unbounded = -1;
const int Unbounded = -1;

readonly ConcurrentQueue<T> _queue = new();
readonly int _queueLimit;
readonly ConcurrentQueue<T> _queue = new();
readonly int _queueLimit;

int _counter;
int _counter;

public BoundedConcurrentQueue(int? queueLimit = null)
{
if (queueLimit.HasValue && queueLimit <= 0)
throw new ArgumentOutOfRangeException(nameof(queueLimit), "Queue limit must be positive, or `null` to indicate unbounded.");
public BoundedConcurrentQueue(int? queueLimit = null)
{
if (queueLimit.HasValue && queueLimit <= 0)
throw new ArgumentOutOfRangeException(nameof(queueLimit), "Queue limit must be positive, or `null` to indicate unbounded.");

_queueLimit = queueLimit ?? Unbounded;
}
_queueLimit = queueLimit ?? Unbounded;
}

public int Count => _queue.Count;
public int Count => _queue.Count;

public bool TryDequeue(out T item)
{
if (_queueLimit == Unbounded)
return _queue.TryDequeue(out item);
public bool TryDequeue(out T item)
{
if (_queueLimit == Unbounded)
return _queue.TryDequeue(out item);

var result = false;
try
{ }
finally // prevent state corrupt while aborting
var result = false;
try
{ }
finally // prevent state corrupt while aborting
{
if (_queue.TryDequeue(out item))
{
if (_queue.TryDequeue(out item))
{
Interlocked.Decrement(ref _counter);
result = true;
}
Interlocked.Decrement(ref _counter);
result = true;
}
}

return result;
}

return result;
public bool TryEnqueue(T item)
{
if (_queueLimit == Unbounded)
{
_queue.Enqueue(item);
return true;
}

public bool TryEnqueue(T item)
var result = true;
try
{ }
finally
{
if (_queueLimit == Unbounded)
if (Interlocked.Increment(ref _counter) <= _queueLimit)
{
_queue.Enqueue(item);
return true;
}

var result = true;
try
{ }
finally
else
{
if (Interlocked.Increment(ref _counter) <= _queueLimit)
{
_queue.Enqueue(item);
}
else
{
Interlocked.Decrement(ref _counter);
result = false;
}
Interlocked.Decrement(ref _counter);
result = false;
}

return result;
}

return result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using System.Collections.Generic;
using System.Threading.Tasks;
using Serilog.Events;

namespace Serilog.Sinks.PeriodicBatching
namespace Serilog.Sinks.PeriodicBatching;

/// <summary>
/// Interface for targets that accept events in batches.
/// </summary>
public interface IBatchedLogEventSink
{
/// <summary>
/// Interface for targets that accept events in batches.
/// Emit a batch of log events, running asynchronously.
/// </summary>
public interface IBatchedLogEventSink
{
/// <summary>
/// Emit a batch of log events, running asynchronously.
/// </summary>
/// <param name="batch">The batch of events to emit.</param>
Task EmitBatchAsync(IEnumerable<LogEvent> batch);
/// <param name="batch">The batch of events to emit.</param>
Task EmitBatchAsync(IEnumerable<LogEvent> batch);

/// <summary>
/// Allows sinks to perform periodic work without requiring additional threads
/// or timers (thus avoiding additional flush/shut-down complexity).
/// </summary>
Task OnEmptyBatchAsync();
}
}
/// <summary>
/// Allows sinks to perform periodic work without requiring additional threads
/// or timers (thus avoiding additional flush/shut-down complexity).
/// </summary>
Task OnEmptyBatchAsync();
}
Loading

0 comments on commit ce315cf

Please sign in to comment.