From 5c07449631405efbaab77e8676d069856f0333c5 Mon Sep 17 00:00:00 2001 From: Drombeys Date: Wed, 1 May 2024 09:46:57 +0300 Subject: [PATCH] Improve request logging --- .../Launcher.cs | 2 +- .../Manager/FileDownloadManager.cs | 20 ++--- .../Manager/InitializerManager.cs | 35 ++++---- .../Services/GitHubApiService.cs | 87 +++++++++++-------- .../ViewModels/DownloadMenuViewModel.cs | 2 +- .../ViewModels/LinkViewModel.cs | 2 +- .../AuthenticationViewModelValidator.cs | 6 +- .../Validators/StartGameViewModelValidator.cs | 4 +- 8 files changed, 87 insertions(+), 71 deletions(-) diff --git a/src/ImeSense.Launchers.Belarus.Core/Launcher.cs b/src/ImeSense.Launchers.Belarus.Core/Launcher.cs index 7918f86..3c4e889 100644 --- a/src/ImeSense.Launchers.Belarus.Core/Launcher.cs +++ b/src/ImeSense.Launchers.Belarus.Core/Launcher.cs @@ -17,7 +17,7 @@ public static class Launcher var process = new Process { StartInfo = new ProcessStartInfo { FileName = path, - Arguments = arguments != null + Arguments = arguments is not null ? string.Join(" ", arguments) : string.Empty, WorkingDirectory = workingDirectory, diff --git a/src/ImeSense.Launchers.Belarus.Core/Manager/FileDownloadManager.cs b/src/ImeSense.Launchers.Belarus.Core/Manager/FileDownloadManager.cs index 2787a01..286a4f0 100644 --- a/src/ImeSense.Launchers.Belarus.Core/Manager/FileDownloadManager.cs +++ b/src/ImeSense.Launchers.Belarus.Core/Manager/FileDownloadManager.cs @@ -4,19 +4,13 @@ namespace ImeSense.Launchers.Belarus.Core.Manager; -public class FileDownloadManager : IFileDownloadManager +/// +/// Default constructor +/// +public class FileDownloadManager(ILogger? logger, HttpClient httpClient) : IFileDownloadManager { - private readonly ILogger? _logger; - private readonly HttpClient _httpClient; - - /// - /// Default constructor - /// - public FileDownloadManager(ILogger? logger, HttpClient httpClient) - { - _logger = logger; - _httpClient = httpClient; - } + private readonly ILogger? _logger = logger; + private readonly HttpClient _httpClient = httpClient; /// /// Downloads a file from the specified URL and saves it to the specified path. @@ -93,9 +87,11 @@ public async Task DownloadAsync(Uri url, string filePath, IProgress? status } } catch (HttpRequestException ex) { _logger?.LogError("{Message}", ex.Message); + _logger?.LogError("{StackTrace}", ex.StackTrace); throw; } catch (Exception ex) { _logger?.LogError("{Message}", ex.Message); + _logger?.LogError("{StackTrace}", ex.StackTrace); throw; } } diff --git a/src/ImeSense.Launchers.Belarus.Core/Manager/InitializerManager.cs b/src/ImeSense.Launchers.Belarus.Core/Manager/InitializerManager.cs index 887d783..fa81581 100644 --- a/src/ImeSense.Launchers.Belarus.Core/Manager/InitializerManager.cs +++ b/src/ImeSense.Launchers.Belarus.Core/Manager/InitializerManager.cs @@ -255,24 +255,25 @@ private async Task IsCheckGitHubConnectionAsync(CancellationToken cancella private async Task IsLauncherReleaseCurrentAsync(CancellationToken cancellationToken = default) { var tags = await _gitStorageApiService.GetTagsAsync(UriStorage.LauncherApiUri, cancellationToken); - if (tags != null) { - var currentVersion = $"{ApplicationHelper.GetAppVersion()}"; - if (currentVersion[0] != 'v') { - currentVersion = currentVersion.Insert(0, "v"); - } + if (tags is null) { + return true; + } - var countTag = tags.Count(x => x!.Name.Equals(currentVersion)); - if (countTag == 0) { - // If there is no such release, we return true so that there is no looping - return true; - } + var currentVersion = $"{ApplicationHelper.GetAppVersion()}"; + if (currentVersion[0] is not 'v') { + currentVersion = currentVersion.Insert(0, "v"); + } - var firstTag = tags.FirstOrDefault(); - if (firstTag != null) { - return firstTag.Name.Equals(currentVersion); - } + var countTag = tags.Count(x => x!.Name.Equals(currentVersion)); + if (countTag == 0) { + // If there is no such release, we return true so that there is no looping return true; } + + var firstTag = tags.FirstOrDefault(); + if (firstTag is not null) { + return firstTag.Name.Equals(currentVersion); + } return true; } @@ -281,7 +282,7 @@ private async Task IsGameReleaseCurrentAsync(CancellationToken cancellatio var gitStorageRelease = _launcherStorage.GitHubRelease; if (File.Exists(PathStorage.CurrentRelease)) { - var releaseComparer = gitStorageRelease != null && await _releaseComparerService.IsComparerAsync(gitStorageRelease, cancellationToken); + var releaseComparer = gitStorageRelease is not null && await _releaseComparerService.IsComparerAsync(gitStorageRelease, cancellationToken); if (!releaseComparer) { await FileSystemHelper.WriteReleaseAsync(gitStorageRelease, PathStorage.CurrentRelease, cancellationToken); _logger?.LogInformation("The releases don't match. Update required!"); @@ -302,7 +303,7 @@ private async Task RemoteLoadWebResourcesAsync(CancellationToken cancellationTok try { var contents = await _gitStorageApiService .DownloadJsonAsync>(FileNameStorage.WebResources, UriStorage.BelarusApiUri, cancellationToken); - if (contents != null) { + if (contents is not null) { await FileSystemHelper.WriteReleaseAsync(contents, Path.Combine(DirectoryStorage.LauncherCache, FileNameStorage.WebResources), cancellationToken); _launcherStorage.WebResources = new(contents); } @@ -346,7 +347,7 @@ private void AddNews(Locale? locale, List allNews, IEnumerable< return; } - if (news != null) { + if (news is not null) { allNews.Add(new LangNewsContent(locale, news)); } else { _logger?.LogError("Failure to load news in {locale}", locale.Title); diff --git a/src/ImeSense.Launchers.Belarus.Core/Services/GitHubApiService.cs b/src/ImeSense.Launchers.Belarus.Core/Services/GitHubApiService.cs index 50ba79c..5937163 100644 --- a/src/ImeSense.Launchers.Belarus.Core/Services/GitHubApiService.cs +++ b/src/ImeSense.Launchers.Belarus.Core/Services/GitHubApiService.cs @@ -22,66 +22,85 @@ public class GitHubApiService(ILogger? logger, HttpClient http /// The deserialized object of type T if successful, or null if the file is not found or deserialization fails public async Task DownloadJsonAsync(string filename, Uri? uriRepository = null, CancellationToken cancellationToken = default) where T : class { - if (uriRepository == null) { - if (_httpClient.BaseAddress == null) { - throw new NullReferenceException("No base address for HttpClient"); - } - uriRepository = _httpClient.BaseAddress; - } + uriRepository ??= _httpClient.BaseAddress ?? throw new NullReferenceException("No base address for HttpClient"); // Get the GitHub release information GitHubRelease? release; - if (_launcherStorage == null) { + if (_launcherStorage is null) { release = await GetLastReleaseAsync(_httpClient.BaseAddress, cancellationToken: cancellationToken); + _logger?.LogInformation("Retrieved last release information from server"); } else { release = _launcherStorage.GitHubRelease; + _logger?.LogInformation("Retrieved last release information from local storage"); + } + + if (release is null || release.Assets is null) { + _logger?.LogWarning("Release information or assets are null"); + return null; } + // Find the asset with the specified filename - var asset = release?.Assets?.FirstOrDefault(n => n.Name.Equals(filename)); + var asset = release.Assets.FirstOrDefault(n => n.Name.Equals(filename)); + if (asset is null) { + _logger?.LogError("Asset with filename {Filename} not found", filename); + return null; + } + // Download the asset - return await _httpClient.GetFromJsonAsync(asset?.BrowserDownloadUrl, typeof(T), - SourceGenerationContext.Default, cancellationToken: cancellationToken) as T; + var response = await _httpClient.GetAsync(asset.BrowserDownloadUrl, cancellationToken); + if (!response.IsSuccessStatusCode) { + _logger?.LogError("Failed to download asset from {BrowserDownloadUrl}. Status code: {StatusCode}", + asset.BrowserDownloadUrl, response.StatusCode); + return null; + } + var stream = await response.Content.ReadAsStreamAsync(cancellationToken); + + return await JsonSerializer.DeserializeAsync(stream, typeof(T), SourceGenerationContext.Default, cancellationToken) as T; + } public async Task GetLastReleaseAsync(Uri? uriRepository = null, CancellationToken cancellationToken = default) { - if (uriRepository == null) { - if (_httpClient.BaseAddress == null) { - throw new NullReferenceException("No base address for HttpClient"); - } - uriRepository = _httpClient.BaseAddress; + uriRepository ??= _httpClient.BaseAddress ?? throw new NullReferenceException("No base address for HttpClient"); + + var response = await _httpClient.GetAsync(new Uri(uriRepository, "releases/latest"), cancellationToken); + if (!response.IsSuccessStatusCode) { + _logger?.LogError("Failed to get last release from {UriRepository}. Status code: {StatusCode}", uriRepository, + response.StatusCode); + return null; } - return await _httpClient.GetFromJsonAsync(new Uri(uriRepository, "releases/latest"), - SourceGenerationContext.Default.GitHubRelease, cancellationToken: cancellationToken); + return await response.Content.ReadFromJsonAsync(typeof(GitHubRelease), SourceGenerationContext.Default, cancellationToken: cancellationToken) as GitHubRelease; } public async Task GetReleaseAsync(string tag, Uri? uriRepository = null, CancellationToken cancellationToken = default) { - if (uriRepository == null) { - if (_httpClient.BaseAddress == null) { - throw new NullReferenceException("No base address for HttpClient"); - } - uriRepository = _httpClient.BaseAddress; + uriRepository ??= _httpClient.BaseAddress ?? throw new NullReferenceException("No base address for HttpClient"); + + var response = await _httpClient.GetAsync(new Uri(uriRepository, $"releases"), cancellationToken); + if (!response.IsSuccessStatusCode) { + _logger?.LogError("Failed to get releases from {UriRepository}. Status code: {StatusCode}", uriRepository, + response.StatusCode); + return null; } - var json = await _httpClient.GetFromJsonAsync(new Uri(uriRepository, $"releases"), - SourceGenerationContext.Default.GitHubReleaseArray, cancellationToken: cancellationToken); - return json?.FirstOrDefault(t => t.TagName.Equals(tag)); + var releases = await response.Content.ReadFromJsonAsync(typeof(List), SourceGenerationContext.Default, cancellationToken: cancellationToken) as List; + + return releases?.FirstOrDefault(t => t.TagName.Equals(tag)); } public async Task?> GetTagsAsync(Uri? uriRepository = null, CancellationToken cancellationToken = default) { - if (uriRepository == null) { - if (_httpClient.BaseAddress == null) { - throw new NullReferenceException("No base address for HttpClient"); - } - uriRepository = _httpClient.BaseAddress; - } + uriRepository ??= _httpClient.BaseAddress ?? throw new NullReferenceException("No base address for HttpClient"); + var response = await _httpClient.GetAsync(new Uri(uriRepository, "tags"), cancellationToken); - await using var tagsStream = await _httpClient.GetStreamAsync(new Uri(uriRepository, "tags"), cancellationToken); - var tags = await JsonSerializer.DeserializeAsync(tagsStream, - SourceGenerationContext.Default.IEnumerableTag, cancellationToken: cancellationToken); + if (!response.IsSuccessStatusCode) { + _logger?.LogError("Failed to get tags from {UriRepository}. Status code: {StatusCode}", + uriRepository, response.StatusCode); + return default; + } + var stream = await response.Content.ReadAsStreamAsync(cancellationToken); + var tags = await JsonSerializer.DeserializeAsync(stream, SourceGenerationContext.Default.IEnumerableTag, cancellationToken: cancellationToken); if (tags is not null) { return tags; diff --git a/src/ImeSense.Launchers.Belarus/ViewModels/DownloadMenuViewModel.cs b/src/ImeSense.Launchers.Belarus/ViewModels/DownloadMenuViewModel.cs index 320b6b7..21e5a4e 100644 --- a/src/ImeSense.Launchers.Belarus/ViewModels/DownloadMenuViewModel.cs +++ b/src/ImeSense.Launchers.Belarus/ViewModels/DownloadMenuViewModel.cs @@ -125,7 +125,7 @@ private async Task DownloadsImplAsync(LauncherViewModel launcherViewModel) return; } - if (filesDownload != null && filesDownload.Any()) { + if (filesDownload is not null && filesDownload.Any()) { var countFiles = filesDownload.Count; var numberFile = 0; IsDownload = true; diff --git a/src/ImeSense.Launchers.Belarus/ViewModels/LinkViewModel.cs b/src/ImeSense.Launchers.Belarus/ViewModels/LinkViewModel.cs index f335e02..c3d0447 100644 --- a/src/ImeSense.Launchers.Belarus/ViewModels/LinkViewModel.cs +++ b/src/ImeSense.Launchers.Belarus/ViewModels/LinkViewModel.cs @@ -50,7 +50,7 @@ public LinkViewModel() private void Init() { - if (_launcherStorage.WebResources != null) { + if (_launcherStorage.WebResources is not null) { _logger?.LogInformation("Web resources are initialized"); WebResources.AddRange(_launcherStorage.WebResources); } else { diff --git a/src/ImeSense.Launchers.Belarus/ViewModels/Validators/AuthenticationViewModelValidator.cs b/src/ImeSense.Launchers.Belarus/ViewModels/Validators/AuthenticationViewModelValidator.cs index 9587b11..5896e15 100644 --- a/src/ImeSense.Launchers.Belarus/ViewModels/Validators/AuthenticationViewModelValidator.cs +++ b/src/ImeSense.Launchers.Belarus/ViewModels/Validators/AuthenticationViewModelValidator.cs @@ -14,21 +14,21 @@ public sealed class AuthenticationViewModelValidator(IAuthenticationValidator va public ValidationHelper EnsureUsernameNotEmpty(AuthorizationViewModel authorizationViewModel) { return authorizationViewModel.ValidationRule(viewModel => viewModel.Username, - username => username != null && _validator.IsUsernameNotEmpty(username), + username => username is not null && _validator.IsUsernameNotEmpty(username), _localeManager.GetStringByKey("LocalizedStrings.EnterNickName")); } public ValidationHelper EnsureUsernameCorrectLength(AuthorizationViewModel authorizationViewModel) { return authorizationViewModel.ValidationRule(viewModel => viewModel.Username, - username => username != null && _validator.IsUsernameCorrectLength(username), + username => username is not null && _validator.IsUsernameCorrectLength(username), _localeManager.GetStringByKey("LocalizedStrings.TooLongNickname")); } public ValidationHelper EnsureUsernameCorrectCharacters(AuthorizationViewModel authorizationViewModel) { return authorizationViewModel.ValidationRule(viewModel => viewModel.Username, - username => username != null && _validator.IsUsernameCorrectCharacters(username), + username => username is not null && _validator.IsUsernameCorrectCharacters(username), _localeManager.GetStringByKey("LocalizedStrings.InvalidCharacters")); } } diff --git a/src/ImeSense.Launchers.Belarus/ViewModels/Validators/StartGameViewModelValidator.cs b/src/ImeSense.Launchers.Belarus/ViewModels/Validators/StartGameViewModelValidator.cs index 4a509fe..a341866 100644 --- a/src/ImeSense.Launchers.Belarus/ViewModels/Validators/StartGameViewModelValidator.cs +++ b/src/ImeSense.Launchers.Belarus/ViewModels/Validators/StartGameViewModelValidator.cs @@ -15,14 +15,14 @@ public ValidationHelper EnsureIpAddressNotEmpty(StartGameViewModel startGameView { return startGameViewModel.ValidationRule(viewModel => viewModel.IpAddress, - serverAddress => serverAddress != null && _validator.IsIpAddressNotEmpty(serverAddress), + serverAddress => serverAddress is not null && _validator.IsIpAddressNotEmpty(serverAddress), _localeManager.GetStringByKey("LocalizedStrings.IpAddressNotEntered")); } public ValidationHelper EnsureValidIpAddressOrUrl(StartGameViewModel startGameViewModel) { return startGameViewModel.ValidationRule(viewModel => viewModel.IpAddress, - serverAddress => serverAddress != null && _validator.IsValidIpAddressOrUrl(serverAddress), + serverAddress => serverAddress is not null && _validator.IsValidIpAddressOrUrl(serverAddress), _localeManager.GetStringByKey("LocalizedStrings.InvalidIpAddress")); } }