MailSharp / MailSharp.SMTP / Metrics / SmtpMetrics.cs
Code · 60 lines · 2811 bytes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60using System.Collections.Concurrent;

namespace MailSharp.SMTP.Metrics;

public sealed class SmtpMetrics
{
	private long totalConnections;
	private long activeSessions;
	private long messagesReceived;
	private long messagesRelayed;
	private long messagesRejectedSpf;
	private long messagesRejectedDkim;
	private long messagesRejectedDmarc;
	private long authSuccess;
	private long authFailed;
	private long bytesReceived;

	public long TotalConnections => totalConnections;
	public long ActiveSessions => activeSessions;
	public long MessagesReceived => messagesReceived;
	public long MessagesRelayed => messagesRelayed;
	public long MessagesRejectedSpf => messagesRejectedSpf;
	public long MessagesRejectedDkim => messagesRejectedDkim;
	public long MessagesRejectedDmarc => messagesRejectedDmarc;
	public long MessagesRejectedTotal => messagesRejectedSpf + messagesRejectedDkim + messagesRejectedDmarc;
	public long AuthSuccess => authSuccess;
	public long AuthFailed => authFailed;
	public long BytesReceived => bytesReceived;
	public long UptimeSeconds => (long)(DateTime.UtcNow - StartTime).TotalSeconds;
	public bool IsRunning { get; set; } = false;
	public DateTime StartTime { get; } = DateTime.UtcNow;
	public DateTime? LastMessageReceivedAt { get; private set; }

	private readonly ConcurrentDictionary<string, long> senderDomains = new(StringComparer.OrdinalIgnoreCase);
	private readonly ConcurrentDictionary<string, long> recipientDomains = new(StringComparer.OrdinalIgnoreCase);

	public IReadOnlyDictionary<string, long> TopSenderDomains => senderDomains;
	public IReadOnlyDictionary<string, long> TopRecipientDomains => recipientDomains;

	public void IncrementConnections() => Interlocked.Increment(ref totalConnections);
	public void IncrementActive() => Interlocked.Increment(ref activeSessions);
	public void DecrementActive() => Interlocked.Decrement(ref activeSessions);
	public void IncrementRelayed() => Interlocked.Increment(ref messagesRelayed);
	public void IncrementRejectedSpf() => Interlocked.Increment(ref messagesRejectedSpf);
	public void IncrementRejectedDkim() => Interlocked.Increment(ref messagesRejectedDkim);
	public void IncrementRejectedDmarc() => Interlocked.Increment(ref messagesRejectedDmarc);
	public void IncrementAuthSuccess() => Interlocked.Increment(ref authSuccess);
	public void IncrementAuthFailed() => Interlocked.Increment(ref authFailed);

	public void MessageReceived(string senderDomain, IEnumerable<string> recipientDomains, long bytes)
	{
		Interlocked.Increment(ref messagesReceived);
		Interlocked.Add(ref bytesReceived, bytes);
		LastMessageReceivedAt = DateTime.UtcNow;

		senderDomains.AddOrUpdate(senderDomain, 1, (_, c) => c + 1);
		foreach (var domain in recipientDomains)
			this.recipientDomains.AddOrUpdate(domain, 1, (_, c) => c + 1);
	}
}