1
0
mirror of https://github.com/bitwarden/mobile.git synced 2024-11-25 12:05:59 +01:00

BEEEP: Abstract and Centralize Logging (#1663)

* Abstracted App Center Logging into its own component, so that we can have it centralized in one place and we avoid checking for FDroid on all the places we want to use it

* Implemented the new logger where Crashes.TrackError was being used except on some specific cases

* Improved logging, added a debug logger and removed AppCenter to be used on DEBUG
This commit is contained in:
Federico Maccaroni 2022-03-02 14:15:16 -03:00 committed by GitHub
parent 34d0ecf64b
commit db7ca3b93e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 328 additions and 147 deletions

View File

@ -1,4 +1,7 @@
using Android; using System;
using System.Collections.Generic;
using System.Linq;
using Android;
using Android.App; using Android.App;
using Android.Content; using Android.Content;
using Android.OS; using Android.OS;
@ -9,12 +12,6 @@ using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Utilities; using Bit.Core.Utilities;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
using System;
using System.Collections.Generic;
using System.Linq;
namespace Bit.Droid.Autofill namespace Bit.Droid.Autofill
{ {
@ -28,6 +25,7 @@ namespace Bit.Droid.Autofill
private IVaultTimeoutService _vaultTimeoutService; private IVaultTimeoutService _vaultTimeoutService;
private IPolicyService _policyService; private IPolicyService _policyService;
private IStateService _stateService; private IStateService _stateService;
private LazyResolve<ILogger> _logger = new LazyResolve<ILogger>("logger");
public async override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal, public async override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal,
FillCallback callback) FillCallback callback)
@ -84,9 +82,7 @@ namespace Bit.Droid.Autofill
} }
catch (Exception e) catch (Exception e)
{ {
#if !FDROID _logger.Value.Exception(e);
Crashes.TrackError(e);
#endif
} }
} }
@ -160,9 +156,7 @@ namespace Bit.Droid.Autofill
} }
catch (Exception e) catch (Exception e)
{ {
#if !FDROID _logger.Value.Exception(e);
Crashes.TrackError(e);
#endif
} }
} }
} }

View File

@ -69,7 +69,7 @@ namespace Bit.Droid
Window.AddFlags(Android.Views.WindowManagerFlags.Secure); Window.AddFlags(Android.Views.WindowManagerFlags.Secure);
} }
#if !FDROID #if !DEBUG && !FDROID
var appCenterHelper = new AppCenterHelper(_appIdService, _stateService); var appCenterHelper = new AppCenterHelper(_appIdService, _stateService);
var appCenterTask = appCenterHelper.InitAsync(); var appCenterTask = appCenterHelper.InitAsync();
#endif #endif

View File

@ -53,7 +53,8 @@ namespace Bit.Droid
ServiceContainer.Resolve<IApiService>("apiService"), ServiceContainer.Resolve<IApiService>("apiService"),
ServiceContainer.Resolve<IMessagingService>("messagingService"), ServiceContainer.Resolve<IMessagingService>("messagingService"),
ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"), ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"),
ServiceContainer.Resolve<IDeviceActionService>("deviceActionService")); ServiceContainer.Resolve<IDeviceActionService>("deviceActionService"),
ServiceContainer.Resolve<ILogger>("logger"));
ServiceContainer.Register<IDeleteAccountActionFlowExecutioner>("deleteAccountActionFlowExecutioner", deleteAccountActionFlowExecutioner); ServiceContainer.Register<IDeleteAccountActionFlowExecutioner>("deleteAccountActionFlowExecutioner", deleteAccountActionFlowExecutioner);
var verificationActionsFlowHelper = new VerificationActionsFlowHelper( var verificationActionsFlowHelper = new VerificationActionsFlowHelper(
@ -87,7 +88,14 @@ namespace Bit.Droid
private void RegisterLocalServices() private void RegisterLocalServices()
{ {
ServiceContainer.Register<ILogService>("logService", new AndroidLogService()); ServiceContainer.Register<INativeLogService>("nativeLogService", new AndroidLogService());
#if FDROID
ServiceContainer.Register<ILogger>("logger", new StubLogger());
#elif DEBUG
ServiceContainer.Register<ILogger>("logger", DebugLogger.Instance);
#else
ServiceContainer.Register<ILogger>("logger", Logger.Instance);
#endif
// Note: This might cause a race condition. Investigate more. // Note: This might cause a race condition. Investigate more.
Task.Run(() => Task.Run(() =>

View File

@ -3,7 +3,7 @@ using System;
namespace Bit.Core.Services namespace Bit.Core.Services
{ {
public class AndroidLogService : ILogService public class AndroidLogService : INativeLogService
{ {
private static readonly string _tag = "BITWARDEN"; private static readonly string _tag = "BITWARDEN";

View File

@ -1,9 +1,8 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
#if !FDROID using Bit.Core.Abstractions;
using Microsoft.AppCenter.Crashes; using Bit.Core.Utilities;
#endif
using Xamarin.CommunityToolkit.ObjectModel; using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms; using Xamarin.Forms;
@ -23,14 +22,14 @@ namespace Bit.App.Controls
set => SetValue(MainFabProperty, value); set => SetValue(MainFabProperty, value);
} }
readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>("logger");
public AccountSwitchingOverlayView() public AccountSwitchingOverlayView()
{ {
InitializeComponent(); InitializeComponent();
ToggleVisibililtyCommand = new AsyncCommand(ToggleVisibilityAsync, ToggleVisibililtyCommand = new AsyncCommand(ToggleVisibilityAsync,
#if !FDROID onException: ex => _logger.Value.Exception(ex),
onException: ex => Crashes.TrackError(ex),
#endif
allowsMultipleExecutions: false); allowsMultipleExecutions: false);
} }
@ -110,9 +109,7 @@ namespace Bit.App.Controls
} }
catch (Exception ex) catch (Exception ex)
{ {
#if !FDROID _logger.Value.Exception(ex);
Crashes.TrackError(ex);
#endif
} }
} }
@ -133,9 +130,7 @@ namespace Bit.App.Controls
} }
catch (Exception ex) catch (Exception ex)
{ {
#if !FDROID _logger.Value.Exception(ex);
Crashes.TrackError(ex);
#endif
} }
} }
} }

