diff --git a/MediaBrowser.Common.Implementations/Security/UsageReporter.cs b/MediaBrowser.Common.Implementations/Security/UsageReporter.cs index e32940be9b..7c8127db31 100644 --- a/MediaBrowser.Common.Implementations/Security/UsageReporter.cs +++ b/MediaBrowser.Common.Implementations/Security/UsageReporter.cs @@ -19,7 +19,7 @@ namespace MediaBrowser.Common.Implementations.Security _httpClient = httpClient; } - public Task ReportUsage(CancellationToken cancellationToken) + public Task ReportServerUsage(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -36,5 +36,20 @@ namespace MediaBrowser.Common.Implementations.Security return _httpClient.Post(Constants.Constants.MbAdminUrl + "service/registration/ping", data, cancellationToken); } + + public Task ReportAppUsage(ClientInfo app, CancellationToken cancellationToken) + { + // TODO: Implement this + // Make sure to handle DeviceVersion being + + return Task.FromResult(true); + } + } + + public class ClientInfo + { + public string AppName { get; set; } + public string AppVersion { get; set; } + public string DeviceVersion { get; set; } } } diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index bc0f8a5d16..d8052b9bf6 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -86,6 +86,12 @@ namespace MediaBrowser.Controller.Session /// The name of the device. public string DeviceName { get; set; } + /// + /// Gets or sets the device version. + /// + /// The device version. + public string DeviceVersion { get; set; } + /// /// Gets or sets the name of the now viewing item. /// diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs index 3ab47f51b9..5f5d5d9012 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs @@ -1,9 +1,13 @@ using MediaBrowser.Common; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Implementations.Security; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Plugins; +using MediaBrowser.Controller.Session; using MediaBrowser.Model.Logging; using System; +using System.Collections.Concurrent; +using System.Collections.Generic; using System.Threading; namespace MediaBrowser.Server.Implementations.EntryPoints @@ -17,16 +21,88 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private readonly INetworkManager _networkManager; private readonly IHttpClient _httpClient; private readonly ILogger _logger; + private readonly ISessionManager _sessionManager; private Timer _timer; private readonly TimeSpan _frequency = TimeSpan.FromHours(24); - public UsageEntryPoint(ILogger logger, IApplicationHost applicationHost, INetworkManager networkManager, IHttpClient httpClient) + private const string DefaultDeviceVersion = "Unknown version"; + private readonly ConcurrentDictionary _apps = new ConcurrentDictionary(); + + public UsageEntryPoint(ILogger logger, IApplicationHost applicationHost, INetworkManager networkManager, IHttpClient httpClient, ISessionManager sessionManager) { _logger = logger; _applicationHost = applicationHost; _networkManager = networkManager; _httpClient = httpClient; + _sessionManager = sessionManager; + + _sessionManager.SessionStarted += _sessionManager_SessionStarted; + } + + void _sessionManager_SessionStarted(object sender, SessionEventArgs e) + { + var session = e.SessionInfo; + + if (!string.IsNullOrEmpty(session.Client) && + !string.IsNullOrEmpty(session.DeviceName)) + { + var keys = new List + { + session.Client, + session.DeviceName + }; + + if (!string.IsNullOrEmpty(session.DeviceVersion)) + { + keys.Add(session.DeviceVersion); + } + else + { + keys.Add(DefaultDeviceVersion); + } + + var key = string.Join("_", keys.ToArray()).GetMD5(); + + _apps.GetOrAdd(key, guid => GetNewClientInfo(session)); + } + } + + private async void ReportNewSession(ClientInfo client) + { + try + { + await new UsageReporter(_applicationHost, _networkManager, _httpClient) + .ReportAppUsage(client, CancellationToken.None) + .ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error sending anonymous usage statistics.", ex); + } + } + + private ClientInfo GetNewClientInfo(SessionInfo session) + { + var info = new ClientInfo + { + AppName = session.Client, + AppVersion = session.ApplicationVersion, + DeviceVersion = session.DeviceVersion + }; + + if (string.IsNullOrEmpty(info.DeviceVersion)) + { + info.DeviceVersion = DefaultDeviceVersion; + } + + // Report usage to remote server, except for web client, since we already have data on that + if (!string.Equals(info.AppName, "Dashboard", StringComparison.OrdinalIgnoreCase)) + { + ReportNewSession(info); + } + + return info; } public void Run() @@ -42,8 +118,9 @@ namespace MediaBrowser.Server.Implementations.EntryPoints { try { - await new UsageReporter(_applicationHost, _networkManager, _httpClient).ReportUsage(CancellationToken.None) - .ConfigureAwait(false); + await new UsageReporter(_applicationHost, _networkManager, _httpClient) + .ReportServerUsage(CancellationToken.None) + .ConfigureAwait(false); } catch (Exception ex) { @@ -53,6 +130,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints public void Dispose() { + _sessionManager.SessionStarted -= _sessionManager_SessionStarted; + if (_timer != null) { _timer.Dispose(); diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 290029b41e..efc7ebb6ad 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -48,9 +48,9 @@ ..\packages\Alchemy.2.2.1\lib\net40\Alchemy.dll - + False - ..\packages\Mono.Nat.1.2.10.0\lib\net40\Mono.Nat.dll + ..\packages\Mono.Nat.1.2.13.0\lib\net40\Mono.Nat.dll ..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index d2ee5161db..fb04de92f3 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -1,7 +1,7 @@  - + \ No newline at end of file