Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7981cd3

Browse files
committed
Implement dashboard log query for PostgreSQL provider.
Improved handling of data providers in `AggregateDataProvider.cs` with added guard clauses and a new `SelectedDataProvider` property. Updated `IDataProvider.cs` to include a method for fetching dashboard statistics asynchronously. Streamlined log data fetching in `ElasticSearchDbDataProvider.cs`, `MongoDbDataProvider.cs`, and `SqlServerDataProvider.cs` for better readability and maintainability.Introduced a new `DashboardModel` class in `LogStatisticModel.cs` for structured dashboard statistics. Added comprehensive tests in `DataProviderDashboardTests.cs` to ensure correct functionality. Refactored various test files for better organization and clarity.
1 parent8b1977a commit7981cd3

File tree

17 files changed

+744
-434
lines changed

17 files changed

+744
-434
lines changed
Lines changed: 58 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,79 @@
1-
usingSystem;
1+
usingArdalis.GuardClauses;
2+
usingSerilog.Ui.Core.Models;
3+
usingSystem;
24
usingSystem.Collections.Generic;
35
usingSystem.Linq;
46
usingSystem.Threading;
57
usingSystem.Threading.Tasks;
6-
usingArdalis.GuardClauses;
7-
usingSerilog.Ui.Core.Models;
88

9-
namespaceSerilog.Ui.Core
9+
namespaceSerilog.Ui.Core;
10+
11+
/// <summary>
12+
/// Aggregates multiple <see cref="IDataProvider" /> into one instance.
13+
/// </summary>
14+
publicclassAggregateDataProvider:IDataProvider
1015
{
16+
privatereadonlyDictionary<string,IDataProvider>_dataProviders=new();
17+
1118
/// <summary>
12-
///Aggregates multiple<see cref="IDataProvider"/> into one instance.
19+
/// It creates an instance of<see cref="AggregateDataProvider" />.
1320
/// </summary>
14-
publicclassAggregateDataProvider:IDataProvider
21+
/// <param name="dataProviders">IEnumerable of providers.</param>
22+
/// <exception cref="ArgumentNullException">when <paramref name="dataProviders" /> is null</exception>
23+
/// <exception cref="ArgumentException">when <paramref name="dataProviders" /> is empty</exception>
24+
publicAggregateDataProvider(IEnumerable<IDataProvider>dataProviders)
1525
{
16-
privatereadonlyDictionary<string,IDataProvider>_dataProviders=new();
26+
List<IDataProvider>providers=Guard.Against.NullOrEmpty(dataProviders).ToList();
1727

18-
/// <summary>
19-
/// It creates an instance of <see cref="AggregateDataProvider"/>.
20-
/// </summary>
21-
/// <param name="dataProviders">IEnumerable of providers.</param>
22-
/// <exception cref="ArgumentNullException">when <paramref name="dataProviders"/> is null</exception>
23-
/// <exception cref="ArgumentException">when <paramref name="dataProviders"/> is empty</exception>
24-
publicAggregateDataProvider(IEnumerable<IDataProvider>dataProviders)
28+
foreach(List<IDataProvider>?groupedinproviders.GroupBy(dp=>dp.Name, p=>p,(_,e)=>e.ToList()))
2529
{
26-
varproviders=Guard.Against.NullOrEmpty(dataProviders).ToList();
27-
28-
foreach(vargroupedinproviders.GroupBy(dp=>dp.Name, p=>p,(_,e)=>e.ToList()))
29-
{
30-
varname=grouped[0].Name;
30+
stringname=grouped[0].Name;
3131

32-
if(grouped.Count==1)
32+
if(grouped.Count==1)
33+
_dataProviders.Add(name,grouped[0]);
34+
else
35+
// When providers with the same name are registered, we ensure uniqueness by
36+
// generating a key I.e. ["MSSQL.dbo.logs", "MSSQL.dbo.logs"] =>
37+
// ["MSSQL.dbo.logs[0]", "MSSQL.dbo.logs[1]"]
38+
for(inti=0;i<grouped.Count;i++)
3339
{
34-
_dataProviders.Add(name,grouped[0]);
40+
IDataProvider?dataProvider=grouped[i];
41+
_dataProviders.Add($"{name}[{i}]",dataProvider);
3542
}
36-
else
37-
{
38-
// When providers with the same name are registered, we ensure uniqueness by
39-
// generating a key I.e. ["MSSQL.dbo.logs", "MSSQL.dbo.logs"] =>
40-
// ["MSSQL.dbo.logs[0]", "MSSQL.dbo.logs[1]"]
41-
for(vari=0;i<grouped.Count;i++)
42-
{
43-
vardataProvider=grouped[i];
44-
_dataProviders.Add($"{name}[{i}]",dataProvider);
45-
}
46-
}
47-
}
48-
49-
SelectedDataProvider=_dataProviders.First().Value;
5043
}
5144

52-
/// <summary>
53-
/// <inheritdoc cref="IDataProvider.Name"/>
54-
/// NOTE: We assume only one Aggregate provider, so the name is static.
55-
/// </summary>
56-
publicstringName=>nameof(AggregateDataProvider);
45+
SelectedDataProvider=_dataProviders.First().Value;
46+
}
47+
48+
/// <summary>
49+
/// If there is only one data provider, this is it.
50+
/// If there are multiple, this is the current data provider.
51+
/// </summary>
52+
privateIDataProviderSelectedDataProvider{get;set;}
53+
54+
/// <summary>
55+
/// Existing data providers keys.
56+
/// </summary>
57+
publicIEnumerable<string>Keys=>_dataProviders.Keys;
5758

58-
/// <summary>
59-
///If there is only one data provider, this is it.
60-
/// If there are multiple, this isthecurrent data provider.
61-
/// </summary>
62-
privateIDataProviderSelectedDataProvider{get;set;}
59+
/// <summary>
60+
/// <inheritdoc cref="IDataProvider.Name" />
61+
/// NOTE: We assume only one Aggregate provider, sothename is static.
62+
/// </summary>
63+
publicstringName=>nameof(AggregateDataProvider);
6364

64-
/// <summary>
65-
/// Switch active data provider by key.
66-
/// </summary>
67-
/// <param name="key">Data provider key</param>
68-
publicvoidSwitchToProvider(stringkey)=>SelectedDataProvider=_dataProviders[key];
65+
/// <inheritdoc />
66+
publicTask<(IEnumerable<LogModel>,int)>FetchDataAsync(FetchLogsQueryqueryParams,
67+
CancellationTokencancellationToken=default)
68+
=>SelectedDataProvider.FetchDataAsync(queryParams,cancellationToken);
6969

70-
/// <summary>
71-
/// Existing data providers keys.
72-
/// </summary>
73-
publicIEnumerable<string>Keys=>_dataProviders.Keys;
70+
/// <inheritdoc />
71+
publicTask<DashboardModel>FetchDashboardAsync(CancellationTokencancellationToken=default)
72+
=>SelectedDataProvider.FetchDashboardAsync(cancellationToken);
7473

75-
/// <inheritdoc/>
76-
publicTask<(IEnumerable<LogModel>,int)>FetchDataAsync(FetchLogsQueryqueryParams,CancellationTokencancellationToken=default)
77-
=>SelectedDataProvider.FetchDataAsync(queryParams,cancellationToken);
78-
}
74+
/// <summary>
75+
/// Switch active data provider by key.
76+
/// </summary>
77+
/// <param name="key">Data provider key</param>
78+
publicvoidSwitchToProvider(stringkey)=>SelectedDataProvider=_dataProviders[key];
7979
}