View File

@ -4,7 +4,6 @@ using System.Windows.Input;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Models.View; using Bit.Core.Models.View;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Microsoft.AppCenter.Crashes;
using Xamarin.CommunityToolkit.ObjectModel; using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms; using Xamarin.Forms;
@ -16,15 +15,14 @@ namespace Bit.App.Controls
private readonly IMessagingService _messagingService; private readonly IMessagingService _messagingService;
public AccountSwitchingOverlayViewModel(IStateService stateService, public AccountSwitchingOverlayViewModel(IStateService stateService,
IMessagingService messagingService) IMessagingService messagingService,
ILogger logger)
{ {
_stateService = stateService; _stateService = stateService;
_messagingService = messagingService; _messagingService = messagingService;
SelectAccountCommand = new AsyncCommand<AccountViewCellViewModel>(SelectAccountAsync, SelectAccountCommand = new AsyncCommand<AccountViewCellViewModel>(SelectAccountAsync,
#if !FDROID onException: ex => logger.Exception(ex),
onException: ex => Crashes.TrackError(ex),
#endif
allowsMultipleExecutions: false); allowsMultipleExecutions: false);
} }

View File

@ -5,9 +5,6 @@ using Bit.App.Utilities;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Exceptions; using Bit.Core.Exceptions;
using Bit.Core.Utilities; using Bit.Core.Utilities;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -15,11 +12,13 @@ namespace Bit.App.Pages
{ {
readonly IPlatformUtilsService _platformUtilsService; readonly IPlatformUtilsService _platformUtilsService;
readonly IVerificationActionsFlowHelper _verificationActionsFlowHelper; readonly IVerificationActionsFlowHelper _verificationActionsFlowHelper;
readonly ILogger _logger;
public DeleteAccountViewModel() public DeleteAccountViewModel()
{ {
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"); _platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
_verificationActionsFlowHelper = ServiceContainer.Resolve<IVerificationActionsFlowHelper>("verificationActionsFlowHelper"); _verificationActionsFlowHelper = ServiceContainer.Resolve<IVerificationActionsFlowHelper>("verificationActionsFlowHelper");
_logger = ServiceContainer.Resolve<ILogger>("logger");
PageTitle = AppResources.DeleteAccount; PageTitle = AppResources.DeleteAccount;
} }
@ -44,9 +43,7 @@ namespace Bit.App.Pages
} }
catch (System.Exception ex) catch (System.Exception ex)
{ {
#if !FDROID _logger.Exception(ex);
Crashes.TrackError(ex);
#endif
await _platformUtilsService.ShowDialogAsync(AppResources.AnErrorHasOccurred); await _platformUtilsService.ShowDialogAsync(AppResources.AnErrorHasOccurred);
} }
} }
@ -60,16 +57,19 @@ namespace Bit.App.Pages
readonly IMessagingService _messagingService; readonly IMessagingService _messagingService;
readonly IPlatformUtilsService _platformUtilsService; readonly IPlatformUtilsService _platformUtilsService;
readonly IDeviceActionService _deviceActionService; readonly IDeviceActionService _deviceActionService;
readonly ILogger _logger;
public DeleteAccountActionFlowExecutioner(IApiService apiService, public DeleteAccountActionFlowExecutioner(IApiService apiService,
IMessagingService messagingService, IMessagingService messagingService,
IPlatformUtilsService platformUtilsService, IPlatformUtilsService platformUtilsService,
IDeviceActionService deviceActionService) IDeviceActionService deviceActionService,
ILogger logger)
{ {
_apiService = apiService; _apiService = apiService;
_messagingService = messagingService; _messagingService = messagingService;
_platformUtilsService = platformUtilsService; _platformUtilsService = platformUtilsService;
_deviceActionService = deviceActionService; _deviceActionService = deviceActionService;
_logger = logger;
} }
public async Task Execute(IActionFlowParmeters parameters) public async Task Execute(IActionFlowParmeters parameters)
@ -102,9 +102,7 @@ namespace Bit.App.Pages
catch (System.Exception ex) catch (System.Exception ex)
{ {
await _deviceActionService.HideLoadingAsync(); await _deviceActionService.HideLoadingAsync();
#if !FDROID _logger.Exception(ex);
Crashes.TrackError(ex);
#endif
await _platformUtilsService.ShowDialogAsync(AppResources.AnErrorHasOccurred); await _platformUtilsService.ShowDialogAsync(AppResources.AnErrorHasOccurred);
} }
} }

