public async Task <TResult> ReceiveAsync <TResult>(IQuery <TResult> query, CancellationToken cancellationToken = default)
        {
            var stopWatch = new Stopwatch();

            _metrics.Increment(new RequestCounterMetric(query));
            _metrics.Increment(new RequestGaugeMetric("generic_request_gauge", "Current request count"));
            try {
                stopWatch.Start();
                var result = await _next.ReceiveAsync(query, cancellationToken);

                stopWatch.Stop();

                _metrics.Observe(new RequestDurationMetric(query), stopWatch.ElapsedMilliseconds);

                return(result);
            }
            catch (Exception exception) {
                stopWatch.Stop();
                _metrics.Increment(new RequestFailureMetric(query, exception));

                throw;
            }
            finally {
                _metrics.Decrement(new RequestGaugeMetric("generic_request_gauge", "Current request count"));
            }
        }
        public async Task ReceiveAsync <TCommand>(TCommand command, CancellationToken cancellationToken = default) where TCommand : ICommand
        {
            var stopWatch = new Stopwatch();

            _metrics.Increment(new RequestCounterMetric(command));
            _metrics.Increment(new RequestGaugeMetric("generic_request_gauge", "Current request count"));

            try {
                stopWatch.Start();
                await _next.ReceiveAsync(command, cancellationToken);

                stopWatch.Stop();

                _metrics.Observe(new RequestDurationMetric(command), stopWatch.ElapsedMilliseconds);
            }
            catch (Exception exception) {
                stopWatch.Stop();
                _metrics.Increment(new RequestFailureMetric(command, exception));

                throw;
            }
            finally {
                _metrics.Decrement(new RequestGaugeMetric("generic_request_gauge", "Current request count"));
            }
        }
        protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            // If metrics aren't enabled, just forward the request and return the response.
            if (!factoryOptions.EnableMetrics)
            {
                return(await base.SendAsync(request, cancellationToken).ConfigureAwait(false));
            }

            // Gather metrics around the http call...
            IList <string> tags = new List <string> {
                { $"requestUri:{request.RequestUri}" },
                { $"commandGroup:{factoryOptions.CommandGroup}" },
                { $"commandName:{factoryOptions.CommandName}" }
            };

            metricsService.Increment($"{prefix}.request", tags: tags);

            Stopwatch stopwatch = Stopwatch.StartNew();

            try
            {
                HttpResponseMessage response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);

                stopwatch.Stop();

                tags.Add($"statusCode:{response.StatusCode}");
                metricsService.Timer($"{prefix}.timing", stopwatch.ElapsedMilliseconds, tags: tags);

                if (response.StatusCode == HttpStatusCode.RequestTimeout ||
                    response.StatusCode == HttpStatusCode.GatewayTimeout)
                {
                    metricsService.Increment($"{prefix}.timeout", tags: tags);
                }
                else if ((int)response.StatusCode >= 500)
                {
                    metricsService.Increment($"{prefix}.failure", tags: tags);
                }
                else
                {
                    metricsService.Increment($"{prefix}.success", tags: tags);
                }

                return(response);
            }
            catch (Exception ex)
            {
                stopwatch.Stop();
                metricsService.Timer($"{prefix}.timing", stopwatch.ElapsedMilliseconds, tags: new[] { $"request:{request.RequestUri}", $"exceptionType: { ex.GetType().FullName }" });
                metricsService.Increment($"{prefix}.failure", tags: new[] { $"request:{request.RequestUri}", $"exceptionType: { ex.GetType().FullName }" });
                throw;
            }
        }