Skip to content

Commit 539d490

Browse files
authored
Merge pull request #145 from serilog-contrib/dev
use ULID for rowkey for speed and efficiency
2 parents 268a778 + cf12599 commit 539d490

File tree

4 files changed

+51
-40
lines changed

4 files changed

+51
-40
lines changed

samples/SampleWebApplication/Pages/Logs.cshtml

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119
<td>@log.RenderedMessage</td>
120120
</tr>
121121
<tr class="collapse" id="[email protected]" style="background-color: #f9f9f9;">
122-
<td colspan="5">
122+
<td colspan="6">
123123
<div class="tab-container">
124124
<ul class="nav nav-tabs" id="[email protected]" role="tablist">
125125
<li class="nav-item" role="presentation">

src/Serilog.Sinks.AzureTableStorage/Serilog.Sinks.AzureTableStorage.csproj

+2-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
<ItemGroup>
4444
<PackageReference Include="MinVer" Version="5.0.0" PrivateAssets="All" />
4545
<PackageReference Include="Serilog" Version="3.1.1" />
46-
<PackageReference Include="Serilog.Sinks.PeriodicBatching" Version="4.0.0" />
46+
<PackageReference Include="Serilog.Sinks.PeriodicBatching" Version="4.0.1" />
4747
<PackageReference Include="Azure.Data.Tables" Version="12.8.3" />
48+
<PackageReference Include="ulid" Version="1.3.3" />
4849
</ItemGroup>
4950
</Project>

src/Serilog.Sinks.AzureTableStorage/Sinks/AzureTableStorage/DefaultKeyGenerator.cs

+7-34
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public virtual string GeneratePartitionKey(LogEvent logEvent, AzureTableStorageS
3131
var utcEventTime = logEvent.Timestamp.UtcDateTime;
3232
var partitionKeyRounding = options?.PartitionKeyRounding;
3333

34-
return utcEventTime.GeneratePartitionKey(partitionKeyRounding);
34+
return GeneratePartitionKey(utcEventTime, partitionKeyRounding);
3535
}
3636

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

5050
var utcEventTime = logEvent.Timestamp.UtcDateTime;
51-
return utcEventTime.GenerateRowKey();
51+
return GenerateRowKey(utcEventTime);
5252
}
5353

5454

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

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

88-
// add incrementing value to ensure unique
89-
int padding = Next();
90-
91-
return $"{targetTicks:D19}{padding:D4}";
88+
// use Ulid for speed and efficiency
89+
return Ulid.NewUlid(timestamp).ToString();
9290
}
93-
94-
/// <summary>
95-
/// Rounds the specified date.
96-
/// </summary>
97-
/// <param name="date">The date to round.</param>
98-
/// <param name="span">The span.</param>
99-
/// <returns>The rounded date</returns>
100-
public static DateTime Round(DateTime date, TimeSpan span)
101-
{
102-
long ticks = (date.Ticks + (span.Ticks / 2) + 1) / span.Ticks;
103-
return new DateTime(ticks * span.Ticks);
104-
}
105-
106-
107-
private static int _counter = new Random().Next(_minCounter, _maxCounter);
108-
109-
private const int _minCounter = 1;
110-
private const int _maxCounter = 9999;
111-
112-
private static int Next()
113-
{
114-
Interlocked.Increment(ref _counter);
115-
return Interlocked.CompareExchange(ref _counter, _minCounter, _maxCounter);
116-
}
117-
11891
}

src/Serilog.Sinks.AzureTableStorage/Sinks/AzureTableStorage/Extensions/DateTimeExtensions.cs

+41-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ namespace Serilog.Sinks.AzureTableStorage.Extensions;
77
/// </summary>
88
public static class DateTimeExtensions
99
{
10-
1110
/// <summary>
1211
/// Generates the PartitionKey based on the logEvent timestamp
1312
/// </summary>
@@ -19,6 +18,7 @@ public static class DateTimeExtensions
1918
/// <remarks>
2019
/// The partition key based on the Timestamp rounded to the nearest 5 min
2120
/// </remarks>
21+
[Obsolete("Use DefaultKeyGenerator instead")]
2222
public static string GeneratePartitionKey(this DateTime utcEventTime, TimeSpan? roundSpan = null)
2323
{
2424
return DefaultKeyGenerator.GeneratePartitionKey(utcEventTime, roundSpan);
@@ -31,19 +31,56 @@ public static string GeneratePartitionKey(this DateTime utcEventTime, TimeSpan?
3131
/// <returns>
3232
/// The generated RowKey
3333
/// </returns>
34+
[Obsolete("Use DefaultKeyGenerator instead")]
3435
public static string GenerateRowKey(this DateTime utcEventTime)
3536
{
3637
return DefaultKeyGenerator.GenerateRowKey(utcEventTime);
3738
}
3839

3940
/// <summary>
40-
/// Rounds the specified date.
41+
/// Rounds the date to the specified time span.
4142
/// </summary>
4243
/// <param name="date">The date to round.</param>
43-
/// <param name="span">The span.</param>
44+
/// <param name="span">The time span to round to.</param>
4445
/// <returns>The rounded date</returns>
4546
public static DateTime Round(this DateTime date, TimeSpan span)
4647
{
47-
return DefaultKeyGenerator.Round(date, span);
48+
long ticks = (date.Ticks + (span.Ticks / 2) + 1) / span.Ticks;
49+
return new DateTime(ticks * span.Ticks);
50+
}
51+
52+
/// <summary>
53+
/// Rounds the date to the specified span.
54+
/// </summary>
55+
/// <param name="date">The date to round.</param>
56+
/// <param name="span">The time span to round to.</param>
57+
/// <returns>The rounded date</returns>
58+
public static DateTimeOffset Round(this DateTimeOffset date, TimeSpan span)
59+
{
60+
long ticks = (date.Ticks + (span.Ticks / 2) + 1) / span.Ticks;
61+
return new DateTimeOffset(ticks * span.Ticks, date.Offset);
4862
}
63+
64+
/// <summary>
65+
/// Converts to specified <paramref name="dateTime"/> to its reverse chronological equivalent. DateTime.MaxValue - dateTime
66+
/// </summary>
67+
/// <param name="dateTime">The date time offset.</param>
68+
/// <returns>A <see cref="DateTime"/> chronological reversed.</returns>
69+
public static DateTime ToReverseChronological(this DateTime dateTime)
70+
{
71+
var targetTicks = DateTime.MaxValue.Ticks - dateTime.Ticks;
72+
return new DateTime(targetTicks);
73+
}
74+
75+
/// <summary>
76+
/// Converts to specified <paramref name="dateTimeOffset"/> to its reverse chronological equivalent. DateTimeOffset.MaxValue - dateTimeOffset
77+
/// </summary>
78+
/// <param name="dateTimeOffset">The date time offset.</param>
79+
/// <returns>A <see cref="DateTimeOffset"/> chronological reversed.</returns>
80+
public static DateTimeOffset ToReverseChronological(this DateTimeOffset dateTimeOffset)
81+
{
82+
var targetTicks = DateTimeOffset.MaxValue.Ticks - dateTimeOffset.Ticks;
83+
return new DateTimeOffset(targetTicks, TimeSpan.Zero);
84+
}
85+
4986
}

0 commit comments

Comments
 (0)