Browse Source

Refactor telemetry services for improved data handling efficiency.

pull/23059/head
Emre KARA 1 year ago
parent
commit
141a1587e6
  1. 56
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/ActivityDataProvider.cs
  2. 2
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/ActivityStorage.cs
  3. 5
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/IActivityDataProvider.cs
  4. 27
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/TelemetryDataSender.cs
  5. 2
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/TelemetryService.cs

56
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/ActivityDataProvider.cs

@ -4,7 +4,6 @@ using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
@ -35,7 +34,6 @@ public class ActivityDataProvider : IActivityDataProvider, IScopedDependency
public async Task AddDeviceInformationAsync(ActivityData activityData)
{
activityData.Add(ActivityPropertyName.DeviceId, await _deviceInfoProvider.GetDeviceIdAsync());
activityData.Add(ActivityPropertyName.DeviceType, _deviceInfoProvider.GetDeviceType());
activityData.Add(ActivityPropertyName.DeviceLanguage, _deviceInfoProvider.GetLanguage());
activityData.Add(ActivityPropertyName.OperatingSystem, _deviceInfoProvider.GetOperatingSystem());
@ -60,20 +58,18 @@ public class ActivityDataProvider : IActivityDataProvider, IScopedDependency
return;
}
var solutionPath = value as string;
if (string.IsNullOrEmpty(solutionPath) || !File.Exists(solutionPath))
var solutionPath = (string)value;
if (!File.Exists(solutionPath))
{
return;
}
var solutionJson = await File.ReadAllTextAsync(solutionPath);
var solutionJson = File.ReadAllText(solutionPath);
using var solutionDoc = JsonDocument.Parse(solutionJson);
var root = solutionDoc.RootElement;
if (!TryAddSolutionId(activityData, root, out var solutionId))
{
return;
}
var solutionId = GetSolutionId(root);
activityData.Add(ActivityPropertyName.SolutionId, solutionId);
if (root.TryGetProperty("creatingStudioConfiguration", out var config))
{
@ -84,22 +80,38 @@ public class ActivityDataProvider : IActivityDataProvider, IScopedDependency
if (root.TryGetProperty("modules", out var modulesElement) && modulesElement.ValueKind == JsonValueKind.Object)
{
var modules = await ExtractModulesAsync(modulesElement);
var modules = ExtractModulesAsync(modulesElement);
activityData.Add(ActivityPropertyName.InstalledModules, modules);
}
}
private bool TryAddSolutionId(ActivityData activityData, JsonElement root, out Guid solutionId)
public async Task<Guid> ReadDeviceIdAsync()
{
solutionId = Guid.Empty;
if (!root.TryGetProperty("id", out var idElement) ||
!Guid.TryParse(idElement.GetString(), out solutionId))
return await _deviceInfoProvider.GetDeviceIdAsync();
}
public Guid? ReadSolutionId(string solutionPath)
{
if (!File.Exists(solutionPath))
{
return false;
return null;
}
var solutionJson = File.ReadAllText(solutionPath);
using var solutionDoc = JsonDocument.Parse(solutionJson);
var root = solutionDoc.RootElement;
activityData.Add(ActivityPropertyName.SolutionId, solutionId);
return true;
return GetSolutionId(root);
}
private Guid GetSolutionId(JsonElement root)
{
if (root.TryGetProperty("id", out var idElement) &&
Guid.TryParse(idElement.GetString(), out var solutionId))
{
return solutionId;
}
throw new Exception("Solution ID is not valid.");
}
private void AddCreatingStudioConfiguration(ActivityData activityData, JsonElement config)
@ -133,7 +145,7 @@ public class ActivityDataProvider : IActivityDataProvider, IScopedDependency
activityData.Add(ActivityPropertyName.SocialLogins, config.GetProperty("socialLogin").GetBoolean());
}
private async Task<List<SolutionModuleInstallationInfo>> ExtractModulesAsync(JsonElement modulesElement)
private List<SolutionModuleInstallationInfo> ExtractModulesAsync(JsonElement modulesElement)
{
var modules = new List<SolutionModuleInstallationInfo>();
@ -151,7 +163,7 @@ public class ActivityDataProvider : IActivityDataProvider, IScopedDependency
continue;
}
var moduleJson = await File.ReadAllTextAsync(path);
var moduleJson = File.ReadAllText(path);
using var moduleDoc = JsonDocument.Parse(moduleJson);
if (!moduleDoc.RootElement.TryGetProperty("imports", out var importsElement) ||
@ -283,9 +295,9 @@ public class ActivityDataProvider : IActivityDataProvider, IScopedDependency
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
await using var stream = await httpClient.GetStreamAsync($"{AbpPlatformUrls.AbpIoUrl}api/license/api-key");
using var doc = await JsonDocument.ParseAsync(stream);
var json = await httpClient.GetStringAsync($"{AbpPlatformUrls.AbpIoUrl}api/license/api-key");
using var doc = JsonDocument.Parse(json);
return doc.RootElement.GetProperty("licenseType").GetInt32();
}
}

