Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
<PackageVersion Include="Particular.LicensingComponent.Report" Version="1.0.0" />
<PackageVersion Include="Particular.Licensing.Sources" Version="6.1.0" />
<PackageVersion Include="Particular.Obsoletes" Version="1.0.0" />
<PackageVersion Include="Particular.ServicePulse.Core" Version="2.5.0-alpha.0.26" />
<PackageVersion Include="Polly.Core" Version="8.6.5" />
<PackageVersion Include="PropertyChanged.Fody" Version="4.1.0" />
<PackageVersion Include="PropertyChanging.Fody" Version="1.31.0" />
Expand Down Expand Up @@ -92,4 +93,4 @@
<GlobalPackageReference Include="Microsoft.Build.CopyOnWrite" Version="1.0.334" />
<GlobalPackageReference Include="Particular.Packaging" Version="4.5.0" />
</ItemGroup>
</Project>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Particular.LicensingComponent.Contracts;

/// <summary>
/// Provides environment data that is included in usage reports
/// </summary>
public interface IEnvironmentDataProvider
{
IEnumerable<(string key, string value)> GetData();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
namespace Particular.LicensingComponent.UnitTests;

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using NUnit.Framework;
using Particular.LicensingComponent.Contracts;
using Particular.LicensingComponent.UnitTests.Infrastructure;

[TestFixture]
class ThroughputCollector_AdditionalEnvironmentDataProvider_Tests : ThroughputCollectorTestFixture
{
public override Task Setup()
{
SetExtraDependencies = services => services.AddSingleton<IEnvironmentDataProvider, TestAdditionalEnvironmentDataProvider>();

return base.Setup();
}

[Test]
public async Task Should_include_additional_environment_data_in_throughput_report()
{
// Arrange
// Act
var report = await ThroughputCollector.GenerateThroughputReport(null, null, default);
// Assert
Assert.That(report, Is.Not.Null);
Assert.That(report.ReportData, Is.Not.Null);
Assert.That(report.ReportData.EnvironmentInformation, Is.Not.Null);
Assert.That(report.ReportData.EnvironmentInformation.EnvironmentData, Is.Not.Null);
Assert.That(report.ReportData.EnvironmentInformation.EnvironmentData.ContainsKey("TestKey"));
Assert.That(report.ReportData.EnvironmentInformation.EnvironmentData["TestKey"], Is.EqualTo("TestValue"));
}

class TestAdditionalEnvironmentDataProvider : IEnvironmentDataProvider
{
public IEnumerable<(string key, string value)> GetData()
{
yield return ("TestKey", "TestValue");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ await DataStore.CreateBuilder()
.WithThroughput(data: [60])
.Build();

var throughputCollector = new ThroughputCollector(DataStore, configuration.ThroughputSettings, configuration.AuditQuery, configuration.MonitoringService, new BrokerThroughputQuery_WithLowerCaseSanitizedNameCleanse());
var throughputCollector = new ThroughputCollector(DataStore, configuration.ThroughputSettings, configuration.AuditQuery, configuration.MonitoringService, [], new BrokerThroughputQuery_WithLowerCaseSanitizedNameCleanse());

// Act
var summary = await throughputCollector.GetThroughputSummary(default);
Expand All @@ -61,7 +61,7 @@ await DataStore.CreateBuilder()
.WithThroughput(data: [60])
.Build();

var throughputCollector = new ThroughputCollector(DataStore, configuration.ThroughputSettings, configuration.AuditQuery, configuration.MonitoringService, new BrokerThroughputQuery_WithLowerCaseSanitizedNameCleanse());
var throughputCollector = new ThroughputCollector(DataStore, configuration.ThroughputSettings, configuration.AuditQuery, configuration.MonitoringService, [], new BrokerThroughputQuery_WithLowerCaseSanitizedNameCleanse());

// Act
var report = await throughputCollector.GenerateThroughputReport(null, null, default);
Expand All @@ -88,7 +88,7 @@ await DataStore.CreateBuilder()
.WithThroughput(data: [60])
.Build();

var throughputCollector = new ThroughputCollector(DataStore, configuration.ThroughputSettings, configuration.AuditQuery, configuration.MonitoringService, new BrokerThroughputQuery_WithNoSanitizedNameCleanse());
var throughputCollector = new ThroughputCollector(DataStore, configuration.ThroughputSettings, configuration.AuditQuery, configuration.MonitoringService, [], new BrokerThroughputQuery_WithNoSanitizedNameCleanse());

// Act
var summary = await throughputCollector.GetThroughputSummary(default);
Expand All @@ -114,7 +114,7 @@ await DataStore.CreateBuilder()
.WithThroughput(data: [60])
.Build();

var throughputCollector = new ThroughputCollector(DataStore, configuration.ThroughputSettings, configuration.AuditQuery, configuration.MonitoringService, new BrokerThroughputQuery_WithNoSanitizedNameCleanse());
var throughputCollector = new ThroughputCollector(DataStore, configuration.ThroughputSettings, configuration.AuditQuery, configuration.MonitoringService, [], new BrokerThroughputQuery_WithNoSanitizedNameCleanse());

// Act
var report = await throughputCollector.GenerateThroughputReport(null, null, default);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Particular.LicensingComponent;

using Contracts;
using Microsoft.Extensions.DependencyInjection;

public static class LicensingComponentServiceCollectionExtensions
{
public static IServiceCollection AddEnvironmentDataProvider<T>(this IServiceCollection services)
where T : class, IEnvironmentDataProvider
=> services.AddSingleton<IEnvironmentDataProvider, T>();
}
10 changes: 9 additions & 1 deletion src/Particular.LicensingComponent/ThroughputCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
using Shared;
using QueueThroughput = Report.QueueThroughput;

public class ThroughputCollector(ILicensingDataStore dataStore, ThroughputSettings throughputSettings, IAuditQuery auditQuery, MonitoringService monitoringService, IBrokerThroughputQuery? throughputQuery = null)
public class ThroughputCollector(ILicensingDataStore dataStore, ThroughputSettings throughputSettings, IAuditQuery auditQuery, MonitoringService monitoringService, IEnumerable<IEnvironmentDataProvider> environmentDataProviders, IBrokerThroughputQuery? throughputQuery = null)
: IThroughputCollector
{
public async Task<ThroughputConnectionSettings> GetThroughputConnectionSettingsInformation(CancellationToken cancellationToken)
Expand Down Expand Up @@ -179,6 +179,14 @@ public async Task<SignedReport> GenerateThroughputReport(string spVersion, DateT
report.EnvironmentInformation.EnvironmentData[EnvironmentDataType.AuditEnabled.ToString()] = systemHasAuditEnabled.ToString();
report.EnvironmentInformation.EnvironmentData[EnvironmentDataType.MonitoringEnabled.ToString()] = systemHasMonitoringEnabled.ToString();

foreach (var environmentDataProvider in environmentDataProviders)
{
foreach (var (key, value) in environmentDataProvider.GetData())
{
report.EnvironmentInformation.EnvironmentData[key] = value;
}
}

var throughputReport = new SignedReport { ReportData = report, Signature = Signature.SignReport(report) };
return throughputReport;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,24 @@ public override async Task ExecuteAsync(InstanceDetailsViewModel model)
}
}

if (!instance.AppConfig.AppSettingExists(ServiceControlSettings.EnableIntegratedServicePulse.Name))
{
var result = await windowManager.ShowYesNoCancelDialog("INPUT REQUIRED - INTEGRATED SERVICEPULSE",
"ServiceControl can host an integrated version of ServicePulse which allows you to monitor your ServiceControl instance without needing to install ServicePulse separately.",
"Should an integrated ServicePulse be enabled for this ServiceControl instance?",
"Enable integrated ServicePulse",
"Do NOT enable integrated ServicePulse");

if (!result.HasValue)
{
//Dialog was cancelled
await eventAggregator.PublishOnUIThreadAsync(new RefreshInstances());
return;
}

upgradeOptions.EnableIntegratedServicePulse = result.Value;
}

if (await commandChecks.StopBecauseInstanceIsRunning(instance))
{
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace ServiceControl.Config.UI.InstanceAdd
{
public class EnableIntegratedServicePulseOption
{
public string Name { get; set; }
public bool Value { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ async Task Add()
serviceControlNewInstance.ServiceAccount = viewModel.ServiceControl.ServiceAccount;
serviceControlNewInstance.ServiceAccountPwd = viewModel.ServiceControl.Password;
serviceControlNewInstance.EnableFullTextSearchOnBodies = viewModel.ServiceControl.EnableFullTextSearchOnBodies.Value;
serviceControlNewInstance.EnableIntegratedServicePulse = viewModel.ServiceControl.EnableIntegratedServicePulse.Value;
}

var auditNewInstance = viewModel.InstallAuditInstance ? ServiceControlAuditNewInstance.CreateWithDefaultPersistence() : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@
Header="FULL TEXT SEARCH ON MESSAGE BODIES"
ItemsSource="{Binding ErrorEnableFullTextSearchOnBodiesOptions}"
SelectedValue="{Binding ErrorEnableFullTextSearchOnBodies}" />
<controls:FormComboBox HorizontalAlignment="Stretch"
VerticalAlignment="Top"
DisplayMemberPath="Name"
Header="ENABLE INTEGRATED SERVICEPULSE"
ItemsSource="{Binding ErrorEnableIntegratedServicePulseOptions}"
SelectedValue="{Binding ErrorEnableIntegratedServicePulse}" />
</StackPanel>
</Expander>
</Grid>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,15 @@ public EnableFullTextSearchOnBodiesOption ErrorEnableFullTextSearchOnBodies
set => ServiceControl.EnableFullTextSearchOnBodies = value;
}

public IEnumerable<EnableIntegratedServicePulseOption> ErrorEnableIntegratedServicePulseOptions =>
ServiceControl.EnableIntegratedServicePulseOptions;

public EnableIntegratedServicePulseOption ErrorEnableIntegratedServicePulse
{
get => ServiceControl.EnableIntegratedServicePulse;
set => ServiceControl.EnableIntegratedServicePulse = value;
}

/* Add Audit Instance */

public string AuditInstanceName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ public ServiceControlInformation(ServiceControlEditorViewModel viewModelParent)
Value = false
}
};
EnableIntegratedServicePulseOptions = new[]
{
new EnableIntegratedServicePulseOption
{
Name = "On",
Value = true
},
new EnableIntegratedServicePulseOption
{
Name = "Off",
Value = false
}
};
ErrorRetention = SettingConstants.ErrorRetentionPeriodDefaultInDaysForUI;
Description = "ServiceControl Service";
HostName = "localhost";
Expand All @@ -48,6 +61,7 @@ public ServiceControlInformation(ServiceControlEditorViewModel viewModelParent)
PortNumber = "33333";
DatabaseMaintenancePortNumber = "33334";
EnableFullTextSearchOnBodies = EnableFullTextSearchOnBodiesOptions.First(p => p.Value); //Default to On.
EnableIntegratedServicePulse = EnableIntegratedServicePulseOptions.First(p => p.Value); //Default to On.
ViewModelParent = viewModelParent;
}

Expand Down Expand Up @@ -92,6 +106,10 @@ public ForwardingOption ErrorForwarding

public EnableFullTextSearchOnBodiesOption EnableFullTextSearchOnBodies { get; set; }

public IEnumerable<EnableIntegratedServicePulseOption> EnableIntegratedServicePulseOptions { get; }

public EnableIntegratedServicePulseOption EnableIntegratedServicePulse { get; set; }

protected void UpdateErrorRetention(TimeSpan value)
{
ErrorRetention = ErrorRetentionUnits == TimeSpanUnits.Days ? value.TotalDays : value.TotalHours;
Expand Down Expand Up @@ -122,6 +140,7 @@ public void UpdateFromInstance(ServiceControlInstance instance)
ErrorForwardingQueueName = instance.ErrorLogQueue;
UpdateErrorRetention(instance.ErrorRetentionPeriod);
EnableFullTextSearchOnBodies = EnableFullTextSearchOnBodiesOptions.FirstOrDefault(p => p.Value == instance.EnableFullTextSearchOnBodies);
EnableIntegratedServicePulse = EnableIntegratedServicePulseOptions.FirstOrDefault(p => p.Value == instance.EnableIntegratedServicePulse);
}

ForwardingOption errorForwarding;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
<GroupBox Grid.Row="4"
Grid.Column="1"
Visibility="{Binding HasBrowsableUrl, Converter={StaticResource boolToVis}}"
Header="URL"
Header="{Binding UrlHeading}"
HeaderTemplate="{StaticResource SimpleHeaderedGroupBox}">
<Hyperlink Command="{Binding OpenUrl}" CommandParameter="{Binding BrowsableUrl}">
<Hyperlink.ContextMenu>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,22 @@ public string BrowsableUrl

public bool HasBrowsableUrl => ServiceInstance is IURLInfo;

public string UrlHeading
{
get
{
if (IsServiceControlInstance)
{
if (ServiceControlInstance.EnableIntegratedServicePulse)
{
return "SERVICEPULSE";
}
}

return "URL";
}
}

public string InstallPath => ((IServicePaths)ServiceInstance).InstallPath;

public string DBPath => GetDBPathIfAvailable();
Expand Down Expand Up @@ -291,6 +307,7 @@ public Task HandleAsync(PostRefreshInstances message, CancellationToken cancella
NotifyOfPropertyChange("HasNewVersion");
NotifyOfPropertyChange("Transport");
NotifyOfPropertyChange("BrowsableUrl");
NotifyOfPropertyChange("UrlHeading");
return Task.CompletedTask;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ async Task Save()
instance.DatabaseMaintenancePort = !string.IsNullOrWhiteSpace(viewModel.ServiceControl.DatabaseMaintenancePortNumber) ? Convert.ToInt32(viewModel.ServiceControl.DatabaseMaintenancePortNumber) : null;
instance.VirtualDirectory = null;
instance.ForwardErrorMessages = viewModel.ServiceControl.ErrorForwarding.Value;
instance.EnableIntegratedServicePulse = viewModel.ServiceControl.EnableIntegratedServicePulse.Value;
instance.ErrorQueue = viewModel.ServiceControl.ErrorQueueName;
instance.ErrorLogQueue = viewModel.ServiceControl.ErrorForwardingQueueName;
instance.ErrorRetentionPeriod = viewModel.ServiceControl.ErrorRetentionPeriod;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,12 @@
Header="FULL TEXT SEARCH ON MESSAGE BODIES"
ItemsSource="{Binding EnableFullTextSearchOnBodiesOptions}"
SelectedValue="{Binding EnableFullTextSearchOnBodies}" />
<controls:FormComboBox HorizontalAlignment="Stretch"
VerticalAlignment="Top"
DisplayMemberPath="Name"
Header="ENABLE INTEGRATED SERVICEPULSE"
ItemsSource="{Binding EnableIntegratedServicePulseOptions}"
SelectedValue="{Binding EnableIntegratedServicePulse}" />
</StackPanel>
</sie:SharedServiceControlEditorView.SharedContent>
</sie:SharedServiceControlEditorView>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public void UpdateInstanceFromViewModel(ServiceControlInstance instance)
instance.ConnectionString = ConnectionString;
instance.DatabaseMaintenancePort = Convert.ToInt32(ServiceControl.DatabaseMaintenancePortNumber);
instance.EnableFullTextSearchOnBodies = ServiceControl.EnableFullTextSearchOnBodies.Value;
instance.EnableIntegratedServicePulse = ServiceControl.EnableIntegratedServicePulse.Value;
}

public string InstanceName => ServiceControl.InstanceName;
Expand Down Expand Up @@ -189,6 +190,15 @@ public EnableFullTextSearchOnBodiesOption EnableFullTextSearchOnBodies
set => ServiceControl.EnableFullTextSearchOnBodies = value;
}

public IEnumerable<EnableIntegratedServicePulseOption> EnableIntegratedServicePulseOptions =>
ServiceControl.EnableIntegratedServicePulseOptions;

public EnableIntegratedServicePulseOption EnableIntegratedServicePulse
{
get => ServiceControl.EnableIntegratedServicePulse;
set => ServiceControl.EnableIntegratedServicePulse = value;
}

public bool SubmitAttempted { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ public class NewServiceControlInstance : PSCmdlet
[Parameter(Mandatory = false, HelpMessage = "Specify whether to enable full text search on error messages.")]
public SwitchParameter EnableFullTextSearchOnBodies { get; set; } = true;

[Parameter(Mandatory = false, HelpMessage = "Specify whether to enable integrated ServicePulse instance.")]
public SwitchParameter EnableIntegratedServicePulse { get; set; }

[Parameter(Mandatory = false, HelpMessage = "Reuse the specified log, db, and install paths even if they are not empty")]
public SwitchParameter Force { get; set; }

Expand Down Expand Up @@ -172,6 +175,7 @@ protected override void ProcessRecord()
details.TransportPackage = ServiceControlCoreTransports.Find(Transport);
details.SkipQueueCreation = SkipQueueCreation;
details.EnableFullTextSearchOnBodies = EnableFullTextSearchOnBodies;
details.EnableIntegratedServicePulse = EnableIntegratedServicePulse;

var modulePath = Path.GetDirectoryName(MyInvocation.MyCommand.Module.Path);

Expand Down
Loading
Loading