Skip to content

Commit

Permalink
Fixed issues with async event handlers and improved trace logging (#306)
Browse files Browse the repository at this point in the history
* Fixed issues with async event handlers and improved trace logging

* Ensure flush is called on shutdown
  • Loading branch information
niemyjski authored May 9, 2023
1 parent eab5003 commit 61e3291
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 19 deletions.
16 changes: 14 additions & 2 deletions src/Exceptionless/Configuration/SettingsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ public static async Task UpdateSettingsAsync(ExceptionlessConfiguration config,
if (config == null || !config.IsValid || !config.Enabled || _isUpdatingSettings)
return;

var log = config.Resolver.GetLog();

try {
_isUpdatingSettings = true;
if (!version.HasValue || version < 0)
Expand All @@ -84,8 +86,18 @@ public static async Task UpdateSettingsAsync(ExceptionlessConfiguration config,
var client = config.Resolver.GetSubmissionClient();

var response = await client.GetSettingsAsync(config, version.Value, serializer).ConfigureAwait(false);
if (!response.Success || response.Settings == null)
if (!response.Success) {
string message = String.IsNullOrEmpty(response.Message)
? "An error occurred retrieving configuration settings."
: String.Concat("An error occurred retrieving configuration settings: ", response.Message);
log.Error(typeof(SettingsManager), response.Exception, message);
return;
}

if (response.Settings == null) {
log.Warn(typeof(SettingsManager), "Error occurred updating settings: Server settings was null");
return;
}

var savedServerSettings = GetSavedServerSettings(config);
config.Settings.Apply(response.Settings);
Expand All @@ -101,7 +113,7 @@ public static async Task UpdateSettingsAsync(ExceptionlessConfiguration config,
var fileStorage = config.Resolver.GetFileStorage();
fileStorage.SaveObject(GetConfigPath(config), response.Settings);
} catch (Exception ex) {
config.Resolver.GetLog().Error(typeof(SettingsManager), ex, "Error occurred updating settings.");
log.Error(typeof(SettingsManager), ex, "Error occurred updating settings.");
} finally {
_isUpdatingSettings = false;
}
Expand Down
1 change: 1 addition & 0 deletions src/Exceptionless/ExceptionlessClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ public Task ProcessQueueAsync() {
}
}

_log.Value.Info(typeof(ExceptionlessClient), "Processing event queue");
return _queue.Value.ProcessAsync();
}

Expand Down
49 changes: 38 additions & 11 deletions src/Exceptionless/Extensions/ExceptionlessClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ public static void Startup(this ExceptionlessClient client, string apiKey = null
if (client.Configuration.UpdateSettingsWhenIdleInterval == null)
client.Configuration.UpdateSettingsWhenIdleInterval = TimeSpan.FromMinutes(2);

var log = client.Configuration.Resolver.GetLog();
log.FormattedInfo(typeof(ExceptionlessClient), "Startup called ApiKey={0} ServerUrl={1}", client.Configuration.ApiKey, client.Configuration.ServerUrl);

client.RegisterAppDomainUnhandledExceptionHandler();

// make sure that queued events are sent when the app exits
Expand All @@ -36,6 +39,8 @@ public static void Startup(this ExceptionlessClient client, string apiKey = null

if (client.Configuration.SessionsEnabled)
client.SubmitSessionStart();

log.Info(typeof(ExceptionlessClient), "Startup finished");
}

/// <summary>
Expand All @@ -46,13 +51,21 @@ public static async Task ShutdownAsync(this ExceptionlessClient client) {
if (client == null)
throw new ArgumentNullException(nameof(client));

var log = client.Configuration.Resolver.GetLog();
log.Info(typeof(ExceptionlessClient), "Shutdown called");

client.UnregisterAppDomainUnhandledExceptionHandler();
client.UnregisterOnProcessExitHandler();
client.UnregisterTaskSchedulerUnobservedTaskExceptionHandler();

await client.ProcessQueueAsync().ConfigureAwait(false);
if (client.Configuration.SessionsEnabled)
if (client.Configuration.SessionsEnabled) {
log.Info(typeof(ExceptionlessClient), "Sending Session End Heartbeat");
await client.SubmitSessionEndAsync().ConfigureAwait(false);
}

log.Info(typeof(ExceptionlessClient), "Shutdown finished");
log.Flush();
}

#region Submission Extensions
Expand Down Expand Up @@ -348,25 +361,32 @@ public static void RegisterAppDomainUnhandledExceptionHandler(this Exceptionless
throw new ArgumentNullException(nameof(client));

if (_onAppDomainUnhandledException == null) {
_onAppDomainUnhandledException = async (sender, args) => {
_onAppDomainUnhandledException = (sender, args) => {
var exception = args.ExceptionObject as Exception;
if (exception == null)
return;

var log = client.Configuration.Resolver.GetLog();
try {
log.Info(typeof(ExceptionlessClient), "AppDomain.CurrentDomain.UnhandledException called");

var contextData = new ContextData();
contextData.MarkAsUnhandledError();
contextData.SetSubmissionMethod("AppDomainUnhandledException");

exception.ToExceptionless(contextData, client).Submit();

// process queue immediately since the app is about to exit.
await client.ProcessQueueAsync().ConfigureAwait(false);
client.ProcessQueueAsync().ConfigureAwait(false).GetAwaiter().GetResult();

if (client.Configuration.SessionsEnabled) {
log.Info(typeof(ExceptionlessClient), "Sending Session End Heartbeat");
client.SubmitSessionEndAsync().ConfigureAwait(false).GetAwaiter().GetResult();
}

if (client.Configuration.SessionsEnabled)
await client.SubmitSessionEndAsync().ConfigureAwait(false);
log.Info(typeof(ExceptionlessClient), "AppDomain.CurrentDomain.UnhandledException finished");
log.Flush();
} catch (Exception ex) {
var log = client.Configuration.Resolver.GetLog();
log.Error(typeof(ExceptionlessClientExtensions), ex, String.Concat("An error occurred while processing AppDomain unhandled exception: ", ex.Message));
}
};
Expand Down Expand Up @@ -397,14 +417,21 @@ public static void RegisterOnProcessExitHandler(this ExceptionlessClient client)
throw new ArgumentNullException(nameof(client));

if (_onProcessExit == null) {
_onProcessExit = async (sender, args) => {
_onProcessExit = (sender, args) => {
var log = client.Configuration.Resolver.GetLog();
try {
await client.ProcessQueueAsync().ConfigureAwait(false);
log.Info(typeof(ExceptionlessClient), "ProcessExit called");

client.ProcessQueueAsync().ConfigureAwait(false).GetAwaiter().GetResult();

if (client.Configuration.SessionsEnabled) {
log.Info(typeof(ExceptionlessClient), "Sending Session End Heartbeat");
client.SubmitSessionEndAsync().ConfigureAwait(false).GetAwaiter().GetResult();
}

if (client.Configuration.SessionsEnabled)
await client.SubmitSessionEndAsync().ConfigureAwait(false);
log.Info(typeof(ExceptionlessClient), "ProcessExit finished");
log.Flush();
} catch (Exception ex) {
var log = client.Configuration.Resolver.GetLog();
log.Error(typeof(ExceptionlessClientExtensions), ex, String.Concat("An error occurred while processing process exit: ", ex.Message));
}
};
Expand Down
11 changes: 5 additions & 6 deletions src/Exceptionless/Submission/DefaultSubmissionClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public async Task<SubmissionResponse> PostEventsAsync(IEnumerable<Event> events,
_client.Value.AddAuthorizationHeader(config.ApiKey);
response = await _client.Value.PostAsync(url, content).ConfigureAwait(false);
} catch (Exception ex) {
return new SubmissionResponse(500, exception: ex);
return new SubmissionResponse(500, message: ex.GetMessage(), exception: ex);
}

if (Int32.TryParse(GetSettingsVersionHeader(response.Headers), out int settingsVersion))
Expand Down Expand Up @@ -75,7 +75,7 @@ public async Task<SubmissionResponse> PostUserDescriptionAsync(string referenceI
_client.Value.AddAuthorizationHeader(config.ApiKey);
response = await _client.Value.PostAsync(url, content).ConfigureAwait(false);
} catch (Exception ex) {
return new SubmissionResponse(500, exception: ex);
return new SubmissionResponse(500, message: ex.GetMessage(), exception: ex);
}

if (Int32.TryParse(GetSettingsVersionHeader(response.Headers), out int settingsVersion))
Expand All @@ -100,16 +100,15 @@ public async Task<SettingsResponse> GetSettingsAsync(ExceptionlessConfiguration
_client.Value.AddAuthorizationHeader(config.ApiKey);
response = await _client.Value.GetAsync(url).ConfigureAwait(false);
} catch (Exception ex) {
var message = String.Concat("Unable to retrieve configuration settings. Exception: ", ex.GetMessage());
return new SettingsResponse(false, message: message);
return new SettingsResponse(false, message: ex.GetMessage(), exception: ex);
}

if (response != null && response.StatusCode == HttpStatusCode.NotModified)
return SettingsResponse.NotModified;

if (response == null || response.StatusCode != HttpStatusCode.OK) {
string message = await GetResponseMessageAsync(response).ConfigureAwait(false);
return new SettingsResponse(false, message: String.Concat("Unable to retrieve configuration settings: ", message));
return new SettingsResponse(false, message: message);
}

string json = await GetResponseTextAsync(response).ConfigureAwait(false);
Expand All @@ -130,7 +129,7 @@ public async Task SendHeartbeatAsync(string sessionIdOrUserId, bool closeSession
await _client.Value.GetAsync(url).ConfigureAwait(false);
} catch (Exception ex) {
var log = config.Resolver.GetLog();
log.Error(String.Concat("Error submitting heartbeat: ", ex.GetMessage()));
log.Error(String.Concat("Error submitting heartbeat: ", ex.GetMessage()), exception: ex);
}
}

Expand Down

0 comments on commit 61e3291

Please sign in to comment.