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; }