Selaa lähdekoodia

Add X-Response-Time-ms header and log slow server response time

David 5 vuotta sitten
vanhempi
sitoutus
262e19b691

+ 78 - 0
Jellyfin.Server/Middleware/ResponseTimeMiddleware.cs

@@ -0,0 +1,78 @@
+using System.Diagnostics;
+using System.Globalization;
+using System.Threading.Tasks;
+using MediaBrowser.Controller.Configuration;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Extensions;
+using Microsoft.Extensions.Logging;
+
+namespace Jellyfin.Server.Middleware
+{
+    /// <summary>
+    /// Response time middleware.
+    /// </summary>
+    public class ResponseTimeMiddleware
+    {
+        private const string ResponseHeaderResponseTime = "X-Response-Time-ms";
+
+        private readonly RequestDelegate _next;
+        private readonly ILogger<ResponseTimeMiddleware> _logger;
+
+        private readonly bool _enableWarning;
+        private readonly long _warningThreshold;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ResponseTimeMiddleware"/> class.
+        /// </summary>
+        /// <param name="next">Next request delegate.</param>
+        /// <param name="logger">Instance of the <see cref="ILogger{ExceptionMiddleware}"/> interface.</param>
+        /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
+        public ResponseTimeMiddleware(
+            RequestDelegate next,
+            ILogger<ResponseTimeMiddleware> logger,
+            IServerConfigurationManager serverConfigurationManager)
+        {
+            _next = next;
+            _logger = logger;
+
+            _enableWarning = serverConfigurationManager.Configuration.EnableSlowResponseWarning;
+            _warningThreshold = serverConfigurationManager.Configuration.SlowResponseThresholdMs;
+        }
+
+        /// <summary>
+        /// Invoke request.
+        /// </summary>
+        /// <param name="context">Request context.</param>
+        /// <returns>Task.</returns>
+        public async Task Invoke(HttpContext context)
+        {
+            var watch = new Stopwatch();
+            watch.Start();
+
+            context.Response.OnStarting(() =>
+            {
+                watch.Stop();
+                LogWarning(context, watch);
+                var responseTimeForCompleteRequest = watch.ElapsedMilliseconds;
+                context.Response.Headers[ResponseHeaderResponseTime] = responseTimeForCompleteRequest.ToString(CultureInfo.InvariantCulture);
+                return Task.CompletedTask;
+            });
+
+            // Call the next delegate/middleware in the pipeline
+            await this._next(context).ConfigureAwait(false);
+        }
+
+        private void LogWarning(HttpContext context, Stopwatch watch)
+        {
+            if (_enableWarning && watch.ElapsedMilliseconds > _warningThreshold)
+            {
+                _logger.LogWarning(
+                    "Slow HTTP Response from {url} to {remoteIp} in {elapsed:g} with Status Code {statusCode}",
+                    context.Request.GetDisplayUrl(),
+                    context.Connection.RemoteIpAddress,
+                    watch.Elapsed,
+                    context.Response.StatusCode);
+            }
+        }
+    }
+}

+ 2 - 0
Jellyfin.Server/Startup.cs

@@ -63,6 +63,8 @@ namespace Jellyfin.Server
 
             app.UseMiddleware<ExceptionMiddleware>();
 
+            app.UseMiddleware<ResponseTimeMiddleware>();
+
             app.UseWebSockets();
 
             app.UseResponseCompression();

+ 13 - 0
MediaBrowser.Model/Configuration/ServerConfiguration.cs

@@ -252,6 +252,16 @@ namespace MediaBrowser.Model.Configuration
 
         public string[] UninstalledPlugins { get; set; }
 
+        /// <summary>
+        /// Gets or sets a value indicating whether slow server responses should be logged as a warning.
+        /// </summary>
+        public bool EnableSlowResponseWarning { get; set; }
+
+        /// <summary>
+        /// Gets or sets the threshold for the slow response time warning in ms.
+        /// </summary>
+        public long SlowResponseThresholdMs { get; set; }
+
         /// <summary>
         /// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
         /// </summary>
@@ -351,6 +361,9 @@ namespace MediaBrowser.Model.Configuration
                     DisabledImageFetchers = new[] { "The Open Movie Database", "TheMovieDb" }
                 }
             };
+
+            EnableSlowResponseWarning = true;
+            SlowResponseThresholdMs = 500;
         }
     }