Skip to content

Commit 7ceda92

Browse files
authored
Merge pull request #151 from serilog-contrib/dev
update with latest
2 parents 539d490 + ad0c3f2 commit 7ceda92

File tree

12 files changed

+1034
-657
lines changed

12 files changed

+1034
-657
lines changed

.github/workflows/build.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ jobs:
5353
run: 'dotnet build --no-restore --configuration Release'
5454

5555
- name: Test Project
56-
run: 'dotnet test --no-build --no-restore --configuration Release'
56+
run: 'dotnet test --no-build --configuration Release'
5757

5858
- name: Create Packages
5959
if: success() && github.event_name != 'pull_request'
60-
run: 'dotnet pack --configuration Release --include-symbols --include-source --no-build --no-restore --output "${{env.BUILD_PATH}}"'
60+
run: 'dotnet pack --configuration Release --no-build --output "${{env.BUILD_PATH}}"'
6161

6262
- name: Upload Packages
6363
if: success() && github.event_name != 'pull_request'

samples/SampleWebApplication/Pages/Logs.cshtml

+2-2
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@
182182
asp-page="/Logs"
183183
asp-route-z="@Model.PageSize"
184184
asp-route-l="@Model.Level"
185-
asp-route-d="@Model.Date.Date"
185+
asp-route-d="@Model.Date"
186186
asp-route-t="">First</a>
187187
</li>
188188
}
@@ -199,7 +199,7 @@
199199
asp-page="/Logs"
200200
asp-route-z="@Model.PageSize"
201201
asp-route-l="@Model.Level"
202-
asp-route-d="@Model.Date.Date"
202+
asp-route-d="@Model.Date"
203203
asp-route-t="@Model.NextToken">Next</a>
204204
</li>
205205
}

samples/SampleWebApplication/Pages/Logs.cshtml.cs

+3-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
using SampleWebApplication.Models;
77

8-
using Serilog.Sinks.AzureTableStorage.Extensions;
8+
using Serilog.Sinks.AzureTableStorage;
99

1010
namespace SampleWebApplication.Pages;
1111

@@ -25,7 +25,7 @@ public LogsModel(TableServiceClient tableServiceClient)
2525
public string? Level { get; set; } = string.Empty;
2626

2727
[BindProperty(Name = "d", SupportsGet = true)]
28-
public DateTime Date { get; set; } = DateTime.Today;
28+
public DateOnly Date { get; set; } = DateOnly.FromDateTime(DateTime.Today);
2929

