diff --git a/MusicX.Core/Services/BackendConnectionService.cs b/MusicX.Core/Services/BackendConnectionService.cs new file mode 100644 index 00000000..740174a2 --- /dev/null +++ b/MusicX.Core/Services/BackendConnectionService.cs @@ -0,0 +1,87 @@ +using System.Net.Http.Json; +using MusicX.Core.Models; +using MusicX.Shared; +using Newtonsoft.Json; +using NLog; + +namespace MusicX.Core.Services; + +public class BackendConnectionService(Logger logger, string appVersion) +{ + private string? _token; + public readonly HttpClient Client = new(); + + public string Host { get; set; } = +#if DEBUG + "http://localhost:2024"; +#else + "https://musicx.zznty.ru"; +#endif + + public async void ReportMetric(string eventName, string? source = null) + { + if (string.IsNullOrEmpty(_token)) + throw new NullReferenceException("Token is null"); + + try + { + using var response = await Client.PostAsJsonAsync($"/metrics/{eventName}/report", new ReportMetricRequest(appVersion, source)); + response.EnsureSuccessStatusCode(); + } + catch (Exception e) + { + logger.Error(e, "Error while reporting event metric {0}", eventName); + throw; + } + } + + public async Task GetTokenAsync(long userId) + { + if (_token is not null) return _token; + logger.Info("Получение временного токена Слушать вместе"); + + var host = await GetHostAsync(); + + Client.BaseAddress = new(host); + using var response = await Client.PostAsJsonAsync("/token", userId); + response.EnsureSuccessStatusCode(); + + _token = await response.Content.ReadFromJsonAsync() ?? + throw new NullReferenceException("Got null response for token request"); + + Client.DefaultRequestHeaders.Authorization = new("Bearer", _token); + + return _token; + } + + private async Task GetHostAsync() + { + if (!string.IsNullOrEmpty(Host)) + return Host; + + try + { + logger.Info("Получение адресса сервера Послушать вместе"); + using (var httpClient = new HttpClient()) + { + var response = await httpClient.GetAsync("https://fooxboy.blob.core.windows.net/musicx/ListenTogetherServers.json"); + + var contents = await response.Content.ReadAsStringAsync(); + + var servers = JsonConvert.DeserializeObject(contents); + + return Host = +#if DEBUG + servers.Test; +#else + servers.Production; +#endif + } + } + catch(Exception) + { + return "http://212.192.40.71:5000"; + } + + } +} \ No newline at end of file diff --git a/MusicX.Core/Services/ListenTogetherService.cs b/MusicX.Core/Services/ListenTogetherService.cs index f193bb9f..26a2fa89 100644 --- a/MusicX.Core/Services/ListenTogetherService.cs +++ b/MusicX.Core/Services/ListenTogetherService.cs @@ -14,6 +14,7 @@ public class ListenTogetherService : IAsyncDisposable private readonly Logger _logger; private HubConnection _connection; private IEnumerable _subscriptions; + private readonly BackendConnectionService _backendConnectionService; /// /// Изменилась позиция трека @@ -66,14 +67,14 @@ public class ListenTogetherService : IAsyncDisposable public string SessionId { get; set; } - public string ConnectUrl => $"{Host}/connect?id={SessionId}"; + public string ConnectUrl => $"{_backendConnectionService.Host}/connect?id={SessionId}"; - public string Host { get; private set; } = "https://musicx.zznty.ru:8443"; public string? Token { get; set; } - public ListenTogetherService(Logger logger) + public ListenTogetherService(Logger logger, BackendConnectionService backendConnectionService) { _logger = logger; + _backendConnectionService = backendConnectionService; SessionOwnerStoped += SessionUserStoped; } @@ -211,24 +212,17 @@ public async Task LeavePlaySessionAsync() LeaveSession?.Invoke(); } - public async Task LoginAsync(long userId) - { - Token = await GetTokenAsync(userId); - } - public async Task ConnectToServerAsync(long userId) { _logger.Info("Подключение к серверу Слушать вместе"); - await GetListenTogetherHostAsync(); - - var token = await GetTokenAsync(userId); + var token = await _backendConnectionService.GetTokenAsync(userId); this.Token = token; _connection = new HubConnectionBuilder() .WithAutomaticReconnect() - .WithUrl($"{Host}/hubs/listen", options => + .WithUrl($"{_backendConnectionService.Host}/hubs/listen", options => options.AccessTokenProvider = () => Task.FromResult(Token)!) .AddProtobufProtocol() .Build(); @@ -275,53 +269,6 @@ public async Task GetListenersInSession() } - private async Task GetTokenAsync(long userId) - { - _logger.Info("Получение временного токена Слушать вместе"); - - using var client = new HttpClient - { - BaseAddress = new(Host) - }; - using var response = await client.PostAsJsonAsync("/token", userId); - response.EnsureSuccessStatusCode(); - - var token = await response.Content.ReadFromJsonAsync() ?? throw new NullReferenceException("Got null response for token request"); - - return token; - } - - private async Task GetListenTogetherHostAsync() - { - if (!string.IsNullOrEmpty(Host)) - return Host; - - try - { - _logger.Info("Получение адресса сервера Послушать вместе"); - using (var httpClient = new HttpClient()) - { - var response = await httpClient.GetAsync("https://fooxboy.blob.core.windows.net/musicx/ListenTogetherServers.json"); - - var contents = await response.Content.ReadAsStringAsync(); - - var servers = JsonConvert.DeserializeObject(contents); - - return Host = -#if DEBUG - servers.Test; -#else - servers.Production; -#endif - } - } - catch(Exception) - { - return "http://212.192.40.71:5000"; - } - - } - private async Task SessionUserStoped() { await _connection.StopAsync(); diff --git a/MusicX.Core/Services/UserRadioService.cs b/MusicX.Core/Services/UserRadioService.cs index efd9d7ad..6c7ab3e2 100644 --- a/MusicX.Core/Services/UserRadioService.cs +++ b/MusicX.Core/Services/UserRadioService.cs @@ -8,40 +8,28 @@ using System.Net.Http.Json; using System.Text; using System.Threading.Tasks; -using VkNet.Abstractions; using VkNet.Model.Attachments; namespace MusicX.Core.Services { - public class UserRadioService + public class UserRadioService(Logger logger, BackendConnectionService backendConnectionService) { - private readonly Logger _logger; - private readonly ListenTogetherService _listenTogetherService; - private readonly IUsersCategory _usersCategory; - public bool IsStarted { get; private set; } - public UserRadioService(Logger logger, ListenTogetherService listenTogetherService, IUsersCategory usersCategory) - { - _logger = logger; - _listenTogetherService = listenTogetherService; - _usersCategory = usersCategory; - } - public async Task> GetStationsList() { - _logger.Info("Получение списка всех доступных станций"); + logger.Info("Получение списка всех доступных станций"); var stations = await HttpRequestAsync>("getStations", new Dictionary()); - _logger.Info($"Получено {stations.Count} пользовательских станций"); + logger.Info($"Получено {stations.Count} пользовательских станций"); return stations; } public Task CreateStationAsync(string sessionId, string title, string cover, string decription, long ownerId, string ownerName, string ownerPhoto) { - _logger.Info($"Создание пользовательской радиостанции с ID {sessionId}"); + logger.Info($"Создание пользовательской радиостанции с ID {sessionId}"); var p = new Dictionary() { @@ -61,7 +49,7 @@ public Task CreateStationAsync(string sessionId, string title, string c public Task DeleteStationAsync(string sessionId) { - _logger.Info($"Удаление пользовательской радиостанции с ID {sessionId}"); + logger.Info($"Удаление пользовательской радиостанции с ID {sessionId}"); var p = new Dictionary() { @@ -75,7 +63,6 @@ public Task DeleteStationAsync(string sessionId) public async Task UploadCoverAsync(string path) { - using var httpClient = await GetHttpClientAsync(); await using var stream = File.OpenRead(path); var data = new MultipartFormDataContent @@ -83,48 +70,28 @@ public async Task UploadCoverAsync(string path) { new StreamContent(stream), "image", "image" } }; - using var response = await httpClient.PostAsync("/radio/uploadImage", data); + using var response = await backendConnectionService.Client.PostAsync("/radio/uploadImage", data); response.EnsureSuccessStatusCode(); - return $"{_listenTogetherService.Host}/{await response.Content.ReadAsStringAsync()}"; + return $"{backendConnectionService.Host}/{await response.Content.ReadAsStringAsync()}"; } private async Task HttpRequestAsync(string method, Dictionary parameters) { try { - using var httpClient = await GetHttpClientAsync(); - var p = parameters.Select(x => x.Key + "=" + x.Value); - return await httpClient.GetFromJsonAsync("/radio/" + method + "?" + string.Join("&", p)); + return await backendConnectionService.Client.GetFromJsonAsync("/radio/" + method + "?" + string.Join("&", p)); } catch(Exception ex) { - _logger.Info($"Произошла ошибка при запросе: {ex}"); - _logger.Error(ex); + logger.Info($"Произошла ошибка при запросе: {ex}"); + logger.Error(ex); throw; } } - - private async ValueTask GetHttpClientAsync() - { - if (_listenTogetherService.Token is null) - { - var users = await _usersCategory.GetAsync(Enumerable.Empty()); - await _listenTogetherService.LoginAsync(users[0].Id); - } - - return new HttpClient - { - BaseAddress = new Uri(_listenTogetherService.Host), - DefaultRequestHeaders = - { - Authorization = new("Bearer", _listenTogetherService.Token) - } - }; - } } } diff --git a/MusicX.Server/Controllers/MetricsController.cs b/MusicX.Server/Controllers/MetricsController.cs new file mode 100644 index 00000000..fd06ad2a --- /dev/null +++ b/MusicX.Server/Controllers/MetricsController.cs @@ -0,0 +1,31 @@ +using System.Security.Claims; +using InfluxDB.Client; +using InfluxDB.Client.Api.Domain; +using InfluxDB.Client.Writes; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using MusicX.Shared; + +namespace MusicX.Server.Controllers; + +[Route("metrics")] +[Authorize] +public class MetricsController(IWriteApiAsync writeApi) : Controller +{ + [HttpPost("{eventName}/report")] + public async Task Report(string eventName, [FromBody] ReportMetricRequest metricRequest) + { + var userId = User.Claims.Single(b => b.Type == ClaimTypes.NameIdentifier).Value; + + var point = PointData.Measurement(eventName) + .Tag("userId", userId) + .Tag("version", metricRequest.AppVersion) + .Field("value", 1) + .Timestamp(DateTime.Now, WritePrecision.Ms); + + if (!string.IsNullOrEmpty(metricRequest.Source)) + point = point.Tag("source", metricRequest.Source); + + await writeApi.WritePointAsync(point); + } +} \ No newline at end of file diff --git a/MusicX.Server/MusicX.Server.csproj b/MusicX.Server/MusicX.Server.csproj index 62689cfb..f5d97095 100644 --- a/MusicX.Server/MusicX.Server.csproj +++ b/MusicX.Server/MusicX.Server.csproj @@ -10,6 +10,7 @@ + @@ -20,7 +21,6 @@ - diff --git a/MusicX.Server/Program.cs b/MusicX.Server/Program.cs index 429081fc..21934ee5 100644 --- a/MusicX.Server/Program.cs +++ b/MusicX.Server/Program.cs @@ -1,6 +1,7 @@ using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; +using InfluxDB.Client; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -48,6 +49,10 @@ builder.Services.AddSingleton(); builder.Services.AddTransient(); +builder.Services.AddScoped(_ => new InfluxDBClient(builder.Configuration.GetConnectionString("influxdb"))); +builder.Services.AddScoped( + provider => provider.GetRequiredService().GetWriteApiAsync()); + var app = builder.Build(); #if DEBUG diff --git a/MusicX.Server/appsettings.json b/MusicX.Server/appsettings.json index e0cca862..805f74ae 100644 --- a/MusicX.Server/appsettings.json +++ b/MusicX.Server/appsettings.json @@ -11,7 +11,9 @@ "Audience": "https://localhost/", "Key": "This is a sample secret key - please don't use in production environment.'" }, - + "ConnectionStrings": { + "InfluxDb": "http://localhost:8086/?logLevel=BASIC&org=musicx&bucket=metrics&token=94aS7aYiepHMckB5P_lHywIICm6XDq31BVYzX4YpxAflNx4bO7TJ7YaOfdAtR-uHO_wNh4E7WAEUR5EVLSVacA==" + }, "UsersCategories": { "Developers": [ 308764786, 316614260 ], "Recoms": [ 0 ], diff --git a/MusicX.Shared/ReportMetricRequest.cs b/MusicX.Shared/ReportMetricRequest.cs new file mode 100644 index 00000000..b3984b8d --- /dev/null +++ b/MusicX.Shared/ReportMetricRequest.cs @@ -0,0 +1,3 @@ +namespace MusicX.Shared; + +public record ReportMetricRequest(string AppVersion, string? Source); \ No newline at end of file diff --git a/MusicX/Controls/CroppedPlaylistControl.xaml.cs b/MusicX/Controls/CroppedPlaylistControl.xaml.cs index 633260df..0f0d8d96 100644 --- a/MusicX/Controls/CroppedPlaylistControl.xaml.cs +++ b/MusicX/Controls/CroppedPlaylistControl.xaml.cs @@ -102,6 +102,9 @@ private async void PlayPlaylist(object sender, System.Windows.Input.MouseButtonE }; Analytics.TrackEvent("PlayPlaylistWithButton", properties); + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("PlayPlaylistWithButton"); + var playerService = StaticService.Container.GetRequiredService(); if (!_nowPlay) diff --git a/MusicX/Controls/PlayerControl.xaml.cs b/MusicX/Controls/PlayerControl.xaml.cs index 1c11fd1f..cf7575f6 100644 --- a/MusicX/Controls/PlayerControl.xaml.cs +++ b/MusicX/Controls/PlayerControl.xaml.cs @@ -679,6 +679,9 @@ private void TextTrack_Click(object sender, RoutedEventArgs e) lyricsViewModel.Track = PlayerService.CurrentTrack; navigationService.OpenModal(lyricsViewModel); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("OpenAudioText"); } private async void DislikeButton_Click(object sender, RoutedEventArgs e) diff --git a/MusicX/Controls/PlaylistControl.xaml.cs b/MusicX/Controls/PlaylistControl.xaml.cs index 2c775cbd..9bd3d922 100644 --- a/MusicX/Controls/PlaylistControl.xaml.cs +++ b/MusicX/Controls/PlaylistControl.xaml.cs @@ -247,6 +247,9 @@ private void CardAction_Click(object sender, RoutedEventArgs e) {"Version", StaticService.Version } }; Analytics.TrackEvent("OpenPlaylist", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("OpenPlayList", "PlaylistControl"); var notificationService = StaticService.Container.GetRequiredService(); @@ -289,6 +292,9 @@ private async void PlayPlaylistGrid_MouseLeftButtonDown(object sender, MouseButt {"Version", StaticService.Version } }; Analytics.TrackEvent("PlayPlaylistWithButton", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("PlayPlaylistWithButton", "PlaylistControl"); var playerService = StaticService.Container.GetRequiredService(); diff --git a/MusicX/Controls/RecommendedPlaylistControl.xaml.cs b/MusicX/Controls/RecommendedPlaylistControl.xaml.cs index b61e308b..c495905b 100644 --- a/MusicX/Controls/RecommendedPlaylistControl.xaml.cs +++ b/MusicX/Controls/RecommendedPlaylistControl.xaml.cs @@ -137,6 +137,10 @@ private void TitleCard_MouseLeftButtonDown(object sender, MouseButtonEventArgs e {"Version", StaticService.Version } }; Analytics.TrackEvent("OpenReccomendedPlaylist", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("OpenPlayList", "RecommendedPlaylist"); + var navigationService = StaticService.Container.GetRequiredService(); navigationService.OpenExternalPage(new PlaylistView(Playlist.Playlist.Id,Playlist.Playlist.OwnerId , Playlist.Playlist.AccessKey)); diff --git a/MusicX/Controls/RecommsPlaylist.xaml.cs b/MusicX/Controls/RecommsPlaylist.xaml.cs index baac0488..474c84be 100644 --- a/MusicX/Controls/RecommsPlaylist.xaml.cs +++ b/MusicX/Controls/RecommsPlaylist.xaml.cs @@ -78,6 +78,9 @@ private void PlayPauseOverlay_OnMouseLeftButtonUp(object sender, MouseButtonEven {"Version", StaticService.Version } }; Analytics.TrackEvent("OpenPlaylist", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("OpenPlayList", "RecommsPlaylist"); var notificationService = StaticService.Container.GetRequiredService(); diff --git a/MusicX/Controls/TrackControl.xaml.cs b/MusicX/Controls/TrackControl.xaml.cs index f0501325..166d6c8f 100644 --- a/MusicX/Controls/TrackControl.xaml.cs +++ b/MusicX/Controls/TrackControl.xaml.cs @@ -338,6 +338,9 @@ private async void Grid_MouseDown(object sender, MouseButtonEventArgs e) {"Version", StaticService.Version } }; Analytics.TrackEvent("PlayTrack", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("PlayTrack", "TrackControl"); if (e.Source is TextBlock) return; diff --git a/MusicX/RootWindow.xaml.cs b/MusicX/RootWindow.xaml.cs index ea8931d4..302cc28a 100644 --- a/MusicX/RootWindow.xaml.cs +++ b/MusicX/RootWindow.xaml.cs @@ -121,6 +121,9 @@ await Task.Factory.StartNew(async() => {"Version", StaticService.Version } }; Analytics.TrackEvent("Connect to session", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("ConnectToSession"); var config = await configService.GetConfig(); await listenTogetherService.ConnectToServerAsync(config.UserId); diff --git a/MusicX/ViewModels/BoomProfileViewModel.cs b/MusicX/ViewModels/BoomProfileViewModel.cs index 9b96d201..ef0d3698 100644 --- a/MusicX/ViewModels/BoomProfileViewModel.cs +++ b/MusicX/ViewModels/BoomProfileViewModel.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Microsoft.AppCenter.Analytics; using Microsoft.AppCenter.Crashes; +using Microsoft.Extensions.DependencyInjection; using MusicX.Core.Exceptions.Boom; using MusicX.Core.Models.Boom; using MusicX.Core.Services; @@ -67,6 +68,9 @@ public async Task OpenProfile() {"Version", StaticService.Version } }; Analytics.TrackEvent("Open Boom profile", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("OpenBoomProfile"); Logger.Info("Открытие страницы Boom profile"); var config = await ConfigService.GetConfig(); diff --git a/MusicX/ViewModels/BoomViewModelBase.cs b/MusicX/ViewModels/BoomViewModelBase.cs index 12ae87bc..c4d064dc 100644 --- a/MusicX/ViewModels/BoomViewModelBase.cs +++ b/MusicX/ViewModels/BoomViewModelBase.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Microsoft.AppCenter.Analytics; using Microsoft.AppCenter.Crashes; +using Microsoft.Extensions.DependencyInjection; using MusicX.Core.Exceptions.Boom; using MusicX.Core.Models.Boom; using MusicX.Core.Services; @@ -55,6 +56,9 @@ public virtual async Task ArtistSelected() {"Version", StaticService.Version } }; Analytics.TrackEvent("Play Artist Mix", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("PlayArtistMix"); if (SelectedArtist == null) return; IsLoadingMix = true; @@ -101,6 +105,9 @@ public virtual async Task TagSelected() {"Version", StaticService.Version } }; Analytics.TrackEvent("Play Tag Mix", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("PlayTagMix"); if (SelectedTag == null) return; diff --git a/MusicX/ViewModels/Controls/ListenTogetherControlViewModel.cs b/MusicX/ViewModels/Controls/ListenTogetherControlViewModel.cs index 7cca67c4..1b1a2bb2 100644 --- a/MusicX/ViewModels/Controls/ListenTogetherControlViewModel.cs +++ b/MusicX/ViewModels/Controls/ListenTogetherControlViewModel.cs @@ -99,6 +99,9 @@ private async Task StartedSessionAsync() {"Version", StaticService.Version } }; Analytics.TrackEvent("Started session", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("StartSession"); IsLoading = true; var sessionId = await _service.StartSessionAsync(_configService.Config.UserId); @@ -139,6 +142,9 @@ private async Task ConnectAsync(string? sessionId) {"Version", StaticService.Version } }; Analytics.TrackEvent("Connect to session", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("ConnectToSession"); await _service.ConnectToServerAsync(_configService.Config.UserId); await _service.JoinToSesstionAsync(sessionId); diff --git a/MusicX/ViewModels/DownloaderViewModel.cs b/MusicX/ViewModels/DownloaderViewModel.cs index d6e1f64a..eb6f8158 100644 --- a/MusicX/ViewModels/DownloaderViewModel.cs +++ b/MusicX/ViewModels/DownloaderViewModel.cs @@ -12,6 +12,7 @@ using AsyncAwaitBestPractices.MVVM; using Microsoft.AppCenter.Analytics; using Microsoft.AppCenter.Crashes; +using Microsoft.Extensions.DependencyInjection; using MusicX.Core.Models; using MusicX.Core.Services; using MusicX.Helpers; @@ -165,6 +166,9 @@ private async void StartDownloading() {"Version", StaticService.Version } }; Analytics.TrackEvent("Download Track", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("DownloadTracks"); if (IsDownloading) return; diff --git a/MusicX/ViewModels/VKMixViewModel.cs b/MusicX/ViewModels/VKMixViewModel.cs index 9ee1776e..1c55ebc5 100644 --- a/MusicX/ViewModels/VKMixViewModel.cs +++ b/MusicX/ViewModels/VKMixViewModel.cs @@ -5,6 +5,7 @@ using AsyncAwaitBestPractices.MVVM; using Microsoft.AppCenter.Analytics; using Microsoft.AppCenter.Crashes; +using Microsoft.Extensions.DependencyInjection; using MusicX.Core.Exceptions.Boom; using MusicX.Core.Services; using MusicX.Helpers; @@ -39,6 +40,9 @@ public async Task OpenedMixesAsync() {"Version", StaticService.Version } }; Analytics.TrackEvent("Open VK Mix", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("OpenVkMix"); Logger.Info("Открытие страницы VK Mix"); var config = await ConfigService.GetConfig(); @@ -121,6 +125,9 @@ private async Task PlayPersonalMixAsync() {"Version", StaticService.Version } }; Analytics.TrackEvent("Play Personal Mix", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("PlayPersonalMix"); if (PlayingPersonalMix) { diff --git a/MusicX/Views/DownloadsView.xaml.cs b/MusicX/Views/DownloadsView.xaml.cs index 2ea5200d..15ad8d79 100644 --- a/MusicX/Views/DownloadsView.xaml.cs +++ b/MusicX/Views/DownloadsView.xaml.cs @@ -5,6 +5,7 @@ using Microsoft.AppCenter.Analytics; using Microsoft.Extensions.DependencyInjection; using MusicX.Controls; +using MusicX.Core.Services; using MusicX.Helpers; using MusicX.Services; using MusicX.ViewModels; @@ -37,6 +38,9 @@ private void DownloadsView_Loaded(object sender, RoutedEventArgs e) {"Version", StaticService.Version } }; Analytics.TrackEvent("OpenDownloads", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("OpenDownloads"); ContentGrid.Visibility = Visibility.Visible; } diff --git a/MusicX/Views/Modals/LyricsModal.xaml.cs b/MusicX/Views/Modals/LyricsModal.xaml.cs index 8f952012..92a242bf 100644 --- a/MusicX/Views/Modals/LyricsModal.xaml.cs +++ b/MusicX/Views/Modals/LyricsModal.xaml.cs @@ -20,10 +20,17 @@ public partial class LyricsModal : Page public LyricsModal() { this.Loaded += LyricsModal_Loaded; + Unloaded += LyricsModal_Unloaded; InitializeComponent(); } + private void LyricsModal_Unloaded(object sender, RoutedEventArgs e) + { + _viewModel.NextLineEvent -= _viewModel_NextLineEvent; + _viewModel.NewTrack -= _viewModel_NewTrack; + } + private void _viewModel_NextLineEvent(int msPoint) { LyricsControlView.ScrollToTime(msPoint); diff --git a/MusicX/Views/SettingsView.xaml.cs b/MusicX/Views/SettingsView.xaml.cs index 016b3760..5f0bc44a 100644 --- a/MusicX/Views/SettingsView.xaml.cs +++ b/MusicX/Views/SettingsView.xaml.cs @@ -64,6 +64,9 @@ private async void SettingsView_Loaded(object sender, RoutedEventArgs e) {"Version", StaticService.Version } }; Analytics.TrackEvent("OpenSettings", properties); + + var connectionService = StaticService.Container.GetRequiredService(); + connectionService.ReportMetric("OpenSettings"); this.config = await configService.GetConfig(); diff --git a/MusicX/Views/StartingWindow.xaml.cs b/MusicX/Views/StartingWindow.xaml.cs index 2b0443a2..634f62f1 100644 --- a/MusicX/Views/StartingWindow.xaml.cs +++ b/MusicX/Views/StartingWindow.xaml.cs @@ -141,6 +141,7 @@ await Task.Run(async () => }); collection.AddSingleton(); collection.AddSingleton(); + collection.AddSingleton(s => new BackendConnectionService(s.GetRequiredService(), StaticService.Version)); collection.AddSingleton(); collection.AddSingleton(); @@ -209,6 +210,17 @@ await container.GetRequiredService() { await vkService.SetTokenAsync(config.AccessToken); + + try + { + var connectionService = container.GetRequiredService(); + await connectionService.GetTokenAsync(config.UserId); + connectionService.ReportMetric("StartApp"); + } + catch (Exception exception) + { + logger.Error(exception); + } var rootWindow = ActivatorUtilities.CreateInstance(container); rootWindow.Show(); diff --git a/docker-compose.yml b/docker-compose.yml index e5128f4b..89e82933 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,7 @@ version: '3.9' volumes: traefik-certificates: + influxdb: services: app: @@ -18,6 +19,29 @@ services: - "traefik.http.services.app.loadbalancer.passhostheader=true" - "traefik.http.routers.app.middlewares=compresstraefik" - "traefik.http.middlewares.compresstraefik.compress=true" + + influxdb: + restart: always + image: influxdb:alpine + volumes: + - "./influxdb-config.yml:/etc/influxdb2/config.yml" + - "influxdb:/var/lib/influxdb2" + networks: + - minecraft_default + healthcheck: + test: "curl -f http://localhost:8086/ping" + interval: 3s + timeout: 10s + retries: 5 + labels: + - "traefik.enable=true" + - "traefik.http.routers.influxdb.rule=Host(`metrics-musicx.zznty.ru`)" + - "traefik.http.routers.influxdb.service=influxdb" + - "traefik.http.routers.influxdb.entrypoints=websecure" + - "traefik.http.services.influxdb.loadbalancer.server.port=8086" + - "traefik.http.routers.influxdb.tls=true" + - "traefik.http.routers.influxdb.tls.certresolver=myresolver" + - "traefik.http.services.influxdb.loadbalancer.passhostheader=true" site: build: diff --git a/influxdb-config.yml b/influxdb-config.yml new file mode 100644 index 00000000..b6f0edbe --- /dev/null +++ b/influxdb-config.yml @@ -0,0 +1,70 @@ +assets-path: "" +bolt-path: /var/lib/influxdb2/influxd.bolt +e2e-testing: false +engine-path: /var/lib/influxdb2/engine +feature-flags: {} +flux-log-enabled: false +hardening-enabled: false +http-bind-address: :8086 +http-idle-timeout: 3m0s +http-read-header-timeout: 10s +http-read-timeout: 0s +http-write-timeout: 0s +influxql-max-select-buckets: 0 +influxql-max-select-point: 0 +influxql-max-select-series: 0 +instance-id: "" +key-name: "" +log-level: info +metrics-disabled: false +nats-max-payload-bytes: 0 +nats-port: 4222 +no-tasks: false +pprof-disabled: false +query-concurrency: 1024 +query-initial-memory-bytes: 0 +query-max-memory-bytes: 0 +query-memory-bytes: 0 +query-queue-size: 1024 +reporting-disabled: false +secret-store: bolt +session-length: 60 +session-renew-disabled: false +sqlite-path: "" +storage-cache-max-memory-size: 1073741824 +storage-cache-snapshot-memory-size: 26214400 +storage-cache-snapshot-write-cold-duration: 10m0s +storage-compact-full-write-cold-duration: 4h0m0s +storage-compact-throughput-burst: 50331648 +storage-max-concurrent-compactions: 0 +storage-max-index-log-file-size: 1048576 +storage-no-validate-field-size: false +storage-retention-check-interval: 30m0s +storage-series-file-max-concurrent-snapshot-compactions: 0 +storage-series-id-set-cache-size: 0 +storage-shard-precreator-advance-period: 30m0s +storage-shard-precreator-check-interval: 10m0s +storage-tsm-use-madv-willneed: false +storage-validate-keys: false +storage-wal-fsync-delay: 0s +storage-wal-max-concurrent-writes: 0 +storage-wal-max-write-delay: 10m0s +storage-write-timeout: 10s +store: disk +testing-always-allow-setup: false +tls-cert: "" +tls-key: "" +tls-min-version: "1.2" +tls-strict-ciphers: false +tracing-type: "" +ui-disabled: false +vault-addr: "" +vault-cacert: "" +vault-capath: "" +vault-client-cert: "" +vault-client-key: "" +vault-client-timeout: 0s +vault-max-retries: 0 +vault-skip-verify: false +vault-tls-server-name: "" +vault-token: "" \ No newline at end of file