Skip to content

Commit 51321e9

Browse files
committed
Implement log search.
1 parent bcb762d commit 51321e9

File tree

7 files changed

+137
-50
lines changed

7 files changed

+137
-50
lines changed

src/Serilog.Ui.Core/IDataProvider.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ namespace Serilog.Ui.Core
55
{
66
public interface IDataProvider
77
{
8-
Task<(IEnumerable<LogModel>, int)> FetchDataAsync(int page, int count, string level = null);
8+
Task<(IEnumerable<LogModel>, int)> FetchDataAsync(
9+
int page,
10+
int count,
11+
string level = null,
12+
string searchCriteria = null
13+
);
914
}
1015
}

src/Serilog.Ui.MsSqlServerProvider/SqlServerDataProvider.cs

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,45 +17,92 @@ public SqlServerDataProvider(RelationalDbOptions options)
1717
_options = options;
1818
}
1919

20-
public async Task<(IEnumerable<LogModel>, int)> FetchDataAsync(int page, int count, string level = null)
20+
public async Task<(IEnumerable<LogModel>, int)> FetchDataAsync(
21+
int page,
22+
int count,
23+
string logLevel = null,
24+
string searchCriteria = null
25+
)
2126
{
22-
using (IDbConnection connection = new SqlConnection(_options.ConnectionString))
23-
{
24-
var logsTask = GetLogsAsync(page - 1, count, level);
25-
var logCountTask = CountLogsAsync();
27+
var logsTask = GetLogsAsync(page - 1, count, logLevel, searchCriteria);
28+
var logCountTask = CountLogsAsync(logLevel, searchCriteria);
2629

27-
await Task.WhenAll(logsTask, logCountTask);
30+
await Task.WhenAll(logsTask, logCountTask);
2831

29-
return (await logsTask, await logCountTask);
30-
}
32+
return (await logsTask, await logCountTask);
3133
}
3234

33-
private async Task<IEnumerable<LogModel>> GetLogsAsync(int page, int count, string level)
35+
private async Task<IEnumerable<LogModel>> GetLogsAsync(int page, int count, string level, string searchCriteria)
3436
{
3537
var queryBuilder = new StringBuilder();
36-
queryBuilder.Append("SELECT[Id], [Message],[Level], [TimeStamp], [Exception], [Properties] FROM[");
38+
queryBuilder.Append("SELECT [Id], [Message], [Level], [TimeStamp], [Exception], [Properties] FROM[");
3739
queryBuilder.Append(_options.Schema);
3840
queryBuilder.Append("].[");
3941
queryBuilder.Append(_options.TableName);
4042
queryBuilder.Append("] ");
4143

44+
var whereIncluded = false;
45+
4246
if (!string.IsNullOrEmpty(level))
47+
{
4348
queryBuilder.Append("WHERE [LEVEL] = @Level ");
49+
whereIncluded = true;
50+
}
51+
52+
if (!string.IsNullOrEmpty(searchCriteria))
53+
{
54+
queryBuilder.Append(whereIncluded
55+
? "AND [Message] LIKE @Search OR [Exception] LIKE @Search "
56+
: "WHERE [Message] LIKE @Search OR [Exception] LIKE @Search ");
57+
}
4458

4559
queryBuilder.Append("ORDER BY Id DESC OFFSET @Offset ROWS FETCH NEXT @Count ROWS ONLY");
4660

4761
using (IDbConnection connection = new SqlConnection(_options.ConnectionString))
4862
{
49-
return await connection.QueryAsync<LogModel>(queryBuilder.ToString(), new { Offset = page, Count = count, Level = level });
63+
return await connection.QueryAsync<LogModel>(queryBuilder.ToString(),
64+
new
65+
{
66+
Offset = page,
67+
Count = count,
68+
Level = level,
69+
Search = searchCriteria != null ? "%" + searchCriteria + "%" : null
70+
});
5071
}
5172
}
5273