View File

@ -17,10 +17,11 @@ namespace Bit.App.Pages
{ {
_stateService = ServiceContainer.Resolve<IStateService>("stateService"); _stateService = ServiceContainer.Resolve<IStateService>("stateService");
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService"); _messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
var logger = ServiceContainer.Resolve<ILogger>("logger");
PageTitle = AppResources.Bitwarden; PageTitle = AppResources.Bitwarden;
AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService) AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, logger)
{ {
AllowActiveAccountSelection = true AllowActiveAccountSelection = true
}; };

View File

@ -11,9 +11,6 @@ using Bit.Core.Models.Domain;
using Bit.Core.Models.Request; using Bit.Core.Models.Request;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Xamarin.Forms; using Xamarin.Forms;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -29,6 +26,7 @@ namespace Bit.App.Pages
private readonly IStateService _stateService; private readonly IStateService _stateService;
private readonly IBiometricService _biometricService; private readonly IBiometricService _biometricService;
private readonly IKeyConnectorService _keyConnectorService; private readonly IKeyConnectorService _keyConnectorService;
private readonly ILogger _logger;
private string _email; private string _email;
private bool _showPassword; private bool _showPassword;
@ -55,12 +53,13 @@ namespace Bit.App.Pages
_stateService = ServiceContainer.Resolve<IStateService>("stateService"); _stateService = ServiceContainer.Resolve<IStateService>("stateService");
_biometricService = ServiceContainer.Resolve<IBiometricService>("biometricService"); _biometricService = ServiceContainer.Resolve<IBiometricService>("biometricService");
_keyConnectorService = ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService"); _keyConnectorService = ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService");
_logger = ServiceContainer.Resolve<ILogger>("logger");
PageTitle = AppResources.VerifyMasterPassword; PageTitle = AppResources.VerifyMasterPassword;
TogglePasswordCommand = new Command(TogglePassword); TogglePasswordCommand = new Command(TogglePassword);
SubmitCommand = new Command(async () => await SubmitAsync()); SubmitCommand = new Command(async () => await SubmitAsync());
AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService) AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger)
{ {
AllowAddAccountRow = true, AllowAddAccountRow = true,
AllowActiveAccountSelection = true AllowActiveAccountSelection = true
@ -151,9 +150,7 @@ namespace Bit.App.Pages
if (string.IsNullOrWhiteSpace(_email)) if (string.IsNullOrWhiteSpace(_email))
{ {
await _vaultTimeoutService.LogOutAsync(); await _vaultTimeoutService.LogOutAsync();
#if !FDROID _logger.Exception(new NullReferenceException("Email not found in storage"));
Crashes.TrackError(new NullReferenceException("Email not found in storage"));
#endif
return; return;
} }
var webVault = _environmentService.GetWebVaultUrl(true); var webVault = _environmentService.GetWebVaultUrl(true);

View File

@ -8,9 +8,6 @@ using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Exceptions; using Bit.Core.Exceptions;
using Bit.Core.Utilities; using Bit.Core.Utilities;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
using Xamarin.Forms; using Xamarin.Forms;
namespace Bit.App.Pages namespace Bit.App.Pages
@ -25,6 +22,7 @@ namespace Bit.App.Pages
private readonly IEnvironmentService _environmentService; private readonly IEnvironmentService _environmentService;
private readonly II18nService _i18nService; private readonly II18nService _i18nService;
private readonly IMessagingService _messagingService; private readonly IMessagingService _messagingService;
private readonly ILogger _logger;
private bool _showPassword; private bool _showPassword;
private bool _showCancelButton; private bool _showCancelButton;
@ -41,12 +39,13 @@ namespace Bit.App.Pages
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService"); _environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
_i18nService = ServiceContainer.Resolve<II18nService>("i18nService"); _i18nService = ServiceContainer.Resolve<II18nService>("i18nService");
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService"); _messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_logger = ServiceContainer.Resolve<ILogger>("logger");
PageTitle = AppResources.Bitwarden; PageTitle = AppResources.Bitwarden;
TogglePasswordCommand = new Command(TogglePassword); TogglePasswordCommand = new Command(TogglePassword);
LogInCommand = new Command(async () => await LogInAsync()); LogInCommand = new Command(async () => await LogInAsync());
AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService) AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger)
{ {
AllowAddAccountRow = true, AllowAddAccountRow = true,
AllowActiveAccountSelection = true AllowActiveAccountSelection = true
@ -221,9 +220,7 @@ namespace Bit.App.Pages
} }
catch (Exception e) catch (Exception e)
{ {
#if !FDROID _logger.Exception(e);
Crashes.TrackError(e);
#endif
} }
} }

