Skip to content

Commit eb91787

Browse files
authored
Merge pull request #730 from fossa-app/license-metrics
Record system license metrics
2 parents c3fbaf1 + 2445f06 commit eb91787

5 files changed

Lines changed: 84 additions & 2 deletions

File tree

src/API.Core/DefaultCoreModule.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Fossa.API.Core.Entities;
33
using Fossa.API.Core.Relationship;
44
using Fossa.API.Core.Services;
5+
using Fossa.API.Core.Telemetry;
56
using Fossa.API.Core.TimeZone;
67
using TIKSN.Data.BareEntityResolvers;
78
using TIKSN.Identity;
@@ -51,6 +52,11 @@ protected override void Load(ContainerBuilder builder)
5152
.AsImplementedInterfaces()
5253
.InstancePerLifetimeScope();
5354

55+
builder
56+
.RegisterType<SystemLicenseMetricsRecorder>()
57+
.AsImplementedInterfaces()
58+
.SingleInstance();
59+
5460
builder
5561
.RegisterType<CompanyLicenseCreator>()
5662
.AsImplementedInterfaces()

src/API.Core/Services/SystemLicenseRetriever.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Fossa.API.Core.Repositories;
2+
using Fossa.API.Core.Telemetry;
23
using Fossa.Licensing;
34
using Microsoft.Extensions.Hosting;
45
using TIKSN.Deployment;
@@ -12,17 +13,20 @@ public class SystemLicenseRetriever : ISystemLicenseRetriever
1213
private readonly IHostEnvironment _hostEnvironment;
1314
private readonly ILicenseFactory<SystemEntitlements, SystemLicenseEntitlements> _licenseFactory;
1415
private readonly ILicenseFileRepository _licenseFileRepository;
16+
private readonly ISystemLicenseMetricsRecorder _systemLicenseMetricsRecorder;
1517
private readonly ISystemPropertiesQueryRepository _systemPropertiesQueryRepository;
1618

