diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 6add7e0b39..35bc25d579 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -25,6 +25,7 @@ using Emby.Server.Implementations.HttpServer.Security; using Emby.Server.Implementations.IO; using Emby.Server.Implementations.Library; using Emby.Server.Implementations.Localization; +using Emby.Server.Implementations.Metrics; using Emby.Server.Implementations.Playlists; using Emby.Server.Implementations.Plugins; using Emby.Server.Implementations.QuickConnect; @@ -59,6 +60,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Controller.Metrics; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Playlists; @@ -419,12 +421,6 @@ namespace Emby.Server.Implementations NetManager = new NetworkManager(ConfigurationManager, _startupConfig, LoggerFactory.CreateLogger()); - // Initialize runtime stat collection - if (ConfigurationManager.Configuration.EnableMetrics) - { - DotNetRuntimeStatsBuilder.Default().StartCollecting(); - } - var networkConfiguration = ConfigurationManager.GetNetworkConfiguration(); HttpPort = networkConfiguration.InternalHttpPort; HttpsPort = networkConfiguration.InternalHttpsPort; @@ -552,6 +548,7 @@ namespace Emby.Server.Implementations serviceCollection.AddScoped(); serviceCollection.AddScoped(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); } /// @@ -579,6 +576,16 @@ namespace Emby.Server.Implementations SetStaticProperties(); + + var userDataRepo = (SqliteUserDataRepository)Resolve(); + ((SqliteItemRepository)Resolve()).Initialize(userDataRepo, Resolve()); + + // Initialize runtime stat collection + if (ConfigurationManager.Configuration.EnableMetrics) + { + Resolve().Initialize(); + } + FindParts(); } diff --git a/Emby.Server.Implementations/Metrics/PrometheusMetricsCollector.cs b/Emby.Server.Implementations/Metrics/PrometheusMetricsCollector.cs new file mode 100644 index 0000000000..30b3b27cea --- /dev/null +++ b/Emby.Server.Implementations/Metrics/PrometheusMetricsCollector.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Metrics; +using Prometheus; +using Prometheus.DotNetRuntime; + +namespace Emby.Server.Implementations.Metrics +{ + /// + /// Prometheus backend for metrics. + /// + public class PrometheusMetricsCollector : IMetricsCollector + { + private readonly ILibraryManager _libraryManager; + + private static readonly Gauge _itemCountGauge = Prometheus.Metrics.CreateGauge("jellyfin_library_items_total", "The number of items in the library", new[] { "item_type" }); + private static readonly string[] _metricTypes = new string[] + { + nameof(Movie), + nameof(Series), nameof(Season), nameof(Episode), + nameof(MusicArtist), nameof(MusicAlbum), nameof(MusicVideo), nameof(Audio), + nameof(Book), + nameof(PhotoAlbum), nameof(Photo) + }; + + /// + /// Initializes a new instance of the class. + /// + /// The library manager. + public PrometheusMetricsCollector(ILibraryManager libraryManager) + { + _libraryManager = libraryManager; + _libraryManager.ItemAdded += IncrementItemCount; + _libraryManager.ItemRemoved += (s, e) => UpdateItemCount(); + } + + /// + public void Initialize() + { + DotNetRuntimeStatsBuilder.Default().StartCollecting(); + UpdateItemCount(); + } + + private void UpdateItemCount() + { + foreach (var type in _metricTypes) + { + BaseItemKind item; + Enum.TryParse(type, out item); + var query = new InternalItemsQuery + { + IncludeItemTypes = new[] { item } + }; + int count = _libraryManager.GetCount(query); + _itemCountGauge.WithLabels(type).Set(count); + } + } + + private void IncrementItemCount(object? sender, ItemChangeEventArgs e) + { + var item = e.Item; + var typeName = item.GetType().Name; + if (_metricTypes.Contains(typeName)) + { + _itemCountGauge.WithLabels(typeName).Inc(); + } + } + } +} diff --git a/MediaBrowser.Controller/Metrics/IMetricsCollector.cs b/MediaBrowser.Controller/Metrics/IMetricsCollector.cs new file mode 100644 index 0000000000..86d2a6dd44 --- /dev/null +++ b/MediaBrowser.Controller/Metrics/IMetricsCollector.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Metrics +{ + /// + /// Interface for metric backends. + /// + public interface IMetricsCollector + { + /// + /// Initializes metrics. + /// + public void Initialize(); + } +}