Skip to content

Commit d27f368

Browse files
committed
Added the ability to update a sessions activity without submitting an event.
1 parent 9f956b5 commit d27f368

20 files changed

+116
-68
lines changed

Source/Extras/Extensions/ExceptionlessExtraConfigurationExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ public static void ReadFromConfigSection(this ExceptionlessConfiguration config)
9696
config.ApiKey = section.ApiKey;
9797

9898
if (!String.IsNullOrEmpty(section.ServerUrl))
99-
config.ServerUrl = section.ServerUrl;
99+
config.ServerUrl = config.HeartbeatServerUrl = section.ServerUrl;
100100

101101
if (section.QueueMaxAge.HasValue)
102102
config.QueueMaxAge = section.QueueMaxAge.Value;
@@ -176,7 +176,7 @@ public static void ReadFromAppSettings(this ExceptionlessConfiguration config) {
176176

177177
string serverUrl = ConfigurationManager.AppSettings["Exceptionless:ServerUrl"];
178178
if (!String.IsNullOrEmpty(serverUrl))
179-
config.ServerUrl = serverUrl;
179+
config.ServerUrl = config.HeartbeatServerUrl = serverUrl;
180180
}
181181

182182
/// <summary>
@@ -194,7 +194,7 @@ public static void ReadFromEnvironmentalVariables(this ExceptionlessConfiguratio
194194

195195
string serverUrl = GetEnvironmentalVariable("Exceptionless:ServerUrl");
196196
if (!String.IsNullOrEmpty(serverUrl))
197-
config.ServerUrl = serverUrl;
197+
config.ServerUrl = config.HeartbeatServerUrl = serverUrl;
198198
}
199199