View File

@ -1,19 +1,16 @@
using System; using System;
using System.Threading.Tasks;
using System.Windows.Input;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Resources; using Bit.App.Resources;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using System.Threading.Tasks;
using Bit.Core.Exceptions;
using Xamarin.Forms;
using Xamarin.CommunityToolkit.ObjectModel;
using System.Windows.Input;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.Core; using Bit.Core;
using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
#if !FDROID using Bit.Core.Exceptions;
using Microsoft.AppCenter.Crashes; using Bit.Core.Utilities;
#endif using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -24,6 +21,7 @@ namespace Bit.App.Pages
private readonly IUserVerificationService _userVerificationService; private readonly IUserVerificationService _userVerificationService;
private readonly IApiService _apiService; private readonly IApiService _apiService;
private readonly IVerificationActionsFlowHelper _verificationActionsFlowHelper; private readonly IVerificationActionsFlowHelper _verificationActionsFlowHelper;
private readonly ILogger _logger;
private bool _showPassword; private bool _showPassword;
private string _secret, _mainActionText, _sendCodeStatus; private string _secret, _mainActionText, _sendCodeStatus;
@ -35,6 +33,7 @@ namespace Bit.App.Pages
_userVerificationService = ServiceContainer.Resolve<IUserVerificationService>("userVerificationService"); _userVerificationService = ServiceContainer.Resolve<IUserVerificationService>("userVerificationService");
_apiService = ServiceContainer.Resolve<IApiService>("apiService"); _apiService = ServiceContainer.Resolve<IApiService>("apiService");
_verificationActionsFlowHelper = ServiceContainer.Resolve<IVerificationActionsFlowHelper>("verificationActionsFlowHelper"); _verificationActionsFlowHelper = ServiceContainer.Resolve<IVerificationActionsFlowHelper>("verificationActionsFlowHelper");
_logger = ServiceContainer.Resolve<ILogger>("logger");
PageTitle = AppResources.VerificationCode; PageTitle = AppResources.VerificationCode;
@ -118,9 +117,7 @@ namespace Bit.App.Pages
} }
catch (Exception ex) catch (Exception ex)
{ {
#if !FDROID _logger.Exception(ex);
Crashes.TrackError(ex);
#endif
await _deviceActionService.HideLoadingAsync(); await _deviceActionService.HideLoadingAsync();
SendCodeStatus = AppResources.AnErrorOccurredWhileSendingAVerificationCodeToYourEmailPleaseTryAgain; SendCodeStatus = AppResources.AnErrorOccurredWhileSendingAVerificationCodeToYourEmailPleaseTryAgain;
} }
@ -171,9 +168,7 @@ namespace Bit.App.Pages
} }
catch (Exception ex) catch (Exception ex)
{ {
#if !FDROID _logger.Exception(ex);
Crashes.TrackError(ex);
#endif
await _deviceActionService.HideLoadingAsync(); await _deviceActionService.HideLoadingAsync();
} }
} }

View File

@ -4,9 +4,6 @@ using Bit.App.Resources;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Models.Domain; using Bit.Core.Models.Domain;
using Bit.Core.Utilities; using Bit.Core.Utilities;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
using Xamarin.Forms; using Xamarin.Forms;
namespace Bit.App.Pages namespace Bit.App.Pages
@ -16,6 +13,7 @@ namespace Bit.App.Pages
private readonly IPlatformUtilsService _platformUtilsService; private readonly IPlatformUtilsService _platformUtilsService;
private readonly IPasswordGenerationService _passwordGenerationService; private readonly IPasswordGenerationService _passwordGenerationService;
private readonly IClipboardService _clipboardService; private readonly IClipboardService _clipboardService;
private readonly ILogger _logger;
private bool _showNoData; private bool _showNoData;
@ -24,6 +22,7 @@ namespace Bit.App.Pages
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"); _platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
_passwordGenerationService = ServiceContainer.Resolve<IPasswordGenerationService>("passwordGenerationService"); _passwordGenerationService = ServiceContainer.Resolve<IPasswordGenerationService>("passwordGenerationService");
_clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService"); _clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
_logger = ServiceContainer.Resolve<ILogger>("logger");
PageTitle = AppResources.PasswordHistory; PageTitle = AppResources.PasswordHistory;
History = new ExtendedObservableCollection<GeneratedPasswordHistory>(); History = new ExtendedObservableCollection<GeneratedPasswordHistory>();
@ -70,9 +69,7 @@ namespace Bit.App.Pages
} }
catch (System.Exception ex) catch (System.Exception ex)
{ {
#if !FDROID _logger.Exception(ex);
Crashes.TrackError(ex);
#endif
} }
} }
} }

View File

