diff --git a/src/Umbraco.Core/Constants-Telemetry.cs b/src/Umbraco.Core/Constants-Telemetry.cs index 0fc2cb1612..f8a382b0bb 100644 --- a/src/Umbraco.Core/Constants-Telemetry.cs +++ b/src/Umbraco.Core/Constants-Telemetry.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Cms.Core; +namespace Umbraco.Cms.Core; public static partial class Constants { @@ -28,5 +28,6 @@ public static partial class Constants public static string IsDebug = "IsDebug"; public static string DatabaseProvider = "DatabaseProvider"; public static string CurrentServerRole = "CurrentServerRole"; + public static string RuntimeMode = "RuntimeMode"; } } diff --git a/src/Umbraco.Infrastructure/Telemetry/Providers/SystemInformationTelemetryProvider.cs b/src/Umbraco.Infrastructure/Telemetry/Providers/SystemInformationTelemetryProvider.cs index 0a5881528e..4847b4cc25 100644 --- a/src/Umbraco.Infrastructure/Telemetry/Providers/SystemInformationTelemetryProvider.cs +++ b/src/Umbraco.Infrastructure/Telemetry/Providers/SystemInformationTelemetryProvider.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; using System.Runtime.InteropServices; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; @@ -23,6 +23,7 @@ internal class SystemInformationTelemetryProvider : IDetailedTelemetryProvider, private readonly IUmbracoDatabaseFactory _umbracoDatabaseFactory; private readonly IUmbracoVersion _version; private readonly IServerRoleAccessor _serverRoleAccessor; + private readonly RuntimeSettings _runtimeSettings; [Obsolete($"Use the constructor that does not take an IOptionsMonitor parameter, scheduled for removal in V12")] public SystemInformationTelemetryProvider( @@ -33,8 +34,9 @@ internal class SystemInformationTelemetryProvider : IDetailedTelemetryProvider, IOptionsMonitor globalSettings, IHostEnvironment hostEnvironment, IUmbracoDatabaseFactory umbracoDatabaseFactory, - IServerRoleAccessor serverRoleAccessor) - : this(version, localizationService, modelsBuilderSettings, hostingSettings, hostEnvironment, umbracoDatabaseFactory, serverRoleAccessor) + IServerRoleAccessor serverRoleAccessor, + IOptionsMonitor runtimeSettings) + : this(version, localizationService, modelsBuilderSettings, hostingSettings, hostEnvironment, umbracoDatabaseFactory, serverRoleAccessor, runtimeSettings) { } @@ -45,24 +47,27 @@ internal class SystemInformationTelemetryProvider : IDetailedTelemetryProvider, IOptionsMonitor hostingSettings, IHostEnvironment hostEnvironment, IUmbracoDatabaseFactory umbracoDatabaseFactory, - IServerRoleAccessor serverRoleAccessor) + IServerRoleAccessor serverRoleAccessor, + IOptionsMonitor runtimeSettings) { _version = version; _localizationService = localizationService; _hostEnvironment = hostEnvironment; _umbracoDatabaseFactory = umbracoDatabaseFactory; _serverRoleAccessor = serverRoleAccessor; - + _runtimeSettings = runtimeSettings.CurrentValue; _hostingSettings = hostingSettings.CurrentValue; _modelsBuilderSettings = modelsBuilderSettings.CurrentValue; } - private string CurrentWebServer => IsRunningInProcessIIS() ? "IIS" : "Kestrel"; + private string CurrentWebServer => GetWebServerName(); private string ServerFramework => RuntimeInformation.FrameworkDescription; private string ModelsBuilderMode => _modelsBuilderSettings.ModelsMode.ToString(); + private string RuntimeMode => _runtimeSettings.Mode.ToString(); + private string CurrentCulture => Thread.CurrentThread.CurrentCulture.ToString(); private bool IsDebug => _hostingSettings.Debug; @@ -82,6 +87,7 @@ internal class SystemInformationTelemetryProvider : IDetailedTelemetryProvider, new(Constants.Telemetry.OsLanguage, CurrentCulture), new(Constants.Telemetry.WebServer, CurrentWebServer), new(Constants.Telemetry.ModelsBuilderMode, ModelsBuilderMode), + new(Constants.Telemetry.RuntimeMode, RuntimeMode), new(Constants.Telemetry.AspEnvironment, AspEnvironment), new(Constants.Telemetry.IsDebug, IsDebug), new(Constants.Telemetry.DatabaseProvider, DatabaseProvider), new(Constants.Telemetry.CurrentServerRole, CurrentServerRole), @@ -95,19 +101,28 @@ internal class SystemInformationTelemetryProvider : IDetailedTelemetryProvider, new("Umbraco Version", _version.SemanticVersion.ToSemanticStringWithoutBuild()), new("Current Culture", CurrentCulture), new("Current UI Culture", Thread.CurrentThread.CurrentUICulture.ToString()), - new("Current Webserver", CurrentWebServer), new("Models Builder Mode", ModelsBuilderMode), - new("Debug Mode", IsDebug.ToString()), new("Database Provider", DatabaseProvider), + new("Current Webserver", CurrentWebServer), + new("Models Builder Mode", ModelsBuilderMode), + new("Runtime Mode", RuntimeMode), + new("Debug Mode", IsDebug.ToString()), + new("Database Provider", DatabaseProvider), new("Current Server Role", CurrentServerRole), }; - private bool IsRunningInProcessIIS() + private string GetWebServerName() { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + var processName = Path.GetFileNameWithoutExtension(Process.GetCurrentProcess().ProcessName); + + if (processName.Contains("w3wp")) { - return false; + return "IIS"; } - var processName = Path.GetFileNameWithoutExtension(Process.GetCurrentProcess().ProcessName); - return processName.Contains("w3wp") || processName.Contains("iisexpress"); + if (processName.Contains("iisexpress")) + { + return "IIS Express"; + } + + return "Kestrel"; } } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Telemetry/TelemetryServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Telemetry/TelemetryServiceTests.cs index 2acb31a5a0..bc4b68b508 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Telemetry/TelemetryServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Telemetry/TelemetryServiceTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; @@ -49,7 +49,8 @@ public class TelemetryServiceTests : UmbracoIntegrationTest Constants.Telemetry.AspEnvironment, Constants.Telemetry.IsDebug, Constants.Telemetry.DatabaseProvider, - Constants.Telemetry.CurrentServerRole + Constants.Telemetry.CurrentServerRole, + Constants.Telemetry.RuntimeMode, }; MetricsConsentService.SetConsentLevel(TelemetryLevel.Detailed); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Services/UserDataServiceTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Services/UserDataServiceTests.cs index a33d9a3680..67ba80a570 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Services/UserDataServiceTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Services/UserDataServiceTests.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading; @@ -108,6 +108,20 @@ public class UserDataServiceTests Assert.AreEqual(modelsMode.ToString(), actual.Data); } + [Test] + [TestCase(RuntimeMode.BackofficeDevelopment)] + [TestCase(RuntimeMode.Development)] + [TestCase(RuntimeMode.Production)] + public void ReportsRuntimeModeCorrectly(RuntimeMode runtimeMode) + { + var userDataService = CreateUserDataService(runtimeMode: runtimeMode); + var userData = userDataService.GetUserData().ToArray(); + + var actual = userData.FirstOrDefault(x => x.Name == "Runtime Mode"); + Assert.IsNotNull(actual?.Data); + Assert.AreEqual(runtimeMode.ToString(), actual.Data); + } + [Test] [TestCase(true)] [TestCase(false)] @@ -124,7 +138,8 @@ public class UserDataServiceTests private SystemInformationTelemetryProvider CreateUserDataService( string culture = "", ModelsMode modelsMode = ModelsMode.InMemoryAuto, - bool isDebug = true) + bool isDebug = true, + RuntimeMode runtimeMode = RuntimeMode.BackofficeDevelopment) { var localizationService = CreateILocalizationService(culture); @@ -138,7 +153,8 @@ public class UserDataServiceTests Mock.Of>(x => x.CurrentValue == new HostingSettings { Debug = isDebug }), Mock.Of(), Mock.Of(x => x.CreateDatabase() == Mock.Of(y => y.DatabaseType == DatabaseType.SQLite)), - Mock.Of()); + Mock.Of(), + Mock.Of>(x => x.CurrentValue == new RuntimeSettings { Mode = runtimeMode })); } private ILocalizationService CreateILocalizationService(string culture) diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Telemetry/SystemInformationTelemetryProviderTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Telemetry/SystemInformationTelemetryProviderTests.cs index fbad15e560..63c7f6a1df 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Telemetry/SystemInformationTelemetryProviderTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Telemetry/SystemInformationTelemetryProviderTests.cs @@ -1,4 +1,4 @@ -using System.Globalization; +using System.Globalization; using System.Linq; using System.Threading; using Microsoft.Extensions.Hosting; @@ -34,6 +34,21 @@ public class SystemInformationTelemetryProviderTests Assert.AreEqual(modelsMode.ToString(), actual.Data); } + [Test] + [TestCase(RuntimeMode.BackofficeDevelopment)] + [TestCase(RuntimeMode.BackofficeDevelopment)] + [TestCase(RuntimeMode.BackofficeDevelopment)] + + public void ReportsRuntimeModeCorrectly(RuntimeMode runtimeMode) + { + var telemetryProvider = CreateProvider(runtimeMode: runtimeMode); + var usageInformation = telemetryProvider.GetInformation().ToArray(); + + var actual = usageInformation.FirstOrDefault(x => x.Name == Constants.Telemetry.RuntimeMode); + Assert.IsNotNull(actual?.Data); + Assert.AreEqual(runtimeMode.ToString(), actual.Data); + } + [Test] [TestCase(true)] [TestCase(false)] @@ -82,7 +97,8 @@ public class SystemInformationTelemetryProviderTests private SystemInformationTelemetryProvider CreateProvider( ModelsMode modelsMode = ModelsMode.InMemoryAuto, bool isDebug = true, - string environment = "") + string environment = "", + RuntimeMode runtimeMode = RuntimeMode.BackofficeDevelopment) { var hostEnvironment = new Mock(); hostEnvironment.Setup(x => x.EnvironmentName).Returns(environment); @@ -93,10 +109,11 @@ public class SystemInformationTelemetryProviderTests return new SystemInformationTelemetryProvider( Mock.Of(), Mock.Of(), - Mock.Of>(x => x.CurrentValue == new ModelsBuilderSettings{ ModelsMode = modelsMode }), + Mock.Of>(x => x.CurrentValue == new ModelsBuilderSettings { ModelsMode = modelsMode }), Mock.Of>(x => x.CurrentValue == new HostingSettings { Debug = isDebug }), hostEnvironment.Object, Mock.Of(x => x.CreateDatabase() == Mock.Of(y => y.DatabaseType == DatabaseType.SQLite)), - Mock.Of()); + Mock.Of(), + Mock.Of>(x => x.CurrentValue == new RuntimeSettings { Mode = runtimeMode })); } }