53-
public async Task<int> CountLogsAsync()
74+
public async Task<int> CountLogsAsync(string level, string searchCriteria)
5475
{
55-
var query = $"SELECT COUNT(Id) FROM [{_options.Schema}].[{_options.TableName}]";
76+
var queryBuilder = new StringBuilder();
77+
queryBuilder.Append("SELECT COUNT(Id) FROM[");
78+
queryBuilder.Append(_options.Schema);
79+
queryBuilder.Append("].[");
80+
queryBuilder.Append(_options.TableName);
81+
queryBuilder.Append("] ");
82+
83+
var whereIncluded = false;
84+
85+
if (!string.IsNullOrEmpty(level))
86+
{
87+
queryBuilder.Append("WHERE [LEVEL] = @Level ");
88+
whereIncluded = true;
89+
}
90+
91+
if (!string.IsNullOrEmpty(searchCriteria))
92+
{
93+
queryBuilder.Append(whereIncluded
94+
? "AND [Message] LIKE @Search OR [Exception] LIKE @Search "
95+
: "WHERE [Message] LIKE @Search OR [Exception] LIKE @Search ");
96+
}
97+
5698
using (IDbConnection connection = new SqlConnection(_options.ConnectionString))
5799
{
58-
return await connection.ExecuteScalarAsync<int>(query);
100+
return await connection.ExecuteScalarAsync<int>(queryBuilder.ToString(),
101+
new
102+
{
103+
Level = level,
104+
Search = searchCriteria != null ? "%" + searchCriteria + "%" : null
105+
});
59106
}
60107
}
61108
}

src/Serilog.Ui.Web/Controllers/LogsController.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public LogsController(IDataProvider dataProvider)
4545
_dataProvider = dataProvider;
4646
}
4747

