-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
189 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
src/TableStorage.Abstracts/Extensions/DateTimeExtentions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace TableStorage.Abstracts.Extensions; | ||
|
||
public static class DateTimeExtentions | ||
{ | ||
/// <summary> | ||
/// Rounds the date to the specified time 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 DateTime Round(this DateTime date, TimeSpan 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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
namespace TableStorage.Abstracts.Tests.Models; | ||
|
||
public class LogEvent : TableEntityBase | ||
{ | ||
public string? Level { get; set; } | ||
|
||
public string? MessageTemplate { get; set; } | ||
|
||
public string? RenderedMessage { get; set; } | ||
|
||
public string? Exception { get; set; } | ||
|
||
public string? Data { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
test/TableStorage.Abstracts.Tests/Services/ILogEventRepository.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using TableStorage.Abstracts.Tests.Models; | ||
|
||
namespace TableStorage.Abstracts.Tests.Services; | ||
|
||
public interface ILogEventRepository : ITableRepository<LogEvent> | ||
{ | ||
Task<PagedResult<LogEvent>> QueryByDate( | ||
DateOnly date, | ||
string? level = null, | ||
string? continuationToken = null, | ||
int? pageSize = 100, | ||
CancellationToken cancellationToken = default); | ||
} |
65 changes: 65 additions & 0 deletions
65
test/TableStorage.Abstracts.Tests/Services/LogEventRepository.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
using Azure.Data.Tables; | ||
|
||
using Microsoft.Extensions.Logging; | ||
|
||
using TableStorage.Abstracts.Extensions; | ||
using TableStorage.Abstracts.Tests.Models; | ||
|
||
namespace TableStorage.Abstracts.Tests.Services; | ||
|
||
public class LogEventRepository : TableRepository<LogEvent>, ILogEventRepository | ||
{ | ||
public LogEventRepository(ILoggerFactory logFactory, TableServiceClient tableServiceClient) | ||
: base(logFactory, tableServiceClient) | ||
{ | ||
} | ||
|
||
public async Task<PagedResult<LogEvent>> QueryByDate( | ||
DateOnly date, | ||
string? level = null, | ||
string? continuationToken = null, | ||
int? pageSize = 100, | ||
CancellationToken cancellationToken = default) | ||
{ | ||
var baseDate = date.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc); | ||
|
||
var upperDate = baseDate.ToReverseChronological(); | ||
var lowwerDate = baseDate.AddDays(1).ToReverseChronological(); | ||
|
||
var upper = $"{upperDate.Ticks:D19}"; | ||
var lower = $"{lowwerDate.Ticks:D19}"; | ||
|
||
var filter = $"(PartitionKey ge '{lower}') and (PartitionKey lt '{upper}')"; | ||
|
||
if (level.HasValue()) | ||
filter += $" and (Level eq '{level}')"; | ||
|
||
return await FindPageAsync(filter, continuationToken, pageSize, cancellationToken); | ||
} | ||
|
||
public override string NewRowKey() | ||
{ | ||
// store newest log first | ||
var timestamp = DateTimeOffset.UtcNow.ToReverseChronological(); | ||
return Ulid.NewUlid(timestamp).ToString(); | ||
} | ||
|
||
protected override void BeforeSave(LogEvent entity) | ||
{ | ||
if (entity.RowKey.IsNullOrWhiteSpace()) | ||
entity.RowKey = NewRowKey(); | ||
|
||
if (entity.PartitionKey.IsNullOrWhiteSpace()) | ||
{ | ||
var timespan = entity.Timestamp ?? DateTimeOffset.UtcNow; | ||
var roundedDate = timespan | ||
.Round(TimeSpan.FromMinutes(5)) | ||
.ToReverseChronological(); | ||
|
||
// create a 19 character String for reverse chronological ordering. | ||
entity.PartitionKey = $"{roundedDate.Ticks:D19}"; | ||
} | ||
} | ||
|
||
protected override string GetTableName() => "LogEvent"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
using TableStorage.Abstracts.Extensions; | ||
|
||
namespace TableStorage.Abstracts.Tests; | ||
|
||
public class UlidGeneratorTests | ||
{ | ||
private readonly ITestOutputHelper _output; | ||
|
||
public UlidGeneratorTests(ITestOutputHelper output) | ||
{ | ||
_output = output; | ||
} | ||
|
||
[Fact] | ||
public void UlidTests() | ||
{ | ||
var timestamp = DateTimeOffset.UtcNow.ToReverseChronological(); | ||
|
||
var previousKey = Ulid.NewUlid(timestamp).ToString(); | ||
|
||
// higher dates should be lower sort | ||
for (int i = 0; i < 100; i++) | ||
{ | ||
timestamp = DateTimeOffset.UtcNow.ToReverseChronological(); | ||
var key = Ulid.NewUlid(timestamp).ToString(); | ||
key.Should().NotBeNull(); | ||
|
||
_output.WriteLine(key); | ||
|
||
string.Compare(key, previousKey).Should().BeLessThan(0); | ||
} | ||
} | ||
} |