Browse Source

Refactor `TelemetryActivityStorage` for improved readability.

pull/23059/head
Emre KARA 1 year ago
parent
commit
e2b5c46b7f
  1. 80
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/Storage/TelemetryActivityStorage.cs

80
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/Storage/TelemetryActivityStorage.cs

@ -16,10 +16,15 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
{ {
private const string MutexName = "Global\\TelemetryActivityStorage"; private const string MutexName = "Global\\TelemetryActivityStorage";
private const string TestModeEnvironmentVariable = "ABP_TELEMETRY_TEST_MODE"; private const string TestModeEnvironmentVariable = "ABP_TELEMETRY_TEST_MODE";
private readonly TimeSpan _infoExpirationPeriod; private readonly TimeSpan _infoExpirationPeriod;
private readonly TimeSpan _activitySendPeriod; private readonly TimeSpan _activitySendPeriod;
private TelemetryActivityStorageState? _cachedState; private TelemetryActivityStorageState? _cachedState;
private readonly static JsonSerializerOptions JsonSerializerOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
public TelemetryActivityStorage() public TelemetryActivityStorage()
{ {
@ -30,7 +35,7 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
public async Task BufferActivityAsync(ActivityEvent activityEvent) public async Task BufferActivityAsync(ActivityEvent activityEvent)
{ {
await ModifyStateAsync(state => await UpdateStateAsync(state =>
{ {
state.Activities.Insert(0, activityEvent); state.Activities.Insert(0, activityEvent);
}); });
@ -44,7 +49,7 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
public async Task EndSessionAsync() public async Task EndSessionAsync()
{ {
await ModifyStateAsync(state => await UpdateStateAsync(state =>
{ {
state.SessionId = null; state.SessionId = null;
}); });
@ -59,7 +64,7 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
return state.SessionId.Value; return state.SessionId.Value;
} }
await ModifyStateAsync(s => await UpdateStateAsync(s =>
{ {
s.SessionId = Guid.NewGuid(); s.SessionId = Guid.NewGuid();
}); });
@ -68,7 +73,7 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
public async Task MarkActivitiesAsSentAsync() public async Task MarkActivitiesAsSentAsync()
{ {
await ModifyStateAsync(state => await UpdateStateAsync(state =>
{ {
state.ActivitySendTime = DateTimeOffset.UtcNow; state.ActivitySendTime = DateTimeOffset.UtcNow;
state.Activities.Clear(); state.Activities.Clear();
@ -77,7 +82,7 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
public async Task MarkSolutionInfoAsAddedAsync(Guid solutionId) public async Task MarkSolutionInfoAsAddedAsync(Guid solutionId)
{ {
await ModifyStateAsync(state => await UpdateStateAsync(state =>
{ {
state.Solutions[solutionId] = DateTimeOffset.UtcNow; state.Solutions[solutionId] = DateTimeOffset.UtcNow;
}); });
@ -85,7 +90,7 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
public async Task MarkApplicationInfoAsAddedAsync(Guid applicationId) public async Task MarkApplicationInfoAsAddedAsync(Guid applicationId)
{ {
await ModifyStateAsync(state => await UpdateStateAsync(state =>
{ {
state.Applications[applicationId] = DateTimeOffset.UtcNow; state.Applications[applicationId] = DateTimeOffset.UtcNow;
}); });
@ -93,7 +98,7 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
public async Task MarkDeviceInfoAsAddedAsync() public async Task MarkDeviceInfoAsAddedAsync()
{ {
await ModifyStateAsync(state => await UpdateStateAsync(state =>
{ {
state.LastDeviceInfoAddTime = DateTimeOffset.UtcNow; state.LastDeviceInfoAddTime = DateTimeOffset.UtcNow;
}); });
@ -130,11 +135,11 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
return bool.TryParse(testModeVariable, out var isTestMode) && isTestMode; return bool.TryParse(testModeVariable, out var isTestMode) && isTestMode;
} }
private async Task ModifyStateAsync(Action<TelemetryActivityStorageState> modifyAction) private async Task UpdateStateAsync(Action<TelemetryActivityStorageState> modifyAction)
{ {
var state = await GetStateAsync(); var state = await GetStateAsync();
modifyAction(state); modifyAction(state);
await SaveAsync(); Save();
} }
private async Task<DateTimeOffset?> GetLastActivitySendTimeAsync() private async Task<DateTimeOffset?> GetLastActivitySendTimeAsync()
@ -166,21 +171,16 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
return lastSend is null || DateTimeOffset.UtcNow - lastSend > _infoExpirationPeriod; return lastSend is null || DateTimeOffset.UtcNow - lastSend > _infoExpirationPeriod;
} }
private async Task<TelemetryActivityStorageState> GetStateAsync() private async ValueTask<TelemetryActivityStorageState> GetStateAsync()
{ {
if (_cachedState != null) if (_cachedState != null)
{ {
return _cachedState; return _cachedState;
} }
EnsureFileExists(); EnsureStorageExists();
_cachedState = await LoadStateFromFileAsync() ?? new TelemetryActivityStorageState();
return _cachedState; _cachedState = await WithExclusiveFileLockAsync(async stream =>
}
private async Task<TelemetryActivityStorageState?> LoadStateFromFileAsync()
{
return await WithExclusiveFileLockAsync(async stream =>
{ {
using var reader = new StreamReader(stream, Encoding.UTF8); using var reader = new StreamReader(stream, Encoding.UTF8);
var encryptedJson = await reader.ReadToEndAsync(); var encryptedJson = await reader.ReadToEndAsync();
@ -191,51 +191,52 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
} }
var json = EncryptionHelper.Decrypt(encryptedJson); var json = EncryptionHelper.Decrypt(encryptedJson);
return JsonSerializer.Deserialize<TelemetryActivityStorageState?>(json, GetJsonSerializerOptions()) return JsonSerializer.Deserialize<TelemetryActivityStorageState>(json, JsonSerializerOptions)
?? new TelemetryActivityStorageState(); ?? new TelemetryActivityStorageState();
}); }) ?? new TelemetryActivityStorageState();
return _cachedState;
} }
private Task SaveAsync() private void Save()
{ {
var state = _cachedState ?? new TelemetryActivityStorageState(); var state = _cachedState ?? new TelemetryActivityStorageState();
var json = JsonSerializer.Serialize(state, GetJsonSerializerOptions()); var json = JsonSerializer.Serialize(state, JsonSerializerOptions);
var encryptedJson = EncryptionHelper.Encrypt(json); var encryptedJson = EncryptionHelper.Encrypt(json);
File.WriteAllText(TelemetryPaths.ActivityStorage, encryptedJson, Encoding.UTF8); File.WriteAllText(TelemetryPaths.ActivityStorage, encryptedJson, Encoding.UTF8);
return Task.CompletedTask;
} }
private void EnsureFileExists() private void EnsureStorageExists()
{ {
try try
{ {
EnsureDirectoryExists(); CreateDirectoryIfNotExists(Path.GetDirectoryName(TelemetryPaths.ActivityStorage)!);
if (!File.Exists(TelemetryPaths.ActivityStorage)) if (!File.Exists(TelemetryPaths.ActivityStorage))
{ {
CreateInitialFile(); InitializeStorage();
} }
} }
catch catch
{ {
// Ignored intentionally // Ignored
} }
} }
private void EnsureDirectoryExists() private static void CreateDirectoryIfNotExists(string path)
{ {
var directory = Path.GetDirectoryName(TelemetryPaths.ActivityStorage); if (!Directory.Exists(path))
if (!Directory.Exists(directory))
{ {
Directory.CreateDirectory(directory!); Directory.CreateDirectory(path);
} }
} }
private void CreateInitialFile()
private void InitializeStorage()
{ {
var initialState = _cachedState ?? new TelemetryActivityStorageState(); var initialState = _cachedState ?? new TelemetryActivityStorageState();
var json = JsonSerializer.Serialize(initialState, GetJsonSerializerOptions()); var json = JsonSerializer.Serialize(initialState, JsonSerializerOptions);
var encryptedJson = EncryptionHelper.Encrypt(json); var encryptedJson = EncryptionHelper.Encrypt(json);
File.WriteAllText(TelemetryPaths.ActivityStorage, encryptedJson, Encoding.UTF8); File.WriteAllText(TelemetryPaths.ActivityStorage, encryptedJson, Encoding.UTF8);
} }
@ -253,15 +254,4 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
return await action(stream); return await action(stream);
}); });
} }
private static JsonSerializerOptions GetJsonSerializerOptions()
{
return new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
}
} }
Loading…
Cancel
Save