@ -7,9 +7,6 @@ using Bit.App.Utilities;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Utilities; using Bit.Core.Utilities;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.PlatformConfiguration; using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific; using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
@ -21,6 +18,7 @@ namespace Bit.App.Pages
{ {
private readonly IBroadcasterService _broadcasterService; private readonly IBroadcasterService _broadcasterService;
private readonly IVaultTimeoutService _vaultTimeoutService; private readonly IVaultTimeoutService _vaultTimeoutService;
private readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>("logger");
private AppOptions _appOptions; private AppOptions _appOptions;
private SendAddEditPageViewModel _vm; private SendAddEditPageViewModel _vm;
@ -132,9 +130,7 @@ namespace Bit.App.Pages
} }
catch (Exception ex) catch (Exception ex)
{ {
#if !FDROID _logger.Value.Exception(ex);
Crashes.TrackError(ex);
#endif
await CloseAsync(); await CloseAsync();
} }
} }

View File

@ -10,9 +10,6 @@ using Bit.Core.Enums;
using Bit.Core.Exceptions; using Bit.Core.Exceptions;
using Bit.Core.Models.View; using Bit.Core.Models.View;
using Bit.Core.Utilities; using Bit.Core.Utilities;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
using Xamarin.Essentials; using Xamarin.Essentials;
using Xamarin.Forms; using Xamarin.Forms;
@ -25,6 +22,7 @@ namespace Bit.App.Pages
private readonly IMessagingService _messagingService; private readonly IMessagingService _messagingService;
private readonly IStateService _stateService; private readonly IStateService _stateService;
private readonly ISendService _sendService; private readonly ISendService _sendService;
private readonly ILogger _logger;
private bool _sendEnabled; private bool _sendEnabled;
private bool _canAccessPremium; private bool _canAccessPremium;
private bool _emailVerified; private bool _emailVerified;
@ -58,6 +56,8 @@ namespace Bit.App.Pages
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService"); _messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_stateService = ServiceContainer.Resolve<IStateService>("stateService"); _stateService = ServiceContainer.Resolve<IStateService>("stateService");
_sendService = ServiceContainer.Resolve<ISendService>("sendService"); _sendService = ServiceContainer.Resolve<ISendService>("sendService");
_logger = ServiceContainer.Resolve<ILogger>("logger");
TogglePasswordCommand = new Command(TogglePassword); TogglePasswordCommand = new Command(TogglePassword);
TypeOptions = new List<KeyValuePair<string, SendType>> TypeOptions = new List<KeyValuePair<string, SendType>>
@ -455,9 +455,7 @@ namespace Bit.App.Pages
catch (Exception ex) catch (Exception ex)
{ {
await _deviceActionService.HideLoadingAsync(); await _deviceActionService.HideLoadingAsync();
#if !FDROID _logger.Exception(ex);
Crashes.TrackError(ex);
#endif
await _platformUtilsService.ShowDialogAsync(AppResources.AnErrorHasOccurred); await _platformUtilsService.ShowDialogAsync(AppResources.AnErrorHasOccurred);
} }
return false; return false;

View File

@ -1,17 +1,14 @@
using System; using System;
using Bit.App.Abstractions;
using Bit.App.Resources;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.App.Abstractions;
using Bit.App.Resources;
using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Exceptions; using Bit.Core.Exceptions;
using Bit.Core.Utilities;
using Bit.Core; using Bit.Core;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
using Xamarin.Forms; using Xamarin.Forms;
namespace Bit.App.Pages namespace Bit.App.Pages
@ -26,6 +23,7 @@ namespace Bit.App.Pages
private readonly IKeyConnectorService _keyConnectorService; private readonly IKeyConnectorService _keyConnectorService;
private readonly IUserVerificationService _userVerificationService; private readonly IUserVerificationService _userVerificationService;
private readonly IApiService _apiService; private readonly IApiService _apiService;
private readonly ILogger _logger;
private int _fileFormatSelectedIndex; private int _fileFormatSelectedIndex;
private string _exportWarningMessage; private string _exportWarningMessage;
@ -48,6 +46,7 @@ namespace Bit.App.Pages
_keyConnectorService = ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService"); _keyConnectorService = ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService");
_userVerificationService = ServiceContainer.Resolve<IUserVerificationService>("userVerificationService"); _userVerificationService = ServiceContainer.Resolve<IUserVerificationService>("userVerificationService");
_apiService = ServiceContainer.Resolve<IApiService>("apiService"); _apiService = ServiceContainer.Resolve<IApiService>("apiService");
_logger = ServiceContainer.Resolve<ILogger>("logger");
PageTitle = AppResources.ExportVault; PageTitle = AppResources.ExportVault;
TogglePasswordCommand = new Command(TogglePassword); TogglePasswordCommand = new Command(TogglePassword);
@ -189,9 +188,7 @@ namespace Bit.App.Pages
ClearResult(); ClearResult();
await _platformUtilsService.ShowDialogAsync(_i18nService.T("ExportVaultFailure")); await _platformUtilsService.ShowDialogAsync(_i18nService.T("ExportVaultFailure"));
System.Diagnostics.Debug.WriteLine(">>> {0}: {1}", ex.GetType(), ex.StackTrace); System.Diagnostics.Debug.WriteLine(">>> {0}: {1}", ex.GetType(), ex.StackTrace);
#if !FDROID _logger.Exception(ex);
Crashes.TrackError(ex);
#endif
} }
} }