200200
private static string GetEnvironmentalVariable(string name) {

Source/Extras/Submission/SubmissionClient.cs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Net;
55
using System.Runtime.CompilerServices;
66
using Exceptionless.Configuration;
7+
using Exceptionless.Dependency;
78
using Exceptionless.Extensions;
89
using Exceptionless.Extras.Extensions;
910
using Exceptionless.Json.Linq;
@@ -23,7 +24,7 @@ public SubmissionResponse PostEvents(IEnumerable<Event> events, ExceptionlessCon
2324

2425
HttpWebResponse response;
2526
try {
26-
var request = CreateHttpWebRequest(config, "events");
27+
var request = CreateHttpWebRequest(config, String.Format("{0}/events", config.GetServiceEndPoint()));
2728
response = request.PostJsonAsyncWithCompression(data).Result as HttpWebResponse;
2829
} catch (AggregateException aex) {
2930
var ex = aex.GetInnermostException() as WebException;
@@ -47,7 +48,7 @@ public SubmissionResponse PostUserDescription(string referenceId, UserDescriptio
4748

4849
HttpWebResponse response;
4950
try {
50-
var request = CreateHttpWebRequest(config, String.Format("events/by-ref/{0}/user-description", referenceId));
51+
var request = CreateHttpWebRequest(config, String.Format("{0}/events/by-ref/{1}/user-description", config.GetServiceEndPoint(), referenceId));
5152
response = request.PostJsonAsyncWithCompression(data).Result as HttpWebResponse;
5253
} catch (AggregateException aex) {
5354
var ex = aex.GetInnermostException() as WebException;
@@ -69,7 +70,7 @@ public SubmissionResponse PostUserDescription(string referenceId, UserDescriptio
6970
public SettingsResponse GetSettings(ExceptionlessConfiguration config, IJsonSerializer serializer) {
7071
HttpWebResponse response;
7172
try {
72-
var request = CreateHttpWebRequest(config, "projects/config");
73+
var request = CreateHttpWebRequest(config, String.Format("{0}/projects/config", config.GetServiceEndPoint()));
7374
response = request.GetJsonAsync().Result as HttpWebResponse;
7475
} catch (Exception ex) {
7576
var message = String.Concat("Unable to retrieve configuration settings. Exception: ", ex.GetMessage());
@@ -86,6 +87,17 @@ public SettingsResponse GetSettings(ExceptionlessConfiguration config, IJsonSeri
8687
var settings = serializer.Deserialize<ClientConfiguration>(json);
8788
return new SettingsResponse(true, settings.Settings, settings.Version);
8889
}
90+
91+
public void SendHeartbeat(string sessionIdOrUserId, ExceptionlessConfiguration config) {
92+
try {
93+
var request = CreateHttpWebRequest(config, String.Format("{0}/events/session/{1}/heartbeat", config.GetHeartbeatServiceEndPoint(), sessionIdOrUserId));
94+
request.Timeout = 1;
95+
var response = request.GetResponseAsync().Result;
96+
} catch (Exception ex) {
97+
var log = config.Resolver.GetLog();
98+
log.Error(String.Concat("Error submitting heartbeat: ", ex.GetMessage()));
99+
}
100+
}
89101

90102
private static string GetResponseMessage(HttpWebResponse response) {
91103
if (response.IsSuccessful())
@@ -105,8 +117,8 @@ private static string GetResponseMessage(HttpWebResponse response) {
105117
return message;
106118
}
107119

108-
protected virtual HttpWebRequest CreateHttpWebRequest(ExceptionlessConfiguration config, string endPoint) {
109-
var request = (HttpWebRequest)WebRequest.Create(String.Concat(config.GetServiceEndPoint(), endPoint));
120+
protected virtual HttpWebRequest CreateHttpWebRequest(ExceptionlessConfiguration config, string url) {
121+
var request = (HttpWebRequest)WebRequest.Create(url);
110122
request.AddAuthorizationHeader(config);
111123
request.SetUserAgent(config.UserAgent);
112124
request.AllowAutoRedirect = true;

Source/Platforms/Log4net/BufferingExceptionlessAppender.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public override void ActivateOptions() {
2424
if (!String.IsNullOrEmpty(ApiKey) && ApiKey != "API_KEY_HERE")
2525
config.ApiKey = ApiKey;
2626
if (!String.IsNullOrEmpty(ServerUrl))
27-
config.ServerUrl = ServerUrl;
27+
config.ServerUrl = config.HeartbeatServerUrl = ServerUrl;
2828
config.UseInMemoryStorage();
2929
});
3030
}

Source/Platforms/Log4net/ExceptionlessAppender.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public override void ActivateOptions() {
1717
if (!String.IsNullOrEmpty(ApiKey) && ApiKey != "API_KEY_HERE")
1818
config.ApiKey = ApiKey;
1919
if (!String.IsNullOrEmpty(ServerUrl))
20-
config.ServerUrl = ServerUrl;
20+
config.ServerUrl = config.HeartbeatServerUrl = ServerUrl;
2121
config.UseInMemoryStorage();
2222
});
2323
}

Source/Platforms/NLog/ExceptionlessTarget.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ protected override void InitializeTarget() {
2727
if (!String.IsNullOrEmpty(ApiKey) && ApiKey != "API_KEY_HERE")
2828
config.ApiKey = ApiKey;
2929
if (!String.IsNullOrEmpty(ServerUrl))
30-
config.ServerUrl = ServerUrl;
30+
config.ServerUrl = config.HeartbeatServerUrl = ServerUrl;
3131
config.UseInMemoryStorage();
3232
});
3333
}

Source/Samples/SampleConsole/Program.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,7 @@ private static void Main() {
8686
} else if (keyInfo.Key == ConsoleKey.D5) {
8787
ExceptionlessClient.Default.Configuration.UseSessions(false, null, true);
8888
ExceptionlessClient.Default.SubmitSessionStart();
89-
} else if (keyInfo.Key == ConsoleKey.D6)
90-
ExceptionlessClient.Default.SubmitSessionHeartbeat();
91-
else if (keyInfo.Key == ConsoleKey.D7)
89+
} else if (keyInfo.Key == ConsoleKey.D7)
9290
ExceptionlessClient.Default.SubmitSessionEnd();
9391
else if (keyInfo.Key == ConsoleKey.D8)
9492
ExceptionlessClient.Default.Configuration.SetUserIdentity(Guid.NewGuid().ToString("N"));

Source/Samples/SampleConsole/Submission/InMemorySubmissionClient.cs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,34 @@
44
using Exceptionless.Models.Data;
55
using Exceptionless.Submission;
66

7-
namespace Exceptionless.SampleConsole
8-
{
9-
public class InMemorySubmissionClient: ISubmissionClient {
10-
private static readonly Dictionary<string, object> _eventRepository = new Dictionary<string, object>();
11-
private static readonly Dictionary<string, object> _userDescriptionRepository = new Dictionary<string, object>();
7+
namespace Exceptionless.SampleConsole {
8+
public class InMemorySubmissionClient : ISubmissionClient {
9+
private readonly Dictionary<string, object> _eventContainer = new Dictionary<string, object>();
10+
private readonly Dictionary<string, object> _userDescriptionContainer = new Dictionary<string, object>();
11+
private readonly Dictionary<string, DateTime> _heartbeatContainer = new Dictionary<string, DateTime>();
1212

1313
public SubmissionResponse PostEvents(IEnumerable<Event> events, ExceptionlessConfiguration config, IJsonSerializer serializer) {
14-
foreach (Event e in events)
15-
{
14+
foreach (Event e in events) {
1615
string data = serializer.Serialize(e);
17-
string referenceId = !string.IsNullOrWhiteSpace(e.ReferenceId)
18-
? e.ReferenceId
19-
: Guid.NewGuid().ToString("D");
20-
_eventRepository[referenceId] = data;
16+
string referenceId = !string.IsNullOrWhiteSpace(e.ReferenceId) ? e.ReferenceId : Guid.NewGuid().ToString("D");
17+
_eventContainer[referenceId] = data;
2118
}
22-
return new SubmissionResponse(200);
2319

20+
return new SubmissionResponse(200);
2421
}
2522

2623
public SubmissionResponse PostUserDescription(string referenceId, UserDescription description, ExceptionlessConfiguration config, IJsonSerializer serializer) {
2724
string data = serializer.Serialize(description);
28-
_userDescriptionRepository[referenceId] = data;
25+
_userDescriptionContainer[referenceId] = data;
2926
return new SubmissionResponse(200);
3027
}
3128

3229
public SettingsResponse GetSettings(ExceptionlessConfiguration config, IJsonSerializer serializer) {
3330
return new SettingsResponse(true);
3431
}
32+
33+
public void SendHeartbeat(string sessionIdOrUserId, ExceptionlessConfiguration config) {
34+
_heartbeatContainer[sessionIdOrUserId] = DateTime.UtcNow;
35+
}
3536
}
36-
}
37+
}

Source/Shared/Configuration/ExceptionlessConfiguration.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
namespace Exceptionless {
1212
public class ExceptionlessConfiguration {
1313
private const string DEFAULT_SERVER_URL = "https://collector.exceptionless.io";
14+
private const string DEFAULT_HEARTBEAT_SERVER_URL = "https://heartbeat.exceptionless.io";
1415
private const string DEFAULT_USER_AGENT = "exceptionless/" + ThisAssembly.AssemblyFileVersion;
1516
private const int DEFAULT_SUBMISSION_BATCH_SIZE = 50;
1617

1718
private readonly IDependencyResolver _resolver;
1819
private bool _configLocked;
1920
private string _apiKey;
21+
private string _heartbeatServerUrl;
2022
private string _serverUrl;
2123
private int _submissionBatchSize;
2224
private ValidationResult _validationResult;
@@ -28,6 +30,7 @@ public ExceptionlessConfiguration(IDependencyResolver resolver) {
2830
throw new ArgumentNullException("resolver");
2931

3032
ServerUrl = DEFAULT_SERVER_URL;
33+
HeartbeatServerUrl = DEFAULT_HEARTBEAT_SERVER_URL;
3134
UserAgent = DEFAULT_USER_AGENT;
3235
SubmissionBatchSize = DEFAULT_SUBMISSION_BATCH_SIZE;
3336
Enabled = true;
@@ -72,6 +75,23 @@ public string ServerUrl {
7275
}
7376
}
7477

78+
/// <summary>
79+
/// The server url that all events will be sent to.
80+
/// </summary>
81+
public string HeartbeatServerUrl {
82+
get { return _heartbeatServerUrl; }
83+
set {
84+
if (_heartbeatServerUrl == value)
85+
return;
86+
87+
if (_configLocked)
88+
throw new ArgumentException("HeartbeatServerUrl can't be changed after the client has been initialized.");
89+
90+
_validationResult = null;
91+
_heartbeatServerUrl = value;
92+
}
93+
}
94+
7595
/// <summary>
7696
/// Used to identify the client that sent the events to the server.
7797
/// </summary>
@@ -358,6 +378,9 @@ public ValidationResult Validate() {
358378
if (String.IsNullOrEmpty(ServerUrl))
359379
result.Messages.Add("ServerUrl is not set.");
360380

381+
if (String.IsNullOrEmpty(HeartbeatServerUrl))
382+
result.Messages.Add("HeartbeatServerUrl is not set.");
383+
361384
return result;
362385
}
363386

Source/Shared/Extensions/ClientExtensions.cs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Threading.Tasks;
3+
using Exceptionless.Dependency;
24
using Exceptionless.Logging;
35
using Exceptionless.Models;
46

@@ -208,20 +210,17 @@ public static void SubmitSessionEnd(this ExceptionlessClient client) {
208210
client.CreateSessionEnd().Submit();
209211
}
210212

211-
/// <summary>
212-
/// Creates a session heartbeat event.
213-
/// </summary>
214-
/// <param name="client">The client instance.</param>
215-
public static EventBuilder CreateSessionHeartbeat(this ExceptionlessClient client) {
216-
return client.CreateEvent().SetType(Event.KnownTypes.SessionHeartbeat);
217-
}
218-
219213
/// <summary>
220214
/// Submits a session heartbeat event.
221215
/// </summary>
222216
/// <param name="client">The client instance.</param>
223-
public static void SubmitSessionHeartbeat(this ExceptionlessClient client) {
224-
client.CreateSessionHeartbeat().Submit();
217+
/// <param name="sessionIdOrUserId">The session id or user id.</param>
218+
public static void SubmitSessionHeartbeat(this ExceptionlessClient client, string sessionIdOrUserId) {
219+
if (String.IsNullOrWhiteSpace(sessionIdOrUserId))
220+
return;
221+
222+
var submissionClient = client.Configuration.Resolver.GetSubmissionClient();
223+
Task.Factory.StartNew(() => submissionClient.SendHeartbeat(sessionIdOrUserId, client.Configuration));
225224
}
226225
}
227226
}

Source/Shared/Extensions/EventExtensions.cs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,7 @@ public static bool IsLog(this Event ev) {
6868
public static bool IsFeatureUsage(this Event ev) {
6969
return ev.Type == Event.KnownTypes.FeatureUsage;
7070
}
71-
72-
/// <summary>
73-
/// Returns true if the event type is session heartbeat.
74-
/// </summary>
75-
public static bool IsSessionHeartbeat(this Event ev) {
76-
return ev.Type == Event.KnownTypes.SessionHeartbeat;
77-
}
78-
71+
7972
/// <summary>
8073
/// Returns true if the event type is session start.
8174
/// </summary>

0 commit comments

Comments
 (0)