< Summary - Jellyfin

Information
Class: Jellyfin.Api.Middleware.ResponseTimeMiddleware
Assembly: Jellyfin.Api
File(s): /srv/git/jellyfin/Jellyfin.Api/Middleware/ResponseTimeMiddleware.cs
Line coverage
100%
Covered lines: 25
Uncovered lines: 0
Coverable lines: 25
Total lines: 68
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 5/8/2026 - 12:15:13 AM Line coverage: 100% (25/25) Total lines: 68

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Invoke()100%11100%

File(s)

/srv/git/jellyfin/Jellyfin.Api/Middleware/ResponseTimeMiddleware.cs

#LineLine coverage
 1using System.Diagnostics;
 2using System.Globalization;
 3using System.Threading.Tasks;
 4using MediaBrowser.Common.Extensions;
 5using MediaBrowser.Controller.Configuration;
 6using Microsoft.AspNetCore.Http;
 7using Microsoft.AspNetCore.Http.Extensions;
 8using Microsoft.Extensions.Logging;
 9
 10namespace Jellyfin.Api.Middleware;
 11
 12/// <summary>
 13/// Response time middleware.
 14/// </summary>
 15public class ResponseTimeMiddleware
 16{
 17    private const string ResponseHeaderResponseTime = "X-Response-Time-ms";
 18
 19    private readonly RequestDelegate _next;
 20    private readonly ILogger<ResponseTimeMiddleware> _logger;
 21
 22    /// <summary>
 23    /// Initializes a new instance of the <see cref="ResponseTimeMiddleware"/> class.
 24    /// </summary>
 25    /// <param name="next">Next request delegate.</param>
 26    /// <param name="logger">Instance of the <see cref="ILogger{ExceptionMiddleware}"/> interface.</param>
 27    public ResponseTimeMiddleware(
 28        RequestDelegate next,
 29        ILogger<ResponseTimeMiddleware> logger)
 30    {
 2231        _next = next;
 2232        _logger = logger;
 2233    }
 34
 35    /// <summary>
 36    /// Invoke request.
 37    /// </summary>
 38    /// <param name="context">Request context.</param>
 39    /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</p
 40    /// <returns>Task.</returns>
 41    public async Task Invoke(HttpContext context, IServerConfigurationManager serverConfigurationManager)
 42    {
 19943        var startTimestamp = Stopwatch.GetTimestamp();
 44
 19945        var enableWarning = serverConfigurationManager.Configuration.EnableSlowResponseWarning;
 19946        var warningThreshold = serverConfigurationManager.Configuration.SlowResponseThresholdMs;
 19947        context.Response.OnStarting(() =>
 19948        {
 19949            var responseTime = Stopwatch.GetElapsedTime(startTimestamp);
 19950            var responseTimeMs = responseTime.TotalMilliseconds;
 19951            if (enableWarning && responseTimeMs > warningThreshold && _logger.IsEnabled(LogLevel.Debug))
 19952            {
 19953                _logger.LogDebug(
 19954                    "Slow HTTP Response from {Url} to {RemoteIP} in {Elapsed:g} with Status Code {StatusCode}",
 19955                    context.Request.GetDisplayUrl(),
 19956                    context.GetNormalizedRemoteIP(),
 19957                    responseTime,
 19958                    context.Response.StatusCode);
 19959            }
 19960
 19961            context.Response.Headers[ResponseHeaderResponseTime] = responseTimeMs.ToString(CultureInfo.InvariantCulture)
 19962            return Task.CompletedTask;
 19963        });
 64
 65        // Call the next delegate/middleware in the pipeline
 19966        await this._next(context).ConfigureAwait(false);
 18967    }
 68}