View File

@ -1,21 +1,18 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Controls;
using Bit.App.Models; using Bit.App.Models;
using Bit.App.Resources; using Bit.App.Resources;
using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Exceptions; using Bit.Core.Exceptions;
using Bit.Core.Models.View; using Bit.Core.Models.View;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Bit.App.Controls;
using Bit.Core;
using Xamarin.Forms; using Xamarin.Forms;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -32,6 +29,8 @@ namespace Bit.App.Pages
private readonly IMessagingService _messagingService; private readonly IMessagingService _messagingService;
private readonly IEventService _eventService; private readonly IEventService _eventService;
private readonly IPolicyService _policyService; private readonly IPolicyService _policyService;
private readonly ILogger _logger;
private CipherView _cipher; private CipherView _cipher;
private bool _showNotesSeparator; private bool _showNotesSeparator;
private bool _showPassword; private bool _showPassword;
@ -82,6 +81,8 @@ namespace Bit.App.Pages
_collectionService = ServiceContainer.Resolve<ICollectionService>("collectionService"); _collectionService = ServiceContainer.Resolve<ICollectionService>("collectionService");
_eventService = ServiceContainer.Resolve<IEventService>("eventService"); _eventService = ServiceContainer.Resolve<IEventService>("eventService");
_policyService = ServiceContainer.Resolve<IPolicyService>("policyService"); _policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
_logger = ServiceContainer.Resolve<ILogger>("logger");
GeneratePasswordCommand = new Command(GeneratePassword); GeneratePasswordCommand = new Command(GeneratePassword);
TogglePasswordCommand = new Command(TogglePassword); TogglePasswordCommand = new Command(TogglePassword);
ToggleCardNumberCommand = new Command(ToggleCardNumber); ToggleCardNumberCommand = new Command(ToggleCardNumber);
@ -538,9 +539,7 @@ namespace Bit.App.Pages
} }
catch(Exception genex) catch(Exception genex)
{ {
#if !FDROID _logger.Exception(genex);
Crashes.TrackError(genex);
#endif
await _deviceActionService.HideLoadingAsync(); await _deviceActionService.HideLoadingAsync();
} }
return false; return false;

View File

@ -45,6 +45,7 @@ namespace Bit.App.Pages
private readonly IMessagingService _messagingService; private readonly IMessagingService _messagingService;
private readonly IStateService _stateService; private readonly IStateService _stateService;
private readonly IPasswordRepromptService _passwordRepromptService; private readonly IPasswordRepromptService _passwordRepromptService;
private readonly ILogger _logger;
public GroupingsPageViewModel() public GroupingsPageViewModel()
{ {
@ -58,6 +59,7 @@ namespace Bit.App.Pages
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService"); _messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_stateService = ServiceContainer.Resolve<IStateService>("stateService"); _stateService = ServiceContainer.Resolve<IStateService>("stateService");
_passwordRepromptService = ServiceContainer.Resolve<IPasswordRepromptService>("passwordRepromptService"); _passwordRepromptService = ServiceContainer.Resolve<IPasswordRepromptService>("passwordRepromptService");
_logger = ServiceContainer.Resolve<ILogger>("logger");
Loading = true; Loading = true;
PageTitle = AppResources.MyVault; PageTitle = AppResources.MyVault;
@ -69,7 +71,7 @@ namespace Bit.App.Pages
}); });
CipherOptionsCommand = new Command<CipherView>(CipherOptionsAsync); CipherOptionsCommand = new Command<CipherView>(CipherOptionsAsync);
AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService) AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger)
{ {
AllowAddAccountRow = true AllowAddAccountRow = true
}; };

View File

@ -2,7 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AppCenter.Crashes; using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using Xamarin.Forms; using Xamarin.Forms;
namespace Bit.App.Pages namespace Bit.App.Pages
@ -14,6 +15,8 @@ namespace Bit.App.Pages
private CancellationTokenSource _autofocusCts; private CancellationTokenSource _autofocusCts;
private Task _continuousAutofocusTask; private Task _continuousAutofocusTask;
private readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>("logger");
public ScanPage(Action<string> callback) public ScanPage(Action<string> callback)
{ {
_callback = callback; _callback = callback;
@ -61,9 +64,7 @@ namespace Bit.App.Pages
catch (TaskCanceledException) { } catch (TaskCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
#if !FDROID _logger.Value.Exception(ex);
Crashes.TrackError(ex);
#endif
} }
}, autofocusCts.Token); }, autofocusCts.Token);
} }

View File

