diff --git a/src/Discord.Net.Net45/Discord.Net.csproj b/src/Discord.Net.Net45/Discord.Net.csproj
index aa80c301f..c86d20878 100644
--- a/src/Discord.Net.Net45/Discord.Net.csproj
+++ b/src/Discord.Net.Net45/Discord.Net.csproj
@@ -478,6 +478,9 @@
Net\HttpException.cs
+
+ Net\Rest\CompletedRequestEventArgs.cs
+
Net\Rest\IRestEngine.cs
diff --git a/src/Discord.Net/DiscordClient.Events.cs b/src/Discord.Net/DiscordClient.Events.cs
index d078b3105..5b620ef38 100644
--- a/src/Discord.Net/DiscordClient.Events.cs
+++ b/src/Discord.Net/DiscordClient.Events.cs
@@ -51,8 +51,8 @@ namespace Discord
=> OnEvent(MessageDeleted, new MessageEventArgs(msg));
private void OnMessageReceived(Message msg)
=> OnEvent(MessageReceived, new MessageEventArgs(msg));
- /*private void OnMessageSent(Message msg)
- => OnEvent(MessageSent, new MessageEventArgs(msg));*/
+ internal void OnMessageSent(Message msg)
+ => OnEvent(MessageSent, new MessageEventArgs(msg));
private void OnMessageUpdated(Message msg)
=> OnEvent(MessageUpdated, new MessageEventArgs(msg));
diff --git a/src/Discord.Net/Net/Rest/CompletedRequestEventArgs.cs b/src/Discord.Net/Net/Rest/CompletedRequestEventArgs.cs
new file mode 100644
index 000000000..1bee431b0
--- /dev/null
+++ b/src/Discord.Net/Net/Rest/CompletedRequestEventArgs.cs
@@ -0,0 +1,19 @@
+using Discord.API;
+
+namespace Discord.Net.Rest
+{
+ public class CompletedRequestEventArgs : RequestEventArgs
+ {
+ public object Response { get; set; }
+ public string ResponseJson { get; set; }
+ public double Milliseconds { get; set; }
+
+ public CompletedRequestEventArgs(IRestRequest request, object response, string responseJson, double milliseconds)
+ : base(request)
+ {
+ Response = response;
+ ResponseJson = responseJson;
+ Milliseconds = milliseconds;
+ }
+ }
+}
diff --git a/src/Discord.Net/Net/Rest/RequestEventArgs.cs b/src/Discord.Net/Net/Rest/RequestEventArgs.cs
index 0741c88db..4f579bb57 100644
--- a/src/Discord.Net/Net/Rest/RequestEventArgs.cs
+++ b/src/Discord.Net/Net/Rest/RequestEventArgs.cs
@@ -1,20 +1,15 @@
-using System;
+using Discord.API;
+using System;
namespace Discord.Net.Rest
{
public class RequestEventArgs : EventArgs
{
- public string Method { get; }
- public string Path { get; }
- public string Payload { get; }
- public double ElapsedMilliseconds { get; }
+ public IRestRequest Request { get; set; }
- public RequestEventArgs(string method, string path, string payload, double milliseconds)
+ public RequestEventArgs(IRestRequest request)
{
- Method = method;
- Path = path;
- Payload = payload;
- ElapsedMilliseconds = milliseconds;
+ Request = request;
}
}
}
diff --git a/src/Discord.Net/Net/Rest/RestClient.cs b/src/Discord.Net/Net/Rest/RestClient.cs
index 0293efb50..c7814c638 100644
--- a/src/Discord.Net/Net/Rest/RestClient.cs
+++ b/src/Discord.Net/Net/Rest/RestClient.cs
@@ -10,7 +10,27 @@ namespace Discord.Net.Rest
{
public sealed partial class RestClient
{
- private readonly DiscordConfig _config;
+ private struct RestResults
+ {
+ public string Response { get; set; }
+ public double Milliseconds { get; set; }
+
+ public RestResults(string response, double milliseconds)
+ {
+ Response = response;
+ Milliseconds = milliseconds;
+ }
+ }
+
+ public event EventHandler SendingRequest = delegate { };
+ public event EventHandler SentRequest = delegate { };
+
+ private void OnSendingRequest(IRestRequest request)
+ => SendingRequest(this, new RequestEventArgs(request));
+ private void OnSentRequest(IRestRequest request, object response, string responseJson, double milliseconds)
+ => SentRequest(this, new CompletedRequestEventArgs(request, response, responseJson, milliseconds));
+
+ private readonly DiscordConfig _config;
private readonly IRestEngine _engine;
private string _token;
private JsonSerializerSettings _deserializeSettings;
@@ -48,21 +68,48 @@ namespace Discord.Net.Rest
_deserializeSettings.CheckAdditionalContent = false;
_deserializeSettings.MissingMemberHandling = MissingMemberHandling.Ignore;
#endif
+
+ if (Logger.Level >= LogSeverity.Verbose)
+ {
+ this.SentRequest += (s, e) =>
+ {
+ string log = $"{e.Request.Method} {e.Request.Endpoint}: {e.Milliseconds} ms";
+ if (_config.LogLevel >= LogSeverity.Debug)
+ {
+ if (e.Request is IRestFileRequest)
+ log += $" [{(e.Request as IRestFileRequest).Filename}]";
+ else if (e.Response != null)
+ {
+ if (e.Request.IsPrivate)
+ log += $" [Hidden]";
+ else
+ log += $" {e.ResponseJson}";
+ }
+ }
+ Logger.Verbose(log);
+ };
+ }
}
public async Task Send(IRestRequest request)
where ResponseT : class
{
if (request == null) throw new ArgumentNullException(nameof(request));
-
- string responseJson = await Send(request, true).ConfigureAwait(false);
- return DeserializeResponse(responseJson);
- }
- public Task Send(IRestRequest request)
+
+ OnSendingRequest(request);
+ var results = await Send(request, true).ConfigureAwait(false);
+ var response = DeserializeResponse(results.Response);
+ OnSentRequest(request, response, results.Response, results.Milliseconds);
+
+ return response;
+ }
+ public async Task Send(IRestRequest request)
{
if (request == null) throw new ArgumentNullException(nameof(request));
-
- return Send(request, false);
+
+ OnSendingRequest(request);
+ var results = await Send(request, false).ConfigureAwait(false);
+ OnSentRequest(request, null, null, results.Milliseconds);
}
public async Task Send(IRestFileRequest request)
@@ -70,80 +117,47 @@ namespace Discord.Net.Rest
{
if (request == null) throw new ArgumentNullException(nameof(request));
- string requestJson = JsonConvert.SerializeObject(request.Payload);
- string responseJson = await SendFile(request, true).ConfigureAwait(false);
- return DeserializeResponse(responseJson);
+ OnSendingRequest(request);
+ var requestJson = JsonConvert.SerializeObject(request.Payload);
+ var results = await SendFile(request, true).ConfigureAwait(false);
+ var response = DeserializeResponse(results.Response);
+ OnSentRequest(request, response, results.Response, results.Milliseconds);
+
+ return response;
}
- public Task Send(IRestFileRequest request)
+ public async Task Send(IRestFileRequest request)
{
if (request == null) throw new ArgumentNullException(nameof(request));
-
- return SendFile(request, false);
+
+ OnSendingRequest(request);
+ var results = await SendFile(request, false);
+ OnSentRequest(request, null, null, results.Milliseconds);
}
- private async Task Send(IRestRequest request, bool hasResponse)
+ private async Task Send(IRestRequest request, bool hasResponse)
{
- var method = request.Method;
- var path = request.Endpoint;
object payload = request.Payload;
- var isPrivate = request.IsPrivate;
-
string requestJson = null;
if (payload != null)
requestJson = JsonConvert.SerializeObject(payload);
- Stopwatch stopwatch = null;
- if (Logger.Level >= LogSeverity.Verbose)
- stopwatch = Stopwatch.StartNew();
-
- string responseJson = await _engine.Send(method, path, requestJson, CancelToken).ConfigureAwait(false);
-
- if (Logger.Level >= LogSeverity.Verbose)
- {
- stopwatch.Stop();
- double milliseconds = Math.Round(stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond, 2);
-
- string log = $"{method} {path}: {milliseconds} ms";
- if (payload != null && _config.LogLevel >= LogSeverity.Debug)
- {
- if (isPrivate)
- log += $" [Hidden]";
- else
- log += $" {requestJson}";
- }
- Logger.Verbose(log);
- }
+ Stopwatch stopwatch = Stopwatch.StartNew();
+ string responseJson = await _engine.Send(request.Method, request.Endpoint, requestJson, CancelToken).ConfigureAwait(false);
+ stopwatch.Stop();
- return responseJson;
+ double milliseconds = Math.Round((double)stopwatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000.0, 2);
+ return new RestResults(responseJson, milliseconds);
}
- private async Task SendFile(IRestFileRequest request, bool hasResponse)
+ private async Task SendFile(IRestFileRequest request, bool hasResponse)
{
- var method = request.Method;
- var path = request.Endpoint;
- var filename = request.Filename;
- var stream = request.Stream;
- var isPrivate = request.IsPrivate;
-
- Stopwatch stopwatch = null;
- if (Logger.Level >= LogSeverity.Verbose)
- stopwatch = Stopwatch.StartNew();
-
- string responseJson = await _engine.SendFile(method, path, filename, stream, CancelToken).ConfigureAwait(false);
-
- if (Logger.Level >= LogSeverity.Verbose)
- {
- stopwatch.Stop();
- double milliseconds = Math.Round(stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond, 2);
-
- string log = $"{method} {path}: {milliseconds} ms";
- if (_config.LogLevel >= LogSeverity.Debug && !isPrivate)
- log += $" {filename}";
- Logger.Verbose(log);
- }
+ Stopwatch stopwatch = Stopwatch.StartNew();
+ string responseJson = await _engine.SendFile(request.Method, request.Endpoint, request.Filename, request.Stream, CancelToken).ConfigureAwait(false);
+ stopwatch.Stop();
- return responseJson;
- }
+ double milliseconds = Math.Round((double)stopwatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000.0, 2);
+ return new RestResults(responseJson, milliseconds);
+ }
private T DeserializeResponse(string json)
{
diff --git a/src/Discord.Net/Net/WebSockets/WebSocket.cs b/src/Discord.Net/Net/WebSockets/WebSocket.cs
index 20b7d6547..935d9a2c1 100644
--- a/src/Discord.Net/Net/WebSockets/WebSocket.cs
+++ b/src/Discord.Net/Net/WebSockets/WebSocket.cs
@@ -89,6 +89,7 @@ namespace Discord.Net.WebSockets
}
catch (Exception ex)
{
+ //TODO: Should this be inside the lock?
await _taskManager.SignalError(ex);
throw;
}