48-
public async Task<IActionResult> Index(int page = 1, int count = 10, string level = null)
48+
public async Task<IActionResult> Index(int page = 1, int count = 10, string level = null, string search = null)
4949
{
5050
if (page < 1)
5151
page = 1;
@@ -57,13 +57,14 @@ public async Task<IActionResult> Index(int page = 1, int count = 10, string leve
5757

5858
SetLogLevelSelectListItem(level);
5959

60-
var (logs, logCount) = await _dataProvider.FetchDataAsync(page, count, level);
60+
var (logs, logCount) = await _dataProvider.FetchDataAsync(page, count, level, search);
6161
var viewModel = new LogViewModel
6262
{
6363
LogCount = logCount,
6464
Logs = logs,
6565
Page = page,
6666
Count = count,
67+
SearchCriteria = search,
6768
LogCountSelectListItems = LogCountSelectListItems,
6869
LogLevelSelectListItems = LogLevelSelectListItems
6970
};

src/Serilog.Ui.Web/ViewModel/LogViewModel.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public class LogViewModel
1414

1515
public int Count { get; set; }
1616

17+
public string SearchCriteria { get; set; }
18+
1719
public IEnumerable<SelectListItem> LogCountSelectListItems { get; set; }
1820

1921
public IEnumerable<SelectListItem> LogLevelSelectListItems { get; set; }

src/Serilog.Ui.Web/Views/Logs/Index.cshtml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@
4040
</div>
4141
<div class="col-sm-12 col-md-4">
4242
<div class="table-filter">
43-
<label>Search:<input type="search" class="form-control form-control-sm" placeholder=""></label>
43+
<label>
44+
Search message:
45+
<input type="search" name="search" id="search" class="form-control form-control-sm" placeholder="" value="@Model.SearchCriteria">
46+
</label>
4447
</div>
4548
</div>
4649
</div>
Lines changed: 52 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,79 @@
11
@model LogViewModel
22
@{
3-
var totalPages = Model.LogCount / Model.Count;
4-
totalPages += Model.LogCount % Model.Count != 0 ? 1 : 0;
3+
const int pageLength = 5;
54
var endIndex = 5;
65
var startIndex = 1;
76
var hasMore = false;
7+
8+
var totalPages = Model.LogCount / Model.Count;
9+
totalPages += Model.LogCount % Model.Count != 0 ? 1 : 0;
10+
811
if (totalPages > 5)
912
{
1013

11-
if (totalPages - Model.Page > 2)
14+
if (totalPages == Model.Page)
15+
{
16+
hasMore = false;
17+
startIndex = totalPages - pageLength;
18+
endIndex = totalPages;
19+
}
20+
else if (totalPages - pageLength == 1)
1221
{
1322
hasMore = true;
14-
startIndex = Model.Page;
15-
endIndex = Model.Page + 5;
23+
}
24+
else
25+
{
26+
if (totalPages - Model.Page > pageLength)
27+
{
28+
hasMore = true;
29+
startIndex = Model.Page;
30+
endIndex = Model.Page + pageLength;
31+
}
32+
else
33+
{
34+
hasMore = false;
35+
startIndex = totalPages - pageLength;
36+
endIndex = totalPages;
37+
}
1638
}
1739
}
1840
}
1941

2042
<div class="table-pagination">
2143
<input type="hidden" id="page" name="page" />
2244
<ul class="pagination">
23-
@if (Model.Page != 1)
45+
@if (Model.Page != 1 || startIndex != 1)
2446
{
25-
var value = Model.Page - 1;
26-
<li class="page-item previous">
27-
<a href="#" data-val="@value" tabindex="@value" class="page-link">Previous</a>
28-
</li>
47+
var value = Model.Page - 1;
48+
<li class="page-item previous">
49+
<a href="#" data-val="@value" tabindex="@value" class="page-link">Previous</a>
50+
</li>
2951
}
3052
@for (var i = startIndex; i <= endIndex; i++)
3153
{
32-
if (Model.Page == i)
33-
{
34-
<li class="page-item active">
35-
<span data-val="@i" class="page-link disabled">
36-
@i
37-
<span class="sr-only">(current)</span>
38-
</span>
39-
</li>
40-
}
41-
else
42-
{
43-
<li>
44-
<a href="#" data-val="@i" tabindex="@i" class="page-link">@i</a>
45-
</li>
46-
}
54+
if (Model.Page == i)
55+
{
56+
<li class="page-item active">
57+
<span data-val="@i" class="page-link disabled">
58+
@i
59+
<span class="sr-only">(current)</span>
60+
</span>
61+
</li>
62+
}
63+
else
64+
{
65+
<li>
66+
<a href="#" data-val="@i" tabindex="@i" class="page-link">@i</a>
67+
</li>
68+
}
4769
}
4870
@if (hasMore)
4971
{
50-
var value = Model.Page + 1;
51-
<li class="page-item ">&nbsp;...&nbsp;</li>
52-
<li class="page-item next">
53-
<a href="#" data-val="@value" tabindex="@value" class="page-link">Next</a>
54-
</li>
72+
var value = Model.Page + 1;
73+
<li class="page-item ">&nbsp;...&nbsp;</li>
74+
<li class="page-item next">
75+
<a href="#" data-val="@value" tabindex="@value" class="page-link">Next</a>
76+
</li>
5577
}
5678
</ul>
5779
</div>

src/Serilog.Ui.Web/wwwroot/js/main.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,19 @@
2020
});
2121

2222
$("#logCount").on("change", function () {
23-
$("#page").val($(".page-link.disabled").attr("data-val"));
23+
$("#page").val("1");
2424
$("form").submit()
2525
});
2626

2727
$("#logFilter").on("change", function () {
28-
$("#page").val($(".page-link.disabled").attr("data-val"));
28+
$("#page").val("1");
2929
$("form").submit()
3030
});
31+
32+
$("#search").keypress(function (e) {
33+
$("#page").val("1");
34+
if (e.which === 13) {
35+
$("form").submit();
36+
}
37+
});
3138
})(jQuery);

0 commit comments

Comments
 (0)