< Summary - Kestrun — Combined Coverage

Information
Class: Kestrun.SignalR.KestrunHub
Assembly: Kestrun
File(s): /home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/SignalR/KestrunHub.cs
Tag: Kestrun/Kestrun@2d87023b37eb91155071c91dd3d6a2eeb3004705
Line coverage
13%
Covered lines: 3
Uncovered lines: 19
Coverable lines: 22
Total lines: 76
Line coverage: 13.6%
Branch coverage
0%
Covered branches: 0
Total branches: 2
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 10/15/2025 - 21:27:26 Line coverage: 13.6% (3/22) Branch coverage: 0% (0/2) Total lines: 76 Tag: Kestrun/Kestrun@c33ec02a85e4f8d6061aeaab5a5e8c3a8b665594 10/15/2025 - 21:27:26 Line coverage: 13.6% (3/22) Branch coverage: 0% (0/2) Total lines: 76 Tag: Kestrun/Kestrun@c33ec02a85e4f8d6061aeaab5a5e8c3a8b665594

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
OnConnectedAsync()100%210%
OnDisconnectedAsync()0%620%
JoinGroup()100%210%
LeaveGroup()100%210%
Echo()100%210%

File(s)

/home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/SignalR/KestrunHub.cs

#LineLine coverage
 1using Microsoft.AspNetCore.SignalR;
 2
 3namespace Kestrun.SignalR;
 4
 5/// <summary>
 6/// Default SignalR hub for Kestrun providing real-time communication capabilities.
 7/// Clients can connect to this hub to receive log messages, events, and other real-time updates.
 8/// </summary>
 9/// <remarks>
 10/// Initializes a new instance of the <see cref="KestrunHub"/> class.
 11/// </remarks>
 12/// <param name="logger">The Serilog logger instance.</param>
 13/// <param name="tracker">The connection tracker for counting connected clients.</param>
 114public class KestrunHub(Serilog.ILogger logger, IConnectionTracker tracker) : Hub
 15{
 116    private readonly Serilog.ILogger _logger = logger;
 117    private readonly IConnectionTracker _tracker = tracker;
 18
 19    /// <summary>
 20    /// Called when a client connects to the hub.
 21    /// </summary>
 22    public override async Task OnConnectedAsync()
 23    {
 024        _logger.Information("SignalR client connected: {ConnectionId}", Context.ConnectionId);
 025        _tracker.OnConnected(Context.ConnectionId);
 026        await base.OnConnectedAsync();
 027    }
 28
 29    /// <summary>
 30    /// Called when a client disconnects from the hub.
 31    /// </summary>
 32    /// <param name="exception">The exception that caused the disconnection, if any.</param>
 33    public override async Task OnDisconnectedAsync(Exception? exception)
 34    {
 035        if (exception != null)
 36        {
 037            _logger.Warning(exception, "SignalR client disconnected with error: {ConnectionId}", Context.ConnectionId);
 38        }
 39        else
 40        {
 041            _logger.Information("SignalR client disconnected: {ConnectionId}", Context.ConnectionId);
 42        }
 043        _tracker.OnDisconnected(Context.ConnectionId);
 044        await base.OnDisconnectedAsync(exception);
 045    }
 46
 47    /// <summary>
 48    /// Allows a client to join a specific group.
 49    /// </summary>
 50    /// <param name="groupName">The name of the group to join.</param>
 51    public async Task JoinGroup(string groupName)
 52    {
 053        await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
 054        _logger.Information("Client {ConnectionId} joined group {GroupName}", Context.ConnectionId, groupName);
 55        // Notify caller so UI can update membership state
 056        await Clients.Caller.SendAsync("GroupJoined", groupName);
 057    }
 58
 59    /// <summary>
 60    /// Allows a client to leave a specific group.
 61    /// </summary>
 62    /// <param name="groupName">The name of the group to leave.</param>
 63    public async Task LeaveGroup(string groupName)
 64    {
 065        await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
 066        _logger.Information("Client {ConnectionId} left group {GroupName}", Context.ConnectionId, groupName);
 67        // Notify caller so UI can update membership state
 068        await Clients.Caller.SendAsync("GroupLeft", groupName);
 069    }
 70
 71    /// <summary>
 72    /// Echoes a message back to the caller (useful for testing).
 73    /// </summary>
 74    /// <param name="message">The message to echo.</param>
 075    public async Task Echo(string message) => await Clients.Caller.SendAsync("ReceiveEcho", message);
 76}