1719
public SystemLicenseRetriever(
1820
ILicenseFileRepository licenseFileRepository,
1921
ILicenseFactory<SystemEntitlements, SystemLicenseEntitlements> licenseFactory,
22+
ISystemLicenseMetricsRecorder systemLicenseMetricsRecorder,
2023
ICertificateProvider certificateProvider,
2124
IHostEnvironment hostEnvironment,
2225
ISystemPropertiesQueryRepository systemPropertiesQueryRepository)
2326
{
2427
_licenseFileRepository = licenseFileRepository ?? throw new ArgumentNullException(nameof(licenseFileRepository));
2528
_licenseFactory = licenseFactory ?? throw new ArgumentNullException(nameof(licenseFactory));
29+
_systemLicenseMetricsRecorder = systemLicenseMetricsRecorder ?? throw new ArgumentNullException(nameof(systemLicenseMetricsRecorder));
2630
_certificateProvider = certificateProvider ?? throw new ArgumentNullException(nameof(certificateProvider));
2731
_hostEnvironment = hostEnvironment ?? throw new ArgumentNullException(nameof(hostEnvironment));
2832
_systemPropertiesQueryRepository = systemPropertiesQueryRepository ?? throw new ArgumentNullException(nameof(systemPropertiesQueryRepository));
@@ -41,12 +45,16 @@ public async Task<Validation<Error, License<SystemEntitlements>>> GetAsync(Cance
4145

4246
var licenseValidation = _licenseFactory.Create(licenseData, certificate);
4347

44-
return licenseValidation
48+
licenseValidation = licenseValidation
4549
.Validate(
4650
license => license.Entitlements.SystemId == systemPropertiesEntity.SystemID,
4751
11751858, "Current System License is issued to another system.")
4852
.Validate(
4953
license => _hostEnvironment.MatchesEnvironment(license.Entitlements.EnvironmentName),
5054
19509088, "Current System License is issued for another deployment environment.");
55+
56+
_systemLicenseMetricsRecorder.Record(licenseValidation);
57+
58+
return licenseValidation;
5159
}
5260
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Fossa.Licensing;
2+
using TIKSN.Licensing;
3+
4+
namespace Fossa.API.Core.Telemetry;
5+
6+
public interface ISystemLicenseMetricsRecorder
7+
{
8+
/// <summary>
9+
/// Records the system license metrics.
10+
/// </summary>
11+
/// <param name="license">The license to record.</param>
12+
void Record(Validation<Error, License<SystemEntitlements>> license);
13+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System.Diagnostics.Metrics;
2+
using Fossa.Licensing;
3+
using TIKSN.Licensing;
4+
5+
namespace Fossa.API.Core.Telemetry;
6+
7+
public class SystemLicenseMetricsRecorder : ISystemLicenseMetricsRecorder
8+
{
9+
private readonly Gauge<double> _daysLeft;
10+
private readonly TimeProvider _timeProvider;
11+
12+
public SystemLicenseMetricsRecorder(
13+
TimeProvider timeProvider,
14+
IMeterFactory meterFactory)
15+
{
16+
var meter = meterFactory.Create("Fossa.API.Core.Telemetry");
17+
_daysLeft = meter.CreateGauge<double>("fossa.api.core.telemetry.system_license_days_left");
18+
_timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
19+
}
20+
21+
public void Record(Validation<Error, License<SystemEntitlements>> license)
22+
{
23+
_daysLeft.Record(
24+
license.Match(
25+
validLicense => CalculateTimeLeft(validLicense).TotalDays,
26+
_ => 0.0),
27+
new KeyValuePair<string, object?>("license_status",
28+
license.Match(
29+
validLicense => "valid",
30+
_ => "invalid")));
31+
}
32+
33+
private TimeSpan CalculateTimeLeft(License<SystemEntitlements> validLicense)
34+
{
35+
var now = _timeProvider.GetUtcNow();
36+
if (validLicense.Terms.NotAfter <= now)
37+
{
38+
return TimeSpan.Zero;
39+
}
40+
41+
return validLicense.Terms.NotAfter.Subtract(now);
42+
}
43+
}

tests/API.UnitTests/PublicAPITests.CoreAssemblyHasNoPublicAPIChangesAsync.verified.txt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ namespace Fossa.API.Core.Services
983983
}
984984
public class SystemLicenseRetriever : Fossa.API.Core.Services.ISystemLicenseRetriever
985985
{
986-
public SystemLicenseRetriever(Fossa.API.Core.Repositories.ILicenseFileRepository licenseFileRepository, TIKSN.Licensing.ILicenseFactory<Fossa.Licensing.SystemEntitlements, Fossa.Licensing.SystemLicenseEntitlements> licenseFactory, Fossa.API.Core.Services.ICertificateProvider certificateProvider, Microsoft.Extensions.Hosting.IHostEnvironment hostEnvironment, Fossa.API.Core.Repositories.ISystemPropertiesQueryRepository systemPropertiesQueryRepository) { }
986+
public SystemLicenseRetriever(Fossa.API.Core.Repositories.ILicenseFileRepository licenseFileRepository, TIKSN.Licensing.ILicenseFactory<Fossa.Licensing.SystemEntitlements, Fossa.Licensing.SystemLicenseEntitlements> licenseFactory, Fossa.API.Core.Telemetry.ISystemLicenseMetricsRecorder systemLicenseMetricsRecorder, Fossa.API.Core.Services.ICertificateProvider certificateProvider, Microsoft.Extensions.Hosting.IHostEnvironment hostEnvironment, Fossa.API.Core.Repositories.ISystemPropertiesQueryRepository systemPropertiesQueryRepository) { }
987987
public System.Threading.Tasks.Task<LanguageExt.Validation<LanguageExt.Common.Error, TIKSN.Licensing.License<Fossa.Licensing.SystemEntitlements>>> GetAsync(System.Threading.CancellationToken cancellationToken) { }
988988
}
989989
public static class SystemProperties
@@ -996,6 +996,18 @@ namespace Fossa.API.Core.Services
996996
public System.Threading.Tasks.Task InitializeAsync(System.Threading.CancellationToken cancellationToken) { }
997997
}
998998
}
999+
namespace Fossa.API.Core.Telemetry
1000+
{
1001+
public interface ISystemLicenseMetricsRecorder
1002+
{
1003+
void Record(LanguageExt.Validation<LanguageExt.Common.Error, TIKSN.Licensing.License<Fossa.Licensing.SystemEntitlements>> license);
1004+
}
1005+
public class SystemLicenseMetricsRecorder : Fossa.API.Core.Telemetry.ISystemLicenseMetricsRecorder
1006+
{
1007+
public SystemLicenseMetricsRecorder(System.TimeProvider timeProvider, System.Diagnostics.Metrics.IMeterFactory meterFactory) { }
1008+
public void Record(LanguageExt.Validation<LanguageExt.Common.Error, TIKSN.Licensing.License<Fossa.Licensing.SystemEntitlements>> license) { }
1009+
}
1010+
}
9991011
namespace Fossa.API.Core.Tenant
10001012
{
10011013
public interface ITenantIdProvider<T>

0 commit comments

Comments
 (0)