Skip to content

Commit 6576e76

Browse files
committed
Change the heartbeat plugin.
1 parent 41601b7 commit 6576e76

File tree

3 files changed

+40
-44
lines changed

3 files changed

+40
-44
lines changed

Source/Shared/Models/Client/Event.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public Event() {
6060
public static class KnownTypes {
6161
public const string Error = "error";
6262
public const string FeatureUsage = "usage";
63-
public const string Heartbeat = "heart";
63+
public const string SessionHeartbeat = "heartbeat";
6464
public const string Log = "log";
6565
public const string NotFound = "404";
6666
public const string SessionStart = "start";

Source/Shared/Plugins/Default/100_SessionManagerPlugin.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ public void Run(EventPluginContext context) {
2626
} else {
2727
sessionId = sessionManager.GetSessionId(identity);
2828
if (String.IsNullOrEmpty(sessionId)) {
29+
// no session found for identity, start new one and assign the session id
30+
// server will automatically create a session start event
2931
sessionId = sessionManager.StartSession(identity);
30-
context.Client.CreateSessionStart(sessionId).;
3132
}
3233
}
3334

Lines changed: 37 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,62 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Threading;
3-
using Exceptionless.Logging;
44
using Exceptionless.Models;
5-
using Exceptionless.Queue;
65

76
namespace Exceptionless.Plugins.Default {
87
[Priority(110)]
98
public class HeartbeatPlugin : IEventPlugin, IDisposable {
10-
private readonly IEventQueue _eventQueue;
11-
private readonly IExceptionlessLog _log;
12-
private Timer _timer;
13-
private Event _lastEvent;
14-
15-
public HeartbeatPlugin(IEventQueue eventQueue, IExceptionlessLog log) {
16-
_eventQueue = eventQueue;
17-
_log = log;
18-
}
9+
private readonly Dictionary<string, SessionHeartbeat> _sessionHeartbeats = new Dictionary<string, SessionHeartbeat>();
10+
private readonly object _lock = new object();
1911

2012
public void Run(EventPluginContext context) {
2113
var sessionIdentifier = context.Event.SessionId ?? context.Event.GetUserIdentity()?.Identity;
22-
if (String.IsNullOrEmpty(sessionIdentifier) || context.Event.IsSessionEnd()) {
23-
_lastEvent = null;
24-
_timer?.Change(Timeout.Infinite, Timeout.Infinite);
14+
if (String.IsNullOrEmpty(sessionIdentifier) || context.Event.Type == Event.KnownTypes.SessionHeartbeat)
2515
return;
26-
}
2716

28-
_lastEvent = context.Event;
29-
if (_timer == null)
30-
_timer = new Timer(OnEnqueueHeartbeat, null, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30));
31-
else
32-
_timer.Change(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30));
17+
lock (_lock) {
18+
if (!_sessionHeartbeats.ContainsKey(sessionIdentifier))
19+
_sessionHeartbeats.Add(sessionIdentifier, new SessionHeartbeat(sessionIdentifier, context.Client));
20+
else if (context.Event.IsSessionEnd()) {
21+
_sessionHeartbeats[sessionIdentifier].Dispose();
22+
_sessionHeartbeats.Remove(sessionIdentifier);
23+
} else
24+
_sessionHeartbeats[sessionIdentifier].DelayNext();
25+
}
3326
}
3427

35-
private void OnEnqueueHeartbeat(object state) {
36-
var heartbeatEvent = CreateHeartbeatEvent(_lastEvent);
37-
if (heartbeatEvent == null)
38-
return;
28+
public void Dispose() {
29+
lock (_lock) {
30+
foreach (var kvp in _sessionHeartbeats)
31+
kvp.Value.Dispose();
32+
}
3933

40-
_log.Trace(nameof(HeartbeatPlugin), $"Enqueuing heartbeat for session: {heartbeatEvent.SessionId}");
41-
_eventQueue.Enqueue(heartbeatEvent);
34+
_sessionHeartbeats.Clear();
35+
}
36+
}
37+
public class SessionHeartbeat : IDisposable {
38+
private readonly Timer _timer;
39+
private readonly int _interval = 30 * 1000;
40+
private readonly ExceptionlessClient _client;
41+
42+
public SessionHeartbeat(string sessionId, ExceptionlessClient client) {
43+
SessionId = sessionId;
44+
_client = client;
45+
_timer = new Timer(SendHeartbeat, null, _interval, _interval);
4246
}
4347

44-
private Event CreateHeartbeatEvent(Event source) {
45-
if (source == null)
46-
return null;
47-
48-
var heartbeatEvent = new Event {
49-
Date = DateTimeOffset.Now,
50-
Type = Event.KnownTypes.Heartbeat,
51-
SessionId = source.SessionId
52-
};
48+
public string SessionId { get; set; }
5349

54-
heartbeatEvent.SetUserIdentity(source.GetUserIdentity());
50+
public void DelayNext() {
51+
_timer.Change(_interval, _interval);
52+
}
5553

56-
return heartbeatEvent;
54+
private void SendHeartbeat(object state) {
55+
_client.SubmitEvent(new Event { Type = Event.KnownTypes.SessionHeartbeat, SessionId = SessionId });
5756
}
5857

5958
public void Dispose() {
60-
if (_timer == null)
61-
return;
62-
63-
_timer.Dispose();
64-
_timer = null;
59+
_timer?.Dispose();
6560
}
6661
}
6762
}

0 commit comments

Comments
 (0)