Skip to content

Commit bb8726c

Browse files
Add an initial draft of a dirty memory custom check
1 parent fca1ba5 commit bb8726c

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
namespace ServiceControl.Audit.Persistence.RavenDB.CustomChecks;
2+
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using NServiceBus.CustomChecks;
8+
9+
class CheckDirtyMemory(IRavenDocumentStoreProvider documentStoreProvider) : CustomCheck("ServiceControl.Audit database", "Dirty memory trends", TimeSpan.FromMinutes(5))
10+
{
11+
readonly List<int> lastDirtyMemoryReads = [];
12+
public override async Task<CheckResult> PerformCheck(CancellationToken cancellationToken = default)
13+
{
14+
var retriever = await GetMemoryRetriever(cancellationToken);
15+
var memoryInfo = await retriever.GetMemoryInformation(cancellationToken);
16+
17+
if (memoryInfo.IsHighDirty)
18+
{
19+
//log warning
20+
return CheckResult.Failed("There is a high level of dirty memory. Check the ServiceControl " +
21+
"troubleshooting guide for guidance on how to mitigate the issue.");
22+
}
23+
24+
lastDirtyMemoryReads.Add(memoryInfo.DirtyMemory);
25+
if (lastDirtyMemoryReads.Count > 20)
26+
{
27+
//cap the list at 20
28+
lastDirtyMemoryReads.RemoveAt(lastDirtyMemoryReads.Count - 1);
29+
}
30+
31+
// evaluate the trends
32+
// if the amount of dirty memory is constantly growing log a warning and fail the check
33+
34+
return CheckResult.Pass;
35+
}
36+
37+
MemoryInformationRetriever _retriever;
38+
async Task<MemoryInformationRetriever> GetMemoryRetriever(CancellationToken cancellationToken = default)
39+
{
40+
if (_retriever == null)
41+
{
42+
var documentStore = await documentStoreProvider.GetDocumentStore(cancellationToken);
43+
var serverUrl = documentStore.Urls[0]; //TODO is there a better way to get the RavenDB server URL?
44+
_retriever = new MemoryInformationRetriever(serverUrl);
45+
}
46+
return _retriever;
47+
}
48+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace ServiceControl.Audit.Persistence.RavenDB;
2+
3+
using System;
4+
using System.Linq;
5+
using System.Net.Http;
6+
using System.Text.Json;
7+
using System.Threading;
8+
using System.Threading.Tasks;
9+
10+
class MemoryInformationRetriever(string serverUrl)
11+
{
12+
readonly HttpClient client = new() { BaseAddress = new Uri(serverUrl) };
13+
14+
record ResponseDto
15+
{
16+
public MemoryInformation MemoryInformation { get; set; }
17+
}
18+
19+
record MemoryInformation
20+
{
21+
public bool IsHighDirty { get; set; }
22+
public string DirtyMemory { get; set; }
23+
}
24+
25+
public async Task<(bool IsHighDirty, int DirtyMemory)> GetMemoryInformation(CancellationToken cancellationToken = default)
26+
{
27+
var httpResponse = await client.GetAsync("/admin/debug/memory/stats", cancellationToken);
28+
var responseDto = JsonSerializer.Deserialize<ResponseDto>(await httpResponse.Content.ReadAsStringAsync(cancellationToken));
29+
30+
return (responseDto.MemoryInformation.IsHighDirty, int.Parse(responseDto.MemoryInformation.DirtyMemory.Split(' ').First()));
31+
}
32+
}

0 commit comments

Comments
 (0)