2
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/ActivityStorage.cs

@ -28,7 +28,7 @@ public class ActivityStorage : IActivityStorage, ISingletonDependency
public async Task<List<ActivityData>> GetBufferedActivitiesAsync()
{
var state = await GetStateAsync();
return state.Activities;
return state.Activities.OrderBy(x => x.Time).ToList();
}
public async Task RemoveActivityAsync(string activityName, CancellationToken cancellationToken = default)

5
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/IActivityDataProvider.cs

@ -1,4 +1,5 @@
using System.Reflection;
using System;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
@ -9,4 +10,6 @@ public interface IActivityDataProvider
Task AddDeviceInformationAsync(ActivityData activityData);
Task AddApplicationInformation(ActivityData activityData);
Task AddSolutionInformationAsync(ActivityData activityData);
Task<Guid> ReadDeviceIdAsync();
Guid? ReadSolutionId(string solutionPath);
}

27
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/TelemetryDataSender.cs

@ -15,9 +15,8 @@ using Volo.Abp.Telemetry.Shared;
namespace Volo.Abp.Telemetry;
public class TelemetryDataSender : ITelemetryDataSender , IScopedDependency
public class TelemetryDataSender : ITelemetryDataSender, IScopedDependency
{
private readonly IActivityStorage _activityStorage;
private readonly IActivityDataProvider _activityDataProvider;
private const int ActivityBatchSize = 50;
@ -37,12 +36,17 @@ public class TelemetryDataSender : ITelemetryDataSender , IScopedDependency
if (activities.Count > 0)
{
await AddExtraInformationAsync(activities[0]);
for (var i = 0; i < activities.Count; i += ActivityBatchSize)
{
var activityBatch = activities.Skip(i).Take(ActivityBatchSize).ToList();
await httpClient.PostAsync($"{AbpPlatformUrls.TelemetryApiUrl}api/telemetry/collect", new StringContent(JsonSerializer.Serialize(activityBatch), Encoding.UTF8, "application/json"));
foreach (var activity in activityBatch)
{
await AddExtraInformationAsync(activity);
}
await httpClient.PostAsync($"{AbpPlatformUrls.TelemetryApiUrl}api/telemetry/collect",
new StringContent(JsonSerializer.Serialize(activityBatch), Encoding.UTF8, "application/json"));
}
await _activityStorage.MarkActivitiesAsSentAsync();
@ -58,13 +62,15 @@ public class TelemetryDataSender : ITelemetryDataSender , IScopedDependency
activityData.Add(ActivityPropertyName.SessionId, sessionId);
activityData.Add(ActivityPropertyName.IsFirstSession, isFirstSession);
activityData.Add(ActivityPropertyName.DeviceId, await _activityDataProvider.ReadDeviceIdAsync());
var lastDeviceInfoSendTime = await _activityStorage.GetLastDeviceInfoSendTimeAsync();
if (lastDeviceInfoSendTime is null || DateTimeOffset.UtcNow - lastDeviceInfoSendTime > TimeSpan.FromDays(7))
{
await _activityDataProvider.AddDeviceInformationAsync(activityData);
await _activityStorage.MarkDeviceInfoAsSentAsync();
}
if (activityData.ContainsKey(ActivityPropertyName.Assembly))
@ -74,21 +80,20 @@ public class TelemetryDataSender : ITelemetryDataSender , IScopedDependency
if (activityData.TryGetValue(ActivityPropertyName.SolutionPath, out var path))
{
var solutionPath = path as string;
if (string.IsNullOrEmpty(solutionPath) || !File.Exists(solutionPath))
var id = _activityDataProvider.ReadSolutionId((string)path);
if (id.HasValue)
{
return;
activityData.Add(ActivityPropertyName.SolutionId, id);
await _activityDataProvider.AddSolutionInformationAsync(activityData);
}
await _activityDataProvider.AddSolutionInformationAsync(activityData);
}
}
catch
{
//ignored
}
}
private static void AddAbpAuthenticationTokenAsync(HttpClient httpClient)
{
if (!File.Exists(AbpTelemetryPaths.AccessToken))

2
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/TelemetryService.cs

@ -58,7 +58,7 @@ public class TelemetryService : ITelemetryService , IScopedDependency
await _telemetryDataSender.SendAsync();
}
if (lastActivitySendTime is not null && lastActivitySendTime > DateTimeOffset.UtcNow.AddDays(7) )
if (lastActivitySendTime is not null && lastActivitySendTime < DateTimeOffset.UtcNow.AddDays(-1) )
{
await _telemetryDataSender.SendAsync();
}

Loading…
Cancel
Save