Skip to content

Commit

Permalink
Merge pull request #145 from serilog-contrib/dev
Browse files Browse the repository at this point in the history
use ULID for rowkey for speed and efficiency
  • Loading branch information
pwelter34 authored Apr 10, 2024
2 parents 268a778 + cf12599 commit 539d490
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 40 deletions.
2 changes: 1 addition & 1 deletion samples/SampleWebApplication/Pages/Logs.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
<td>@log.RenderedMessage</td>
</tr>
<tr class="collapse" id="[email protected]" style="background-color: #f9f9f9;">
<td colspan="5">
<td colspan="6">
<div class="tab-container">
<ul class="nav nav-tabs" id="[email protected]" role="tablist">
<li class="nav-item" role="presentation">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
<ItemGroup>
<PackageReference Include="MinVer" Version="5.0.0" PrivateAssets="All" />
<PackageReference Include="Serilog" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.PeriodicBatching" Version="4.0.0" />
<PackageReference Include="Serilog.Sinks.PeriodicBatching" Version="4.0.1" />
<PackageReference Include="Azure.Data.Tables" Version="12.8.3" />
<PackageReference Include="ulid" Version="1.3.3" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public virtual string GeneratePartitionKey(LogEvent logEvent, AzureTableStorageS
var utcEventTime = logEvent.Timestamp.UtcDateTime;
var partitionKeyRounding = options?.PartitionKeyRounding;

return utcEventTime.GeneratePartitionKey(partitionKeyRounding);
return GeneratePartitionKey(utcEventTime, partitionKeyRounding);
}

/// <summary>
Expand All @@ -48,7 +48,7 @@ public virtual string GenerateRowKey(LogEvent logEvent, AzureTableStorageSinkOpt
// row key created in reverse chronological order so newest are always first

var utcEventTime = logEvent.Timestamp.UtcDateTime;
return utcEventTime.GenerateRowKey();
return GenerateRowKey(utcEventTime);
}


Expand All @@ -67,7 +67,7 @@ public virtual string GenerateRowKey(LogEvent logEvent, AzureTableStorageSinkOpt
public static string GeneratePartitionKey(DateTime utcEventTime, TimeSpan? roundSpan = null)
{
var span = roundSpan ?? TimeSpan.FromMinutes(5);
var roundedEvent = Round(utcEventTime, span);
var roundedEvent = utcEventTime.Round(span);

// create a 19 character String for reverse chronological ordering.
return $"{DateTime.MaxValue.Ticks - roundedEvent.Ticks:D19}";
Expand All @@ -82,37 +82,10 @@ public static string GeneratePartitionKey(DateTime utcEventTime, TimeSpan? round
/// </returns>
public static string GenerateRowKey(DateTime utcEventTime)
{
// create a reverse chronological ordering date
var targetTicks = DateTime.MaxValue.Ticks - utcEventTime.Ticks;
// create a reverse chronological ordering date, newest logs sorted first
var timestamp = utcEventTime.ToReverseChronological();

// add incrementing value to ensure unique
int padding = Next();

return $"{targetTicks:D19}{padding:D4}";
// use Ulid for speed and efficiency
return Ulid.NewUlid(timestamp).ToString();
}

/// <summary>
/// Rounds the specified date.
/// </summary>
/// <param name="date">The date to round.</param>
/// <param name="span">The span.</param>
/// <returns>The rounded date</returns>
public static DateTime Round(DateTime date, TimeSpan span)
{
long ticks = (date.Ticks + (span.Ticks / 2) + 1) / span.Ticks;
return new DateTime(ticks * span.Ticks);
}


private static int _counter = new Random().Next(_minCounter, _maxCounter);

private const int _minCounter = 1;
private const int _maxCounter = 9999;

private static int Next()
{
Interlocked.Increment(ref _counter);
return Interlocked.CompareExchange(ref _counter, _minCounter, _maxCounter);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ namespace Serilog.Sinks.AzureTableStorage.Extensions;
/// </summary>
public static class DateTimeExtensions
{

/// <summary>
/// Generates the PartitionKey based on the logEvent timestamp
/// </summary>
Expand All @@ -19,6 +18,7 @@ public static class DateTimeExtensions
/// <remarks>
/// The partition key based on the Timestamp rounded to the nearest 5 min
/// </remarks>
[Obsolete("Use DefaultKeyGenerator instead")]
public static string GeneratePartitionKey(this DateTime utcEventTime, TimeSpan? roundSpan = null)
{
return DefaultKeyGenerator.GeneratePartitionKey(utcEventTime, roundSpan);
Expand All @@ -31,19 +31,56 @@ public static string GeneratePartitionKey(this DateTime utcEventTime, TimeSpan?
/// <returns>
/// The generated RowKey
/// </returns>
[Obsolete("Use DefaultKeyGenerator instead")]
public static string GenerateRowKey(this DateTime utcEventTime)
{
return DefaultKeyGenerator.GenerateRowKey(utcEventTime);
}

/// <summary>
/// Rounds the specified date.
/// Rounds the date to the specified time span.
/// </summary>
/// <param name="date">The date to round.</param>
/// <param name="span">The span.</param>
/// <param name="span">The time span to round to.</param>
/// <returns>The rounded date</returns>
public static DateTime Round(this DateTime date, TimeSpan span)
{
return DefaultKeyGenerator.Round(date, span);
long ticks = (date.Ticks + (span.Ticks / 2) + 1) / span.Ticks;
return new DateTime(ticks * span.Ticks);
}

/// <summary>
/// Rounds the date to the specified span.
/// </summary>
/// <param name="date">The date to round.</param>
/// <param name="span">The time span to round to.</param>
/// <returns>The rounded date</returns>
public static DateTimeOffset Round(this DateTimeOffset date, TimeSpan span)
{
long ticks = (date.Ticks + (span.Ticks / 2) + 1) / span.Ticks;
return new DateTimeOffset(ticks * span.Ticks, date.Offset);
}

/// <summary>
/// Converts to specified <paramref name="dateTime"/> to its reverse chronological equivalent. DateTime.MaxValue - dateTime
/// </summary>
/// <param name="dateTime">The date time offset.</param>
/// <returns>A <see cref="DateTime"/> chronological reversed.</returns>
public static DateTime ToReverseChronological(this DateTime dateTime)
{
var targetTicks = DateTime.MaxValue.Ticks - dateTime.Ticks;
return new DateTime(targetTicks);
}

/// <summary>
/// Converts to specified <paramref name="dateTimeOffset"/> to its reverse chronological equivalent. DateTimeOffset.MaxValue - dateTimeOffset
/// </summary>
/// <param name="dateTimeOffset">The date time offset.</param>
/// <returns>A <see cref="DateTimeOffset"/> chronological reversed.</returns>
public static DateTimeOffset ToReverseChronological(this DateTimeOffset dateTimeOffset)
{
var targetTicks = DateTimeOffset.MaxValue.Ticks - dateTimeOffset.Ticks;
return new DateTimeOffset(targetTicks, TimeSpan.Zero);
}

}

0 comments on commit 539d490

Please sign in to comment.