@ -1,14 +1,12 @@
using System; using System;
using System.Linq;
using System.Threading.Tasks;
using Bit.App.Models; using Bit.App.Models;
using Bit.App.Styles; using Bit.App.Styles;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Xamarin.Forms; using Xamarin.Forms;
using System.Linq;
using System.Threading.Tasks;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
namespace Bit.App.Utilities namespace Bit.App.Utilities
{ {
@ -76,9 +74,7 @@ namespace Bit.App.Utilities
} }
catch (Exception ex) catch (Exception ex)
{ {
#if !FDROID LoggerHelper.LogEvenIfCantBeResolved(ex);
Crashes.TrackError(ex);
#endif
} }
} }
@ -168,9 +164,7 @@ namespace Bit.App.Utilities
} }
catch (Exception ex) catch (Exception ex)
{ {
#if !FDROID LoggerHelper.LogEvenIfCantBeResolved(ex);
Crashes.TrackError(ex);
#endif
} }
} }
} }

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Bit.Core.Abstractions
{
public interface ILogger
{
/// <summary>
/// Logs something that is not in itself an exception, e.g. a wrong flow or value that needs to be reported
/// and looked into.
/// </summary>
/// <param name="message">A text to be used as the issue's title</param>
/// <param name="extraData">Additional data</param>
void Error(string message,
IDictionary<string, string> extraData = null,
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0);
/// <summary>
/// Logs an exception
/// </summary>
void Exception(Exception ex);
}
}

View File