3030
[BindProperty(Name = "t", SupportsGet = true)]
3131
public string ContinuationToken { get; set; } = string.Empty;
@@ -38,11 +38,7 @@ public async Task<IActionResult> OnGetAsync(CancellationToken cancellationToken)
3838
{
3939
var logTable = _tableServiceClient.GetTableClient("SampleLog");
4040

41-
var dateTime = Date.Date.ToUniversalTime();
42-
var upper = dateTime.GeneratePartitionKey();
43-
var lower = dateTime.AddDays(1).GeneratePartitionKey();
44-
45-
var filter = $"({nameof(ITableEntity.PartitionKey)} ge '{lower}') and ({nameof(ITableEntity.PartitionKey)} lt '{upper}')";
41+
var filter = DefaultKeyGenerator.GeneratePartitionKeyQuery(Date);
4642

4743
if (!string.IsNullOrWhiteSpace(Level))
4844
filter += $" and ({nameof(LogEventModel.Level)} eq '{Level}')";

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

+13-2
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,22 @@
1616
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
1717
<RepositoryUrl>https://github.com/serilog-contrib/serilog-sinks-azuretablestorage.git</RepositoryUrl>
1818
<RepositoryType>git</RepositoryType>
19+
<PublishRepositoryUrl>true</PublishRepositoryUrl>
1920
<GenerateDocumentationFile>true</GenerateDocumentationFile>
2021
<RootNamespace>Serilog</RootNamespace>
2122
<LangVersion>latest</LangVersion>
2223
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
23-
<Copyright>Copyright © Serilog Contributors 2023</Copyright>
24+
<Copyright>Copyright © Serilog Contributors 2024</Copyright>
25+
</PropertyGroup>
26+
27+
<PropertyGroup Label="Debug">
28+
<DebugType>embedded</DebugType>
29+
<EmbedUntrackedSources>true</EmbedUntrackedSources>
30+
<IncludeSymbols>false</IncludeSymbols>
31+
</PropertyGroup>
32+
33+
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
34+
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
2435
</PropertyGroup>
2536

2637
<ItemGroup>
@@ -43,7 +54,7 @@
4354
<ItemGroup>
4455
<PackageReference Include="MinVer" Version="5.0.0" PrivateAssets="All" />
4556
<PackageReference Include="Serilog" Version="3.1.1" />
46-
<PackageReference Include="Serilog.Sinks.PeriodicBatching" Version="4.0.1" />
57+
<PackageReference Include="Serilog.Sinks.PeriodicBatching" Version="4.1.0" />
4758
<PackageReference Include="Azure.Data.Tables" Version="12.8.3" />
4859
<PackageReference Include="ulid" Version="1.3.3" />
4960
</ItemGroup>

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

+121-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
using System;
2+
using System.Dynamic;
23
using System.Threading;
34

5+
using Azure.Data.Tables;
6+
47
using Serilog.Events;
58
using Serilog.Sinks.AzureTableStorage.Extensions;
69

@@ -9,8 +12,10 @@ namespace Serilog.Sinks.AzureTableStorage;
912
/// <summary>
1013
/// Default document key generator
1114
/// </summary>
15+
/// <seealso cref="Serilog.Sinks.AzureTableStorage.IKeyGenerator" />
1216
public class DefaultKeyGenerator : IKeyGenerator
1317
{
18+
private const string PartitionKeyName = nameof(ITableEntity.PartitionKey);
1419

1520
/// <summary>
1621
/// Automatically generates the PartitionKey based on the logEvent timestamp
@@ -28,7 +33,7 @@ public virtual string GeneratePartitionKey(LogEvent logEvent, AzureTableStorageS
2833
// batch insert is used to get around time based partition key performance issues
2934
// values are created in reverse chronological order so newest are always first
3035

31-
var utcEventTime = logEvent.Timestamp.UtcDateTime;
36+
var utcEventTime = logEvent.Timestamp;
3237
var partitionKeyRounding = options?.PartitionKeyRounding;
3338

3439
return GeneratePartitionKey(utcEventTime, partitionKeyRounding);
@@ -47,45 +52,149 @@ public virtual string GenerateRowKey(LogEvent logEvent, AzureTableStorageSinkOpt
4752

4853
// row key created in reverse chronological order so newest are always first
4954

50-
var utcEventTime = logEvent.Timestamp.UtcDateTime;
55+
var utcEventTime = logEvent.Timestamp;
5156
return GenerateRowKey(utcEventTime);
5257
}
5358

5459

55-
5660
/// <summary>
57-
/// Generates the PartitionKey based on the logEvent timestamp
61+
/// Generates the PartitionKey based on the specified <paramref name="eventTime"/> timestamp
5862
/// </summary>
59-
/// <param name="utcEventTime">The UTC event time.</param>
63+
/// <param name="eventTime">The event time.</param>
6064
/// <param name="roundSpan">The round span.</param>
6165
/// <returns>
6266
/// The Generated PartitionKey
6367
/// </returns>
6468
/// <remarks>
6569
/// The partition key based on the Timestamp rounded to the nearest 5 min
6670
/// </remarks>
67-
public static string GeneratePartitionKey(DateTime utcEventTime, TimeSpan? roundSpan = null)
71+
public static string GeneratePartitionKey(DateTimeOffset eventTime, TimeSpan? roundSpan = null)
6872
{
6973
var span = roundSpan ?? TimeSpan.FromMinutes(5);
70-
var roundedEvent = utcEventTime.Round(span);
74+
var dateTime = eventTime.ToUniversalTime();
75+
var roundedEvent = dateTime.Round(span);
7176

7277
// create a 19 character String for reverse chronological ordering.
73-
return $"{DateTime.MaxValue.Ticks - roundedEvent.Ticks:D19}";
78+
return $"{DateTimeOffset.MaxValue.Ticks - roundedEvent.Ticks:D19}";
7479
}
7580

7681
/// <summary>
77-
/// Generates the RowKey using the timestamp
82+
/// Generates the PartitionKey based on the specified <paramref name="eventTime"/> timestamp
7883
/// </summary>
79-
/// <param name="utcEventTime">The UTC event time.</param>
84+
/// <param name="eventTime">The event time.</param>
85+
/// <param name="roundSpan">The round span.</param>
86+
/// <returns>
87+
/// The Generated PartitionKey
88+
/// </returns>
89+
/// <remarks>
90+
/// The partition key based on the Timestamp rounded to the nearest 5 min
91+
/// </remarks>
92+
public static string GeneratePartitionKey(DateTime eventTime, TimeSpan? roundSpan = null)
93+
{
94+
var dateTime = eventTime.ToUniversalTime();
95+
var dateTimeOffset = new DateTimeOffset(dateTime, TimeSpan.Zero);
96+
97+
return GeneratePartitionKey(dateTimeOffset, roundSpan);
98+
}
99+
100+
101+
/// <summary>
102+
/// Generates the RowKey using a reverse chronological ordering date, newest logs sorted first
103+
/// </summary>
104+
/// <param name="eventTime">The event time.</param>
80105
/// <returns>
81106
/// The generated RowKey
82107
/// </returns>
83-
public static string GenerateRowKey(DateTime utcEventTime)
108+
public static string GenerateRowKey(DateTimeOffset eventTime)
84109
{
110+
var dateTime = eventTime.ToUniversalTime();
111+
85112
// create a reverse chronological ordering date, newest logs sorted first
86-
var timestamp = utcEventTime.ToReverseChronological();
113+
var timestamp = dateTime.ToReverseChronological();
87114

88115
// use Ulid for speed and efficiency
89116
return Ulid.NewUlid(timestamp).ToString();
90117
}
118+
119+
/// <summary>
120+
/// Generates the RowKey using a reverse chronological ordering date, newest logs sorted first
121+
/// </summary>
122+
/// <param name="eventTime">The event time.</param>
123+
/// <returns>
124+
/// The generated RowKey
125+
/// </returns>
126+
public static string GenerateRowKey(DateTime eventTime)
127+
{
128+
var dateTime = eventTime.ToUniversalTime();
129+
var dateTimeOffset = new DateTimeOffset(dateTime, TimeSpan.Zero);
130+
131+
return GenerateRowKey(dateTimeOffset);
132+
}
133+
134+
135+
#if NET6_0_OR_GREATER
136+
/// <summary>
137+
/// Generates the partition key query using the specified <paramref name="date"/>.
138+
/// </summary>
139+
/// <param name="date">The date to use for query.</param>
140+
/// <param name="offset">The date's offset from Coordinated Universal Time (UTC).</param>
141+
/// <returns>An Azure Table partiion key query.</returns>
142+
public static string GeneratePartitionKeyQuery(DateOnly date, TimeSpan offset)
143+
{
144+
// date is assumed to be in local time, will be converted to UTC
145+
var startTime = new DateTimeOffset(date.Year, date.Month, date.Day, 0, 0, 0, offset);
146+
var endTime = startTime.AddDays(1);
147+
148+
return GeneratePartitionKeyQuery(startTime, endTime);
149+
}
150+
151+
/// <summary>
152+
/// Generates the partition key query using the specified <paramref name="date"/>.
153+
/// </summary>
154+
/// <param name="date">The date to use for query.</param>
155+
/// <param name="zone">The time zone the date is in.</param>
156+
/// <returns>An Azure Table partiion key query.</returns>
157+
public static string GeneratePartitionKeyQuery(DateOnly date, TimeZoneInfo zone = null)
158+
{
159+
// date is assumed to be in local time, will be converted to UTC
160+
var startTime = date.ToDateTimeOffset(zone);
161+
var endTime = date.AddDays(1).ToDateTimeOffset(zone);
162+
163+
return GeneratePartitionKeyQuery(startTime, endTime);
164+
}
165+
#endif
166+
167+
/// <summary>
168+
/// Generates the partition key query using the specified <paramref name="startDate"/> and <paramref name="endDate"/>.
169+
/// </summary>
170+
/// <param name="startDate">The start date to use for query.</param>
171+
/// <param name="endDate">The end date to use for query.</param>
172+
/// <returns>An Azure Table partiion key query.</returns>
173+
public static string GeneratePartitionKeyQuery(DateTime startDate, DateTime endDate)
174+
{
175+
var startTime = startDate.ToUniversalTime();
176+
var startTimeOffset = new DateTimeOffset(startTime, TimeSpan.Zero);
177+
178+
var endTime = endDate.ToUniversalTime();
179+
var endTimeOffset = new DateTimeOffset(endTime, TimeSpan.Zero);
180+
181+
return GeneratePartitionKeyQuery(startTimeOffset, endTimeOffset);
182+
}
183+
184+
/// <summary>
185+
/// Generates the partition key query using the specified <paramref name="startDate"/> and <paramref name="endDate"/>.
186+
/// </summary>
187+
/// <param name="startDate">The start date to use for query.</param>
188+
/// <param name="endDate">The end date to use for query.</param>
189+
/// <returns>An Azure Table partiion key query.</returns>
190+
public static string GeneratePartitionKeyQuery(DateTimeOffset startDate, DateTimeOffset endDate)
191+
{
192+
var startTime = startDate.ToUniversalTime();
193+
var endTime = endDate.ToUniversalTime();
194+
195+
var upper = startTime.ToReverseChronological().Ticks.ToString("D19");
196+
var lower = endTime.ToReverseChronological().Ticks.ToString("D19");
197+
198+
return $"({PartitionKeyName} ge '{lower}') and ({PartitionKeyName} lt '{upper}')";
199+
}
91200
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System;
2+
3+
namespace Serilog.Sinks.AzureTableStorage.Extensions;
4+
5+
#if NET6_0_OR_GREATER
6+
/// <summary>
7+
/// Extension methods for <see cref="DateOnly"/>
8+
/// </summary>
9+
public static class DateOnlyExtensions
10+
{
11+
/// <summary>
12+
/// Converts the <see cref="DateOnly"/> to a <see cref="DateTimeOffset"/> in the specified timezone.
13+
/// </summary>
14+
/// <param name="dateOnly">The date to convert.</param>
15+
/// <param name="zone">The time zone the date is in.</param>
16+
/// <returns>The converted <see cref="DateTimeOffset"/></returns>
17+
public static DateTimeOffset ToDateTimeOffset(this DateOnly dateOnly, TimeZoneInfo zone = null)
18+
{
19+
zone ??= TimeZoneInfo.Local;
20+
21+
var dateTime = dateOnly.ToDateTime(TimeOnly.MinValue);
22+
var offset = zone.GetUtcOffset(dateTime);
23+
24+
return new DateTimeOffset(dateTime, offset);
25+
}
26+
27+
/// <summary>
28+
/// Converts the <see cref="DateTimeOffset"/> to a <see cref="DateOnly"/> in the specified timezone.
29+
/// </summary>
30+
/// <param name="dateTime">The <see cref="DateTimeOffset"/> to convert.</param>
31+
/// <param name="zone">The time zone the date is in.</param>
32+
/// <returns>The converted <see cref="DateOnly"/></returns>
33+
public static DateOnly ToDateOnly(this DateTimeOffset dateTime, TimeZoneInfo zone = null)
34+
{
35+
zone ??= TimeZoneInfo.Local;
36+
37+
var targetZone = TimeZoneInfo.ConvertTime(dateTime, zone);
38+
return DateOnly.FromDateTime(targetZone.Date);
39+
}
40+
}
41+
#endif

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

-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ public static class DateTimeExtensions
1818
/// <remarks>
1919
/// The partition key based on the Timestamp rounded to the nearest 5 min
2020
/// </remarks>
21-
[Obsolete("Use DefaultKeyGenerator instead")]
2221
public static string GeneratePartitionKey(this DateTime utcEventTime, TimeSpan? roundSpan = null)
2322
{
2423
return DefaultKeyGenerator.GeneratePartitionKey(utcEventTime, roundSpan);
@@ -31,7 +30,6 @@ public static string GeneratePartitionKey(this DateTime utcEventTime, TimeSpan?
3130
/// <returns>
3231
/// The generated RowKey
3332
/// </returns>
34-
[Obsolete("Use DefaultKeyGenerator instead")]
3533
public static string GenerateRowKey(this DateTime utcEventTime)
3634
{
3735
return DefaultKeyGenerator.GenerateRowKey(utcEventTime);

0 commit comments

Comments
 (0)