‎src/Serilog.Ui.Core/IDataProvider.cs‎

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,26 @@
33
usingSystem.Threading.Tasks;
44
usingSerilog.Ui.Core.Models;
55

6-
namespaceSerilog.Ui.Core
6+
namespaceSerilog.Ui.Core;
7+
8+
/// <summary>
9+
/// Data provider interface
10+
/// </summary>
11+
publicinterfaceIDataProvider
712
{
813
/// <summary>
9-
/// Data provider interface
14+
/// Name of the provider, used to identify this provider when using multiple.
15+
/// </summary>
16+
stringName{get;}
17+
18+
/// <summary>
19+
/// Fetches the log data asynchronous.
1020
/// </summary>
11-
publicinterfaceIDataProvider
12-
{
13-
/// <summary>
14-
/// Fetches the log data asynchronous.
15-
/// </summary>
16-
Task<(IEnumerable<LogModel>results,inttotal)>FetchDataAsync(FetchLogsQueryqueryParams,CancellationTokencancellationToken=default);
21+
Task<(IEnumerable<LogModel>results,inttotal)>FetchDataAsync(FetchLogsQueryqueryParams,
22+
CancellationTokencancellationToken=default);
1723

18-
/// <summary>
19-
/// Name of the provider, used to identify this provider when using multiple.
20-
/// </summary>
21-
stringName{get;}
22-
}
24+
/// <summary>
25+
/// Fetches dashboard statistics asynchronous.
26+
/// </summary>
27+
Task<DashboardModel>FetchDashboardAsync(CancellationTokencancellationToken=default);
2328
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
usingSystem.Collections.Generic;
2+
3+
namespaceSerilog.Ui.Core.Models;
4+
5+
/// <summary>
6+
/// Represents dashboard statistics for log data visualization.
7+
/// </summary>
8+
publicclassDashboardModel
9+
{
10+
/// <summary>
11+
/// Gets or sets the total count of logs.
12+
/// </summary>
13+
publicintTotalLogs{get;set;}
14+
15+
/// <summary>
16+
/// Gets or sets the count of logs by level.
17+
/// </summary>
18+
publicDictionary<string,int>LogsByLevel{get;set;}=new();
19+
20+
/// <summary>
21+
/// Gets or sets the count of logs for today.
22+
/// </summary>
23+
publicintTodayLogs{get;set;}
24+
25+
/// <summary>
26+
/// Gets or sets the count of error logs for today.
27+
/// </summary>
28+
publicintTodayErrorLogs{get;set;}
29+
}

‎src/Serilog.Ui.ElasticSearchProvider/ElasticSearchDbDataProvider.cs‎

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
usingSystem;
1+
usingNest;
2+
usingNewtonsoft.Json;
3+
usingSerilog.Ui.Core;
4+
usingSerilog.Ui.Core.Models;
5+
usingSystem;
26
usingSystem.Collections.Generic;
37
usingSystem.Linq;
48
usingSystem.Reflection;
59
usingSystem.Threading;
610
usingSystem.Threading.Tasks;
7-
usingNest;
8-
usingNewtonsoft.Json;
9-
usingSerilog.Ui.Core;
10-
usingSerilog.Ui.Core.Models;
1111
usingstaticSerilog.Ui.Core.Models.SearchOptions;
1212

1313
namespaceSerilog.Ui.ElasticSearchProvider;
@@ -24,35 +24,40 @@ public class ElasticSearchDbDataProvider(IElasticClient client, ElasticSearchDbO
2424

2525
privatereadonlyElasticSearchDbOptions_options=options??thrownewArgumentNullException(nameof(options));
2626

27-
publicTask<(IEnumerable<LogModel>,int)>FetchDataAsync(FetchLogsQueryqueryParams,CancellationTokencancellationToken=default)
28-
{
29-
returnGetLogsAsync(queryParams,cancellationToken);
30-
}
27+
publicTask<(IEnumerable<LogModel>,int)>FetchDataAsync(FetchLogsQueryqueryParams,
28+
CancellationTokencancellationToken=default)=>GetLogsAsync(queryParams,cancellationToken);
29+
30+
publicTask<DashboardModel>FetchDashboardAsync(CancellationTokencancellationToken=default)=>
31+
thrownewNotImplementedException();
3132

3233
publicstringName=>_options.ProviderName;
3334

34-
privateasyncTask<(IEnumerable<LogModel>,int)>GetLogsAsync(FetchLogsQueryqueryParams,CancellationTokencancellationToken=default)
35+
privateasyncTask<(IEnumerable<LogModel>,int)>GetLogsAsync(FetchLogsQueryqueryParams,
36+
CancellationTokencancellationToken=default)
3537
{
3638
// since serilog-sink does not have keyword indexes on level and message, we can only sort on @timestamp
3739
Func<SortDescriptor<ElasticSearchDbLogModel>,SortDescriptor<ElasticSearchDbLogModel>>sortDescriptor=
3840
queryParams.SortBy==SortDirection.Desc
3941
? descriptor=>descriptor.Descending(TimeStampPropertyName)
4042
: descriptor=>descriptor.Ascending(TimeStampPropertyName);
41-
varrowNoStart=queryParams.Page*queryParams.Count;
42-
vardescriptor=newSearchDescriptor<ElasticSearchDbLogModel>()
43+
introwNoStart=queryParams.Page*queryParams.Count;
44+
SearchDescriptor<ElasticSearchDbLogModel>?descriptor=newSearchDescriptor<ElasticSearchDbLogModel>()
4345
.Index(_options.IndexName)
4446
.Query(q=>
45-
+q.Match(m=>m.Field(f=>f.Level).Query(queryParams.Level))&&
46-
+q.DateRange(dr=>dr.Field(f=>f.Timestamp).GreaterThanOrEquals(queryParams.StartDate).LessThanOrEquals(queryParams.EndDate))&&
47-
+q.Match(m=>m.Field(f=>f.Message).Query(queryParams.SearchCriteria))||
47+
(+q.Match(m=>m.Field(f=>f.Level).Query(queryParams.Level))&&
48+
+q.DateRange(dr=>
49+
dr.Field(f=>f.Timestamp).GreaterThanOrEquals(queryParams.StartDate)
50+
.LessThanOrEquals(queryParams.EndDate))&&
51+
+q.Match(m=>m.Field(f=>f.Message).Query(queryParams.SearchCriteria)))||
4852
+q.Match(m=>m.Field(f=>f.Exceptions).Query(queryParams.SearchCriteria)))
4953
.Sort(sortDescriptor)
5054
.Skip(rowNoStart)
5155
.Size(queryParams.Count);
5256

53-
varresult=await_client.SearchAsync<ElasticSearchDbLogModel>(descriptor,cancellationToken);
57+
ISearchResponse<ElasticSearchDbLogModel>?result=
58+
await_client.SearchAsync<ElasticSearchDbLogModel>(descriptor,cancellationToken);
5459

55-
int.TryParse(result?.Total.ToString(),outvartotal);
60+
int.TryParse(result?.Total.ToString(),outinttotal);
5661

5762
return(result?.Documents.Select((x,index)=>x.ToLogModel(rowNoStart,index)).ToList()??[],total);
5863
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp