Skip to content

Commit

Permalink
Merge pull request #123 from exceptionless/bug/format-exception
Browse files Browse the repository at this point in the history
Fixed a bug that was causing a format exception & proxy support
  • Loading branch information
niemyjski authored Sep 17, 2016
2 parents fdaaa84 + 2a76628 commit f0494c8
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 46 deletions.
4 changes: 2 additions & 2 deletions src/Exceptionless.Tests/Plugins/PluginTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ public void VerifyDeduplication() {
var errorPlugin = new ErrorPlugin();

EventPluginContext mergedContext = null;
using (var duplicateCheckerPlugin = new DuplicateCheckerPlugin(TimeSpan.FromMilliseconds(20))) {
using (var duplicateCheckerPlugin = new DuplicateCheckerPlugin(TimeSpan.FromMilliseconds(40))) {
for (int index = 0; index < 10; index++) {
var builder = GetException().ToExceptionless();
var context = new EventPluginContext(client, builder.Target, builder.PluginContextData);
Expand All @@ -745,7 +745,7 @@ public void VerifyDeduplication() {
}
}

Thread.Sleep(50);
Thread.Sleep(100);
Assert.Equal(9, mergedContext.Event.Count.GetValueOrDefault());
}

Expand Down
2 changes: 1 addition & 1 deletion src/Exceptionless.Tests/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
}
},
"dependencies": {
"BenchmarkDotNet": "0.9.8",
"BenchmarkDotNet": "0.9.9",
"Exceptionless": {
"target": "project"
},
Expand Down
16 changes: 11 additions & 5 deletions src/Exceptionless/Configuration/ExceptionlessConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Reflection;
using Exceptionless.Dependency;
using Exceptionless.Plugins;
Expand Down Expand Up @@ -99,11 +100,6 @@ public string HeartbeatServerUrl {
}
}

/// <summary>
/// Used to identify the client that sent the events to the server.
/// </summary>
public string UserAgent { get; set; }

/// <summary>
/// The API key that will be used when sending events to the server.
/// </summary>
Expand All @@ -122,6 +118,16 @@ public string ApiKey {
}
}

/// <summary>
/// Used to identify the client that sent the events to the server.
/// </summary>
public string UserAgent { get; set; }

/// <summary>
/// Ability to set a custom proxy. By default, .NET will use any system or configuration defined proxy settings.
/// </summary>
public IWebProxy Proxy { get; set; }

/// <summary>
/// Whether the client is currently enabled or not. If it is disabled, submitted errors will be discarded and no data will be sent to the server.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Exceptionless/Configuration/SettingsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public static void CheckVersion(int version, ExceptionlessConfiguration config)
public static void UpdateSettings(ExceptionlessConfiguration config, int? version = null) {
if (config == null || !config.IsValid || !config.Enabled)
return;

try {
if (!version.HasValue || version < 0)
version = GetVersion(config);
Expand Down
2 changes: 1 addition & 1 deletion src/Exceptionless/ExceptionlessClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ public void SubmitEvent(Event ev, ContextData pluginContextData = null) {
_queue.Value.Enqueue(ev);

if (!String.IsNullOrEmpty(ev.ReferenceId)) {
_log.Value.FormattedTrace(typeof(ExceptionlessClient), "Setting last reference id '{0}'", ev.ReferenceId);
_log.Value.FormattedTrace(typeof(ExceptionlessClient), "Setting last reference id: {0}", ev.ReferenceId);
_lastReferenceIdManager.Value.SetLast(ev.ReferenceId);
}

Expand Down
30 changes: 19 additions & 11 deletions src/Exceptionless/Logging/ExceptionlessLogExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,71 +11,79 @@ public static void Error(this IExceptionlessLog log, Type source, Exception exce
}

public static void FormattedError(this IExceptionlessLog log, Type source, Exception exception, string format, params object[] args) {
log.Error(String.Format(format, args), GetSourceName(source), exception);
log.Error(GetMessage(format, args), GetSourceName(source), exception);
}

public static void FormattedError(this IExceptionlessLog log, Type source, string format, params object[] args) {
log.Error(String.Format(format, args), GetSourceName(source));
log.Error(GetMessage(format, args), GetSourceName(source));
}

public static void Info(this IExceptionlessLog log, Type source, string message) {
log.Info(message, GetSourceName(source));
}

public static void FormattedInfo(this IExceptionlessLog log, Type source, string format, params object[] args) {
log.Info(String.Format(format, args), GetSourceName(source));
log.Info(GetMessage(format, args), GetSourceName(source));
}

public static void Debug(this IExceptionlessLog log, Type source, string message) {
log.Debug(message, GetSourceName(source));
}

public static void FormattedDebug(this IExceptionlessLog log, Type source, string format, params object[] args) {
log.Debug(String.Format(format, args), GetSourceName(source));
log.Debug(GetMessage(format, args), GetSourceName(source));
}

public static void Warn(this IExceptionlessLog log, Type source, string message) {
log.Warn(message, GetSourceName(source));
}

public static void FormattedWarn(this IExceptionlessLog log, Type source, string format, params object[] args) {
log.Warn(String.Format(format, args), GetSourceName(source));
log.Warn(GetMessage(format, args), GetSourceName(source));
}

public static void Trace(this IExceptionlessLog log, Type source, string message) {
log.Trace(message, GetSourceName(source));
}

public static void FormattedTrace(this IExceptionlessLog log, Type source, string format, params object[] args) {
log.Trace(String.Format(format, args), GetSourceName(source));
log.Trace(GetMessage(format, args), GetSourceName(source));
}

public static void Error(this IExceptionlessLog log, Exception exception, string message) {
log.Error(message, exception: exception);
}

public static void FormattedError(this IExceptionlessLog log, Exception exception, string format, params object[] args) {
log.Error(String.Format(format, args), exception: exception);
log.Error(GetMessage(format, args), exception: exception);
}

public static void FormattedError(this IExceptionlessLog log, string format, params object[] args) {
log.Error(String.Format(format, args));
log.Error(GetMessage(format, args));
}

public static void FormattedInfo(this IExceptionlessLog log, string format, params object[] args) {
log.Info(String.Format(format, args));
log.Info(GetMessage(format, args));
}

public static void FormattedDebug(this IExceptionlessLog log, string format, params object[] args) {
log.Debug(String.Format(format, args));
log.Debug(GetMessage(format, args));
}

public static void FormattedWarn(this IExceptionlessLog log, string format, params object[] args) {
log.Warn(String.Format(format, args));
log.Warn(GetMessage(format, args));
}

private static string GetSourceName(Type type) {
return type.Name;
}

private static string GetMessage(string format, params object[] args) {
try {
return String.Format(format, args);
} catch (Exception) {
return format;
}
}
}
}
10 changes: 5 additions & 5 deletions src/Exceptionless/Plugins/Default/1010_DuplicateCheckerPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,29 +32,29 @@ public DuplicateCheckerPlugin(TimeSpan? interval) {
public void Run(EventPluginContext context) {
int hashCode = context.Event.GetHashCode();
int count = context.Event.Count ?? 1;
context.Log.FormattedTrace(typeof(DuplicateCheckerPlugin), String.Concat("Checking event: ", context.Event.Message, " with hash: ", hashCode));
context.Log.FormattedTrace(typeof(DuplicateCheckerPlugin), "Checking event: {0} with hash: {1}", context.Event.Message, hashCode);

lock (_lock) {
// Increment the occurrence count if the event is already queued for submission.
var merged = _mergedEvents.FirstOrDefault(s => s.HashCode == hashCode);
if (merged != null) {
merged.IncrementCount(count);
merged.UpdateDate(context.Event.Date);
context.Log.FormattedInfo(typeof(DuplicateCheckerPlugin), String.Concat("Ignoring duplicate event with hash:", hashCode));
context.Log.FormattedInfo(typeof(DuplicateCheckerPlugin), "Ignoring duplicate event with hash: {0}", hashCode);
context.Cancel = true;
return;
}

DateTimeOffset repeatWindow = DateTimeOffset.UtcNow.Subtract(_interval);
if (_processed.Any(s => s.Item1 == hashCode && s.Item2 >= repeatWindow)) {
context.Log.FormattedInfo(typeof(DuplicateCheckerPlugin), String.Concat("Adding event with hash:", hashCode, " to cache."));
context.Log.FormattedInfo(typeof(DuplicateCheckerPlugin), "Adding event with hash: {0} to cache.", hashCode);
// This event is a duplicate for the first time, lets save it so we can delay it while keeping count
_mergedEvents.Enqueue(new MergedEvent(hashCode, context, count));
context.Cancel = true;
return;
}

context.Log.FormattedInfo(typeof(DuplicateCheckerPlugin), String.Concat("Enqueueing event with hash:", hashCode, " to cache."));
context.Log.FormattedInfo(typeof(DuplicateCheckerPlugin), "Enqueueing event with hash: {0} to cache.", hashCode);
_processed.Enqueue(Tuple.Create(hashCode, DateTimeOffset.UtcNow));

while (_processed.Count > 50)
Expand Down Expand Up @@ -116,7 +116,7 @@ public void Resubmit() {
_context.Resolver.GetEventQueue().Enqueue(_context.Event);

if (!String.IsNullOrEmpty(_context.Event.ReferenceId)) {
_context.Log.FormattedTrace(typeof(DuplicateCheckerPlugin), "Setting last reference id '{0}'", _context.Event.ReferenceId);
_context.Log.FormattedTrace(typeof(DuplicateCheckerPlugin), "Setting last reference id: {0}", _context.Event.ReferenceId);
_context.Resolver.GetLastReferenceIdManager().SetLast(_context.Event.ReferenceId);
}

Expand Down
4 changes: 2 additions & 2 deletions src/Exceptionless/Services/DefaultEnvironmentInfoCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public DefaultEnvironmentInfoCollector(IExceptionlessLog log) {
public EnvironmentInfo GetEnvironmentInfo() {
if (_environmentInfo != null) {
PopulateThreadInfo(_environmentInfo);
PopulateMemoryInfo(_environmentInfo);
PopulateMemoryInfo(_environmentInfo);
return _environmentInfo;
}

Expand Down Expand Up @@ -178,7 +178,7 @@ private void PopulateRuntimeInfo(EnvironmentInfo info) {
#if NETSTANDARD
computerInfo = Microsoft.Extensions.PlatformAbstractions.PlatformServices.Default;
#elif NET45
computerInfo = new Microsoft.VisualBasic.Devices.ComputerInfo();
computerInfo = new Microsoft.VisualBasic.Devices.ComputerInfo();
#endif
} catch (Exception ex) {
_log.FormattedInfo(typeof(DefaultEnvironmentInfoCollector), "Unable to get computer info. Error message: {0}", ex.Message);
Expand Down
37 changes: 20 additions & 17 deletions src/Exceptionless/Submission/DefaultSubmissionClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@

namespace Exceptionless.Submission {
public class DefaultSubmissionClient : ISubmissionClient, IDisposable {
private readonly HttpClient _client;
private readonly Lazy<HttpClient> _client;

public DefaultSubmissionClient(ExceptionlessConfiguration config) {
_client = CreateHttpClient(config.UserAgent);
_client = new Lazy<HttpClient>(() => CreateHttpClient(config));
}

public SubmissionResponse PostEvents(IEnumerable<Event> events, ExceptionlessConfiguration config, IJsonSerializer serializer) {
Expand All @@ -36,8 +36,8 @@ public SubmissionResponse PostEvents(IEnumerable<Event> events, ExceptionlessCon
if (data.Length > 1024 * 4)
content = new GzipContent(content);

_client.AddAuthorizationHeader(config.ApiKey);
response = _client.PostAsync(url, content).ConfigureAwait(false).GetAwaiter().GetResult();
_client.Value.AddAuthorizationHeader(config.ApiKey);
response = _client.Value.PostAsync(url, content).ConfigureAwait(false).GetAwaiter().GetResult();
} catch (Exception ex) {
return new SubmissionResponse(500, message: ex.Message);
}
Expand All @@ -48,7 +48,7 @@ public SubmissionResponse PostEvents(IEnumerable<Event> events, ExceptionlessCon

return new SubmissionResponse((int)response.StatusCode, GetResponseMessage(response));
}

public SubmissionResponse PostUserDescription(string referenceId, UserDescription description, ExceptionlessConfiguration config, IJsonSerializer serializer) {
if (!config.IsValid)
return new SubmissionResponse(500, message: "Invalid client configuration settings.");
Expand All @@ -64,8 +64,8 @@ public SubmissionResponse PostUserDescription(string referenceId, UserDescriptio
if (data.Length > 1024 * 4)
content = new GzipContent(content);

_client.AddAuthorizationHeader(config.ApiKey);
response = _client.PostAsync(url, content).ConfigureAwait(false).GetAwaiter().GetResult();
_client.Value.AddAuthorizationHeader(config.ApiKey);
response = _client.Value.PostAsync(url, content).ConfigureAwait(false).GetAwaiter().GetResult();
} catch (Exception ex) {
return new SubmissionResponse(500, message: ex.Message);
}
Expand All @@ -85,8 +85,8 @@ public SettingsResponse GetSettings(ExceptionlessConfiguration config, int versi

HttpResponseMessage response;
try {
_client.AddAuthorizationHeader(config.ApiKey);
response = _client.GetAsync(url).ConfigureAwait(false).GetAwaiter().GetResult();
_client.Value.AddAuthorizationHeader(config.ApiKey);
response = _client.Value.GetAsync(url).ConfigureAwait(false).GetAwaiter().GetResult();
} catch (Exception ex) {
var message = String.Concat("Unable to retrieve configuration settings. Exception: ", ex.GetMessage());
return new SettingsResponse(false, message: message);
Expand All @@ -105,22 +105,22 @@ public SettingsResponse GetSettings(ExceptionlessConfiguration config, int versi
var settings = serializer.Deserialize<ClientConfiguration>(json);
return new SettingsResponse(true, settings.Settings, settings.Version);
}

public void SendHeartbeat(string sessionIdOrUserId, bool closeSession, ExceptionlessConfiguration config) {
if (!config.IsValid)
return;

string url = String.Format("{0}/events/session/heartbeat?id={1}&close={2}", GetHeartbeatServiceEndPoint(config), sessionIdOrUserId, closeSession);
try {
_client.AddAuthorizationHeader(config.ApiKey);
_client.GetAsync(url).ConfigureAwait(false).GetAwaiter().GetResult();
_client.Value.AddAuthorizationHeader(config.ApiKey);
_client.Value.GetAsync(url).ConfigureAwait(false).GetAwaiter().GetResult();
} catch (Exception ex) {
var log = config.Resolver.GetLog();
log.Error(String.Concat("Error submitting heartbeat: ", ex.GetMessage()));
}
}

private HttpClient CreateHttpClient(string userAgent) {
protected virtual HttpClient CreateHttpClient(ExceptionlessConfiguration config) {
#if NET45
var handler = new WebRequestHandler { UseDefaultCredentials = true };
handler.ServerCertificateValidationCallback = delegate { return true; };
Expand All @@ -130,17 +130,19 @@ private HttpClient CreateHttpClient(string userAgent) {
//handler.ServerCertificateCustomValidationCallback = delegate { return true; };
#endif
#endif

if (handler.SupportsAutomaticDecompression)
handler.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip | DecompressionMethods.None;

if (handler.SupportsRedirectConfiguration)
handler.AllowAutoRedirect = true;


if (handler.SupportsProxy && config.Proxy != null)
handler.Proxy = config.Proxy;

var client = new HttpClient(handler, true);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.ExpectContinue = false;
client.DefaultRequestHeaders.UserAgent.ParseAdd(userAgent);
client.DefaultRequestHeaders.UserAgent.ParseAdd(config.UserAgent);

return client;
}
Expand Down Expand Up @@ -205,7 +207,8 @@ private Uri GetHeartbeatServiceEndPoint(ExceptionlessConfiguration config) {
}

public void Dispose() {
_client.Dispose();
if (_client.IsValueCreated)
_client.Value.Dispose();
}
}
}
2 changes: 1 addition & 1 deletion src/Platforms/Exceptionless.NLog/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"define": [ "NET45" ]
},
"dependencies": {
"NLog": "4.3.6"
"NLog": "4.3.8"
}
}
}
Expand Down

0 comments on commit f0494c8

Please sign in to comment.