diff --git a/BililiveRecorder.Core/Event/IOStatsEventArgs.cs b/BililiveRecorder.Core/Event/IOStatsEventArgs.cs index 40b08ef..e408c94 100644 --- a/BililiveRecorder.Core/Event/IOStatsEventArgs.cs +++ b/BililiveRecorder.Core/Event/IOStatsEventArgs.cs @@ -4,6 +4,11 @@ namespace BililiveRecorder.Core.Event { public sealed class IOStatsEventArgs : EventArgs { + /// + /// 直播服务器域名 + /// + public string? StreamHost { get; set; } + /// /// 当前统计区间的开始时间 /// diff --git a/BililiveRecorder.Core/Recording/RecordTaskBase.cs b/BililiveRecorder.Core/Recording/RecordTaskBase.cs index 16b444e..dd856ff 100644 --- a/BililiveRecorder.Core/Recording/RecordTaskBase.cs +++ b/BililiveRecorder.Core/Recording/RecordTaskBase.cs @@ -157,6 +157,7 @@ namespace BililiveRecorder.Core.Recording this.OnIOStats(new IOStatsEventArgs { + StreamHost = streamHost, NetworkBytesDownloaded = networkDownloadBytes, Duration = durationDiff, StartTime = startTime, diff --git a/BililiveRecorder.Core/Room.cs b/BililiveRecorder.Core/Room.cs index 00b6d1a..9e23c01 100644 --- a/BililiveRecorder.Core/Room.cs +++ b/BililiveRecorder.Core/Room.cs @@ -353,6 +353,7 @@ namespace BililiveRecorder.Core { this.logger.Verbose("IO stats: {@stats}", e); + this.Stats.StreamHost = e.StreamHost; this.Stats.StartTime = e.StartTime; this.Stats.EndTime = e.EndTime; this.Stats.Duration = e.Duration; diff --git a/BililiveRecorder.Core/RoomStats.cs b/BililiveRecorder.Core/RoomStats.cs index 0a79ad6..cea8cb1 100644 --- a/BililiveRecorder.Core/RoomStats.cs +++ b/BililiveRecorder.Core/RoomStats.cs @@ -9,6 +9,7 @@ namespace BililiveRecorder.Core public class RoomStats : INotifyPropertyChanged { #region IO Stats Fields + private string? ___StreamHost; private DateTimeOffset ___StartTime; private DateTimeOffset ___EndTime; private TimeSpan ___Duration; @@ -54,6 +55,11 @@ namespace BililiveRecorder.Core #region IO Stats Properties + /// + /// 直播服务器域名 + /// + public string? StreamHost { get => this.___StreamHost; set => this.SetField(ref this.___StreamHost, value); } + /// /// 当前统计区间的开始时间 /// @@ -207,6 +213,8 @@ namespace BililiveRecorder.Core // ------------------------------ + this.StreamHost = null; + this.StartTime = default; this.EndTime = default; this.Duration = default; diff --git a/BililiveRecorder.WPF/App.xaml b/BililiveRecorder.WPF/App.xaml index aa595f9..1cb446b 100644 --- a/BililiveRecorder.WPF/App.xaml +++ b/BililiveRecorder.WPF/App.xaml @@ -33,6 +33,7 @@ + diff --git a/BililiveRecorder.WPF/Controls/RoomCard.xaml b/BililiveRecorder.WPF/Controls/RoomCard.xaml index 81dd831..cfe32a9 100644 --- a/BililiveRecorder.WPF/Controls/RoomCard.xaml +++ b/BililiveRecorder.WPF/Controls/RoomCard.xaml @@ -11,7 +11,7 @@ l:ResxLocalizationProvider.DefaultDictionary="Strings" xmlns:local="clr-namespace:BililiveRecorder.WPF.Controls" xmlns:core="clr-namespace:BililiveRecorder.Core;assembly=BililiveRecorder.Core" - d:DataContext="{d:DesignInstance core:Room}" + d:DataContext="{d:DesignInstance core:IRoom}" d:DesignWidth="220" d:DesignHeight="110" mc:Ignorable="d"> - /// 读取直播间统计信息 + /// 读取直播间录制统计信息 /// /// /// [HttpGet("{roomId:int}/stats")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(RestApiError), StatusCodes.Status404NotFound)] - public ActionResult GetRoomStats(int roomId) + public ActionResult GetRoomRecordingStats(int roomId) { var room = this.FetchRoom(roomId); if (room is null) @@ -161,14 +161,14 @@ namespace BililiveRecorder.Web.Api } /// - /// 读取直播间统计信息 + /// 读取直播间录制统计信息 /// /// /// [HttpGet("{objectId:guid}/stats")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(RestApiError), StatusCodes.Status404NotFound)] - public ActionResult GetRoomStats(Guid objectId) + public ActionResult GetRoomRecordingStats(Guid objectId) { var room = this.FetchRoom(objectId); if (room is null) @@ -176,6 +176,38 @@ namespace BililiveRecorder.Web.Api return this.mapper.Map(room.Stats); } + /// + /// 读取直播间 IO 统计信息 + /// + /// + /// + [HttpGet("{roomId:int}/ioStats")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(RestApiError), StatusCodes.Status404NotFound)] + public ActionResult GetRoomIOStats(int roomId) + { + var room = this.FetchRoom(roomId); + if (room is null) + return this.NotFound(new RestApiError { Code = RestApiErrorCode.RoomNotFound, Message = "Room not found" }); + return this.mapper.Map(room.Stats); + } + + /// + /// 读取直播间 IO 统计信息 + /// + /// + /// + [HttpGet("{objectId:guid}/ioStats")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(RestApiError), StatusCodes.Status404NotFound)] + public ActionResult GetRoomIOStats(Guid objectId) + { + var room = this.FetchRoom(objectId); + if (room is null) + return this.NotFound(new RestApiError { Code = RestApiErrorCode.RoomNotFound, Message = "Room not found" }); + return this.mapper.Map(room.Stats); + } + #endregion #region Room Config diff --git a/BililiveRecorder.Web/Models/Graphql/IOStatsType.cs b/BililiveRecorder.Web/Models/Graphql/IOStatsType.cs index 7453883..029a7ca 100644 --- a/BililiveRecorder.Web/Models/Graphql/IOStatsType.cs +++ b/BililiveRecorder.Web/Models/Graphql/IOStatsType.cs @@ -7,6 +7,7 @@ namespace BililiveRecorder.Web.Models.Graphql { public IOStatsType() { + this.Field(x => x.StreamHost, nullable: true); this.Field(x => x.StartTime); this.Field(x => x.EndTime); this.Field(x => x.Duration, type: typeof(TimeSpanMillisecondsGraphType)); diff --git a/BililiveRecorder.Web/Models/Rest/RoomIOStatsDto.cs b/BililiveRecorder.Web/Models/Rest/RoomIOStatsDto.cs index 32f194a..5c7e64d 100644 --- a/BililiveRecorder.Web/Models/Rest/RoomIOStatsDto.cs +++ b/BililiveRecorder.Web/Models/Rest/RoomIOStatsDto.cs @@ -4,6 +4,11 @@ namespace BililiveRecorder.Web.Models.Rest { public class RoomIOStatsDto { + /// + /// 直播服务器域名 + /// + public string? StreamHost { get; set; } + /// /// 当前统计区间的开始时间 ///