< Summary - Jellyfin

Information
Class: Jellyfin.Api.Controllers.ClientLogController
Assembly: Jellyfin.Api
File(s): /srv/git/jellyfin/Jellyfin.Api/Controllers/ClientLogController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 20
Coverable lines: 20
Total lines: 79
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 10
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 1/23/2026 - 12:11:06 AM Line coverage: 0% (0/11) Branch coverage: 0% (0/6) Total lines: 784/19/2026 - 12:14:27 AM Line coverage: 0% (0/20) Branch coverage: 0% (0/10) Total lines: 784/27/2026 - 12:15:04 AM Line coverage: 0% (0/20) Branch coverage: 0% (0/10) Total lines: 79 1/23/2026 - 12:11:06 AM Line coverage: 0% (0/11) Branch coverage: 0% (0/6) Total lines: 784/19/2026 - 12:14:27 AM Line coverage: 0% (0/20) Branch coverage: 0% (0/10) Total lines: 784/27/2026 - 12:15:04 AM Line coverage: 0% (0/20) Branch coverage: 0% (0/10) Total lines: 79

Coverage delta

Coverage delta 1 -1

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
LogFile()0%2040%
GetRequestInformation()0%4260%

File(s)

/srv/git/jellyfin/Jellyfin.Api/Controllers/ClientLogController.cs

#LineLine coverage
 1using System.Net.Mime;
 2using System.Threading.Tasks;
 3using Jellyfin.Api.Attributes;
 4using Jellyfin.Api.Extensions;
 5using Jellyfin.Api.Models.ClientLogDtos;
 6using MediaBrowser.Controller.ClientEvent;
 7using MediaBrowser.Controller.Configuration;
 8using Microsoft.AspNetCore.Authorization;
 9using Microsoft.AspNetCore.Http;
 10using Microsoft.AspNetCore.Mvc;
 11
 12namespace Jellyfin.Api.Controllers;
 13
 14/// <summary>
 15/// Client log controller.
 16/// </summary>
 17[Authorize]
 18[Tags("System")]
 19public class ClientLogController : BaseJellyfinApiController
 20{
 21    private const int MaxDocumentSize = 1_000_000;
 22    private readonly IClientEventLogger _clientEventLogger;
 23    private readonly IServerConfigurationManager _serverConfigurationManager;
 24
 25    /// <summary>
 26    /// Initializes a new instance of the <see cref="ClientLogController"/> class.
 27    /// </summary>
 28    /// <param name="clientEventLogger">Instance of the <see cref="IClientEventLogger"/> interface.</param>
 29    /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</p
 030    public ClientLogController(
 031        IClientEventLogger clientEventLogger,
 032        IServerConfigurationManager serverConfigurationManager)
 33    {
 034        _clientEventLogger = clientEventLogger;
 035        _serverConfigurationManager = serverConfigurationManager;
 036    }
 37
 38    /// <summary>
 39    /// Upload a document.
 40    /// </summary>
 41    /// <response code="200">Document saved.</response>
 42    /// <response code="403">Event logging disabled.</response>
 43    /// <response code="413">Upload size too large.</response>
 44    /// <returns>Create response.</returns>
 45    [HttpPost("Document")]
 46    [ProducesResponseType(typeof(ClientLogDocumentResponseDto), StatusCodes.Status200OK)]
 47    [ProducesResponseType(StatusCodes.Status403Forbidden)]
 48    [ProducesResponseType(StatusCodes.Status413PayloadTooLarge)]
 49    [AcceptsFile(MediaTypeNames.Text.Plain)]
 50    [RequestSizeLimit(MaxDocumentSize)]
 51    public async Task<ActionResult<ClientLogDocumentResponseDto>> LogFile()
 52    {
 053        if (!_serverConfigurationManager.Configuration.AllowClientLogUpload)
 54        {
 055            return Forbid();
 56        }
 57
 058        if (Request.ContentLength > MaxDocumentSize)
 59        {
 60            // Manually validate to return proper status code.
 061            return StatusCode(StatusCodes.Status413PayloadTooLarge, $"Payload must be less than {MaxDocumentSize:N0} byt
 62        }
 63
 064        var (clientName, clientVersion) = GetRequestInformation();
 065        var fileName = await _clientEventLogger.WriteDocumentAsync(clientName, clientVersion, Request.Body)
 066            .ConfigureAwait(false);
 067        return Ok(new ClientLogDocumentResponseDto(fileName));
 068    }
 69
 70    private (string ClientName, string ClientVersion) GetRequestInformation()
 71    {
 072        var clientName = HttpContext.User.GetClient() ?? "unknown-client";
 073        var clientVersion = HttpContext.User.GetIsApiKey()
 074            ? "apikey"
 075            : HttpContext.User.GetVersion() ?? "unknown-version";
 76
 077        return (clientName, clientVersion);
 78    }
 79}