@ -1,6 +1,6 @@
namespace Bit.Core.Abstractions namespace Bit.Core.Abstractions
{ {
public interface ILogService public interface INativeLogService
{ {
void Debug(string message); void Debug(string message);
void Error(string message); void Error(string message);

View File

@ -15,6 +15,8 @@
<ItemGroup> <ItemGroup>
<None Remove="Resources\eff_long_word_list.txt" /> <None Remove="Resources\eff_long_word_list.txt" />
<None Remove="Resources\public_suffix_list.dat" /> <None Remove="Resources\public_suffix_list.dat" />
<None Remove="Microsoft.AppCenter.Crashes" />
<None Remove="Services\Logging\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -31,4 +33,7 @@
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="4.4.0" /> <PackageReference Include="Microsoft.AppCenter.Crashes" Version="4.4.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Services\Logging\" />
</ItemGroup>
</Project> </Project>

View File

@ -3,7 +3,7 @@ using System;
namespace Bit.Core.Services namespace Bit.Core.Services
{ {
public class ConsoleLogService : ILogService public class ConsoleLogService : INativeLogService
{ {
public void Debug(string message) public void Debug(string message)
{ {

View File

@ -0,0 +1,50 @@
#if !FDROID
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using Bit.Core.Abstractions;
namespace Bit.Core.Services
{
public class DebugLogger : ILogger
{
static ILogger _instance;
public static ILogger Instance
{
get
{
if (_instance is null)
{
_instance = new DebugLogger();
}
return _instance;
}
}
protected DebugLogger()
{
}
public void Error(string message, IDictionary<string, string> extraData = null, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
var classAndMethod = $"{Path.GetFileNameWithoutExtension(sourceFilePath)}.{memberName}";
var filePathAndLineNumber = $"{Path.GetFileName(sourceFilePath)}:{sourceLineNumber}";
if (string.IsNullOrEmpty(message))
{
Debug.WriteLine($"Error found in: {classAndMethod})");
return;
}
Debug.WriteLine($"File: {filePathAndLineNumber}");
Debug.WriteLine($"Method: {memberName}");
Debug.WriteLine($"Message: {message}");
}
public void Exception(Exception ex) => Debug.WriteLine(ex);
}
}
#endif

View File

@ -0,0 +1,71 @@
#if !FDROID
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using Bit.Core.Abstractions;
using Microsoft.AppCenter.Crashes;
namespace Bit.Core.Services
{
public class Logger : ILogger
{
static ILogger _instance;
public static ILogger Instance
{
get
{
if (_instance is null)
{
_instance = new Logger();
}
return _instance;
}
}
protected Logger()
{
}
public void Error(string message,
IDictionary<string, string> extraData = null,
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0)
{
var classAndMethod = $"{Path.GetFileNameWithoutExtension(sourceFilePath)}.{memberName}";
var filePathAndLineNumber = $"{Path.GetFileName(sourceFilePath)}:{sourceLineNumber}";
var properties = new Dictionary<string, string>
{
["File"] = filePathAndLineNumber,
["Method"] = memberName
};
var exception = new Exception(message ?? $"Error found in: {classAndMethod}");
if (extraData == null)
{
Crashes.TrackError(exception, properties);
}
else
{
var data = properties.Concat(extraData).ToDictionary(x => x.Key, x => x.Value);
Crashes.TrackError(exception, data);
}
}
public void Exception(Exception exception)
{
try
{
Crashes.TrackError(exception);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
}
#endif

View File

@ -0,0 +1,33 @@
using System;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
namespace Bit.Core.Services
{
public static class LoggerHelper
{
/// <summary>
/// Logs the exception even if the service can't be resolved.
/// Useful when we need to log an exception in situations where the ServiceContainer may not be initialized.
/// </summary>
/// <param name="ex"></param>
public static void LogEvenIfCantBeResolved(Exception ex)
{
if (ServiceContainer.Resolve<ILogger>("logger", true) is ILogger logger)
{
logger.Exception(ex);
}
else
{
#if !FDROID
// just in case the caller throws the exception in a moment where the logger can't be resolved
// we need to track the error as well
Crashes.TrackError(ex);
#endif
}
}
}
}

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Bit.Core.Abstractions;
namespace Bit.Core.Services
{
/// <summary>
/// A logger that does nothing, this is useful on e.g. FDroid, where we cannot use logging through AppCenter
/// </summary>
public class StubLogger : ILogger
{
public void Error(string message, IDictionary<string, string> extraData = null, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
}
public void Exception(Exception ex)
{
}
}
}

View File

@ -1,8 +1,6 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
#if !FDROID using Bit.Core.Services;
using Microsoft.AppCenter.Crashes;
#endif
namespace Bit.Core.Utilities namespace Bit.Core.Utilities
{ {
@ -22,9 +20,7 @@ namespace Bit.Core.Utilities
} }
catch (Exception ex) catch (Exception ex)
{ {
#if !FDROID LoggerHelper.LogEvenIfCantBeResolved(ex);
Crashes.TrackError(ex);
#endif
onException?.Invoke(ex); onException?.Invoke(ex);
} }
} }

View File

@ -27,17 +27,28 @@ namespace Bit.iOS.Core.Utilities
public static void RegisterAppCenter() public static void RegisterAppCenter()
{ {
#if !DEBUG
var appCenterHelper = new AppCenterHelper( var appCenterHelper = new AppCenterHelper(
ServiceContainer.Resolve<IAppIdService>("appIdService"), ServiceContainer.Resolve<IAppIdService>("appIdService"),
ServiceContainer.Resolve<IStateService>("stateService")); ServiceContainer.Resolve<IStateService>("stateService"));
var appCenterTask = appCenterHelper.InitAsync(); var appCenterTask = appCenterHelper.InitAsync();
#endif
} }
public static void RegisterLocalServices() public static void RegisterLocalServices()
{ {
if (ServiceContainer.Resolve<ILogService>("logService", true) == null) if (ServiceContainer.Resolve<INativeLogService>("nativeLogService", true) == null)
{ {
ServiceContainer.Register<ILogService>("logService", new ConsoleLogService()); ServiceContainer.Register<INativeLogService>("nativeLogService", new ConsoleLogService());
}
if (ServiceContainer.Resolve<ILogger>("logger", true) == null)
{
#if DEBUG
ServiceContainer.Register<ILogger>("logger", DebugLogger.Instance);
#else
ServiceContainer.Register<ILogger>("logger", Logger.Instance);
#endif
} }
var preferencesStorage = new PreferencesStorageService(AppGroupId); var preferencesStorage = new PreferencesStorageService(AppGroupId);
@ -156,7 +167,8 @@ namespace Bit.iOS.Core.Utilities
ServiceContainer.Resolve<IApiService>("apiService"), ServiceContainer.Resolve<IApiService>("apiService"),
ServiceContainer.Resolve<IMessagingService>("messagingService"), ServiceContainer.Resolve<IMessagingService>("messagingService"),
ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"), ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"),
ServiceContainer.Resolve<IDeviceActionService>("deviceActionService")); ServiceContainer.Resolve<IDeviceActionService>("deviceActionService"),
ServiceContainer.Resolve<ILogger>("logger"));
ServiceContainer.Register<IDeleteAccountActionFlowExecutioner>("deleteAccountActionFlowExecutioner", deleteAccountActionFlowExecutioner); ServiceContainer.Register<IDeleteAccountActionFlowExecutioner>("deleteAccountActionFlowExecutioner", deleteAccountActionFlowExecutioner);
var verificationActionsFlowHelper = new VerificationActionsFlowHelper( var verificationActionsFlowHelper = new VerificationActionsFlowHelper(

View File

@ -1,7 +1,7 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Bit.App.Utilities; using Bit.App.Utilities;
using Microsoft.AppCenter.Crashes; using Bit.Core.Services;
using UIKit; using UIKit;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS; using Xamarin.Forms.Platform.iOS;
@ -39,7 +39,7 @@ namespace Bit.iOS.Core.Utilities
} }
catch (Exception e) catch (Exception e)
{ {
Crashes.TrackError(e); Logger.Instance.Exception(e);
} }
finally finally
{ {

View File

@ -287,7 +287,7 @@ namespace Bit.iOS
} }
// Migration services // Migration services
ServiceContainer.Register<ILogService>("logService", new ConsoleLogService()); ServiceContainer.Register<INativeLogService>("nativeLogService", new ConsoleLogService());
// Note: This might cause a race condition. Investigate more. // Note: This might cause a race condition. Investigate more.
Task.Run(() => Task.Run(() =>

View File

@ -1,8 +1,8 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.Core.Services;
using Foundation; using Foundation;
using Microsoft.AppCenter.Crashes;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using UserNotifications; using UserNotifications;
using Xamarin.Forms; using Xamarin.Forms;
@ -45,7 +45,7 @@ namespace Bit.iOS.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Crashes.TrackError(ex); Logger.Instance.Exception(ex);
} }
} }