11using Dapper ;
22using Npgsql ;
33using Serilog . Ui . Core ;
4+ using Serilog . Ui . PostgreSqlProvider . Models ;
45using System ;
56using System . Collections . Generic ;
67using System . Data ;
7- using System . Text ;
8+ using System . Linq ;
89using System . Threading . Tasks ;
910
10- namespace Serilog . Ui . PostgreSqlProvider
11+ namespace Serilog . Ui . PostgreSqlProvider ;
12+
13+ public class PostgresDataProvider ( PostgreSqlDbOptions options ) : IDataProvider
1114{
12- public class PostgresDataProvider : IDataProvider
15+ public string Name => options . ToDataProviderName ( "NPGSQL" ) ;
16+
17+ public async Task < ( IEnumerable < LogModel > , int ) > FetchDataAsync (
18+ int page ,
19+ int count ,
20+ string level = null ,
21+ string searchCriteria = null ,
22+ DateTime ? startDate = null ,
23+ DateTime ? endDate = null
24+ )
1325 {
14- private readonly RelationalDbOptions _options ;
15-
16- public PostgresDataProvider ( RelationalDbOptions options )
26+ if ( startDate != null && startDate . Value . Kind != DateTimeKind . Utc )
1727 {
18- _options = options ?? throw new ArgumentNullException ( nameof ( options ) ) ;
28+ startDate = DateTime . SpecifyKind ( startDate . Value , DateTimeKind . Utc ) ;
1929 }
2030
21- public async Task < ( IEnumerable < LogModel > , int ) > FetchDataAsync (
22- int page ,
23- int count ,
24- string level = null ,
25- string searchCriteria = null ,
26- DateTime ? startDate = null ,
27- DateTime ? endDate = null
28- )
31+ if ( endDate != null && endDate . Value . Kind != DateTimeKind . Utc )
2932 {
30- if ( startDate != null && startDate . Value . Kind != DateTimeKind . Utc )
31- startDate = DateTime . SpecifyKind ( startDate . Value , DateTimeKind . Utc ) ;
32- if ( endDate != null && endDate . Value . Kind != DateTimeKind . Utc )
33- endDate = DateTime . SpecifyKind ( endDate . Value , DateTimeKind . Utc ) ;
34- var logsTask = GetLogsAsync ( page - 1 , count , level , searchCriteria , startDate , endDate ) ;
35- var logCountTask = CountLogsAsync ( level , searchCriteria , startDate , endDate ) ;
36-
37- await Task . WhenAll ( logsTask , logCountTask ) ;
38-
39- return ( await logsTask , await logCountTask ) ;
33+ endDate = DateTime . SpecifyKind ( endDate . Value , DateTimeKind . Utc ) ;
4034 }
4135
42- public string Name => _options . ToDataProviderName ( "NPGSQL" ) ;
43-
44- private async Task < IEnumerable < LogModel > > GetLogsAsync ( int page ,
45- int count ,
46- string level ,
47- string searchCriteria ,
48- DateTime ? startDate ,
49- DateTime ? endDate )
50- {
51- var queryBuilder = new StringBuilder ( ) ;
52- queryBuilder . Append ( "SELECT message, message_template, level, timestamp, exception, log_event AS \" Properties\" FROM \" " ) ;
53- queryBuilder . Append ( _options . Schema ) ;
54- queryBuilder . Append ( "\" .\" " ) ;
55- queryBuilder . Append ( _options . TableName ) ;
56- queryBuilder . Append ( "\" " ) ;
36+ var logsTask = GetLogsAsync ( page - 1 , count , level , searchCriteria , startDate , endDate ) ;
37+ var logCountTask = CountLogsAsync ( level , searchCriteria , startDate , endDate ) ;
38+ await Task . WhenAll ( logsTask , logCountTask ) ;
5739
58- GenerateWhereClause ( queryBuilder , level , searchCriteria , startDate , endDate ) ;
59-
60- queryBuilder . Append ( " ORDER BY timestamp DESC LIMIT @Count OFFSET @Offset " ) ;
61-
62- using IDbConnection connection = new NpgsqlConnection ( _options . ConnectionString ) ;
63- var logs = await connection . QueryAsync < PostgresLogModel > ( queryBuilder . ToString ( ) ,
64- new
65- {
66- Offset = page * count ,
67- Count = count ,
68- // TODO: this level could be a text column, to be passed as parameter: https://github.com/b00ted/serilog-sinks-postgresql/blob/ce73c7423383d91ddc3823fe350c1c71fc23bab9/Serilog.Sinks.PostgreSQL/Sinks/PostgreSQL/ColumnWriters.cs#L97
69- Level = LogLevelConverter . GetLevelValue ( level ) ,
70- Search = searchCriteria != null ? "%" + searchCriteria + "%" : null ,
71- StartDate = startDate ,
72- EndDate = endDate
73- } ) ;
40+ return ( await logsTask , await logCountTask ) ;
41+ }
7442
75- var index = 1 ;
76- foreach ( var log in logs )
77- log . RowNo = ( page * count ) + index ++ ;
43+ private async Task < IEnumerable < LogModel > > GetLogsAsync (
44+ int page ,
45+ int count ,
46+ string level ,
47+ string searchCriteria ,
48+ DateTime ? startDate ,
49+ DateTime ? endDate )
50+ {
51+ var query = QueryBuilder . BuildFetchLogsQuery ( options . Schema , options . TableName , level , searchCriteria , ref startDate , ref endDate ) ;
7852
79- return logs ;
80- }
53+ using IDbConnection connection = new NpgsqlConnection ( options . ConnectionString ) ;
8154
82- private async Task < int > CountLogsAsync (
83- string level ,
84- string searchCriteria ,
85- DateTime ? startDate = null ,
86- DateTime ? endDate = null )
55+ var logs = ( await connection . QueryAsync < PostgresLogModel > ( query ,
56+ new
57+ {
58+ Offset = page * count ,
59+ Count = count ,
60+ // TODO: this level could be a text column, to be passed as parameter: https://github.com/b00ted/serilog-sinks-postgresql/blob/ce73c7423383d91ddc3823fe350c1c71fc23bab9/Serilog.Sinks.PostgreSQL/Sinks/PostgreSQL/ColumnWriters.cs#L97
61+ Level = LogLevelConverter . GetLevelValue ( level ) ,
62+ Search = searchCriteria != null ? "%" + searchCriteria + "%" : null ,
63+ StartDate = startDate ,
64+ EndDate = endDate
65+ } ) ) . ToList ( ) ;
66+
67+ var index = 1 ;
68+ foreach ( var log in logs )
8769 {
88- var queryBuilder = new StringBuilder ( ) ;
89- queryBuilder . Append ( "SELECT COUNT(message) FROM \" " ) ;
90- queryBuilder . Append ( _options . Schema ) ;
91- queryBuilder . Append ( "\" .\" " ) ;
92- queryBuilder . Append ( _options . TableName ) ;
93- queryBuilder . Append ( "\" " ) ;
94-
95- GenerateWhereClause ( queryBuilder , level , searchCriteria , startDate , endDate ) ;
96-
97- using IDbConnection connection = new NpgsqlConnection ( _options . ConnectionString ) ;
98- return await connection . ExecuteScalarAsync < int > ( queryBuilder . ToString ( ) ,
99- new
100- {
101- Level = LogLevelConverter . GetLevelValue ( level ) ,
102- Search = searchCriteria != null ? "%" + searchCriteria + "%" : null ,
103- StartDate = startDate ,
104- EndDate = endDate
105- } ) ;
70+ log . RowNo = ( page * count ) + index ++ ;
10671 }
10772
108- private void GenerateWhereClause (
109- StringBuilder queryBuilder ,
110- string level ,
111- string searchCriteria ,
112- DateTime ? startDate = null ,
113- DateTime ? endDate = null )
114- {
115- var whereIncluded = false ;
116-
117- if ( ! string . IsNullOrEmpty ( level ) )
118- {
119- queryBuilder . Append ( " WHERE level = @Level " ) ;
120- whereIncluded = true ;
121- }
73+ return logs ;
74+ }
12275
123- if ( ! string . IsNullOrEmpty ( searchCriteria ) )
124- {
125- queryBuilder . Append ( whereIncluded
126- ? " AND message LIKE @Search OR exception LIKE @Search "
127- : " WHERE message LIKE @Search OR exception LIKE @Search " ) ;
128- }
76+ private async Task < int > CountLogsAsync (
77+ string level ,
78+ string searchCriteria ,
79+ DateTime ? startDate = null ,
80+ DateTime ? endDate = null )
81+ {
82+ var query = QueryBuilder . BuildCountLogsQuery ( options . Schema , options . TableName , level , searchCriteria , ref startDate , ref endDate ) ;
12983
130- if ( startDate != null )
131- {
132- queryBuilder . Append ( whereIncluded
133- ? " AND timestamp >= @StartDate "
134- : " WHERE timestamp >= @StartDate " ) ;
135- whereIncluded = true ;
136- }
84+ using IDbConnection connection = new NpgsqlConnection ( options . ConnectionString ) ;
13785
138- if ( endDate != null )
86+ return await connection . ExecuteScalarAsync < int > ( query ,
87+ new
13988 {
140- queryBuilder . Append ( whereIncluded
141- ? " AND timestamp < @EndDate "
142- : " WHERE timestamp < @EndDate " ) ;
143- }
144- }
89+ Level = LogLevelConverter . GetLevelValue ( level ) ,
90+ Search = searchCriteria != null ? "%" + searchCriteria + "%" : null ,
91+ StartDate = startDate ,
92+ EndDate = endDate
93+ } ) ;
14594 }
146- }
95+ }
0 commit comments