Tracking failed imap setup steps for app insights.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SQLite;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
@@ -49,4 +50,25 @@ public class CustomServerInformation
|
||||
/// Default is 5.
|
||||
/// </summary>
|
||||
public int MaxConcurrentClients { get; set; }
|
||||
|
||||
public Dictionary<string, string> GetConnectionProperties()
|
||||
{
|
||||
// Printout the public connection properties.
|
||||
|
||||
var connectionProperties = new Dictionary<string, string>
|
||||
{
|
||||
{ "IncomingServer", IncomingServer },
|
||||
{ "IncomingServerPort", IncomingServerPort },
|
||||
{ "IncomingServerSocketOption", IncomingServerSocketOption.ToString() },
|
||||
{ "IncomingAuthenticationMethod", IncomingAuthenticationMethod.ToString() },
|
||||
{ "OutgoingServer", OutgoingServer },
|
||||
{ "OutgoingServerPort", OutgoingServerPort },
|
||||
{ "OutgoingServerSocketOption", OutgoingServerSocketOption.ToString() },
|
||||
{ "OutgoingAuthenticationMethod", OutgoingAuthenticationMethod.ToString() },
|
||||
{ "ProxyServer", ProxyServer },
|
||||
{ "ProxyServerPort", ProxyServerPort }
|
||||
};
|
||||
|
||||
return connectionProperties;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,30 @@
|
||||
using System;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
|
||||
namespace Wino.Core.Domain.Exceptions;
|
||||
|
||||
public class ImapClientPoolException : Exception
|
||||
{
|
||||
public ImapClientPoolException()
|
||||
{
|
||||
}
|
||||
|
||||
public ImapClientPoolException(string message, CustomServerInformation customServerInformation, string protocolLog) : base(message)
|
||||
{
|
||||
CustomServerInformation = customServerInformation;
|
||||
ProtocolLog = protocolLog;
|
||||
}
|
||||
|
||||
public ImapClientPoolException(string message, string protocolLog) : base(message)
|
||||
{
|
||||
ProtocolLog = protocolLog;
|
||||
}
|
||||
|
||||
public ImapClientPoolException(Exception innerException, string protocolLog) : base(Translator.Exception_ImapClientPoolFailed, innerException)
|
||||
{
|
||||
ProtocolLog = protocolLog;
|
||||
}
|
||||
|
||||
public CustomServerInformation CustomServerInformation { get; }
|
||||
public string ProtocolLog { get; }
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Wino.Core.Domain.Interfaces;
|
||||
|
||||
public interface ILogInitializer
|
||||
{
|
||||
void SetupLogger(string fullLogFilePath);
|
||||
|
||||
void RefreshLoggingLevel();
|
||||
}
|
||||
10
Wino.Core.Domain/Interfaces/IWinoLogger.cs
Normal file
10
Wino.Core.Domain/Interfaces/IWinoLogger.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wino.Core.Domain.Interfaces;
|
||||
|
||||
public interface IWinoLogger
|
||||
{
|
||||
void SetupLogger(string fullLogFilePath);
|
||||
void RefreshLoggingLevel();
|
||||
void TrackEvent(string eventName, Dictionary<string, string> properties = null);
|
||||
}
|
||||
@@ -22,15 +22,15 @@ using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Services;
|
||||
|
||||
namespace Wino.Core.UWP;
|
||||
|
||||
public abstract class WinoApplication : Application
|
||||
namespace Wino.Core.UWP
|
||||
{
|
||||
public abstract class WinoApplication : Application
|
||||
{
|
||||
public new static WinoApplication Current => (WinoApplication)Application.Current;
|
||||
public const string WinoLaunchLogPrefix = "[Wino Launch] ";
|
||||
|
||||
public IServiceProvider Services { get; }
|
||||
protected ILogInitializer LogInitializer { get; }
|
||||
protected IWinoLogger LogInitializer { get; }
|
||||
protected IApplicationConfiguration AppConfiguration { get; }
|
||||
protected IWinoServerConnectionManager<AppServiceConnection> AppServiceConnectionManager { get; }
|
||||
protected IThemeService ThemeService { get; }
|
||||
@@ -50,7 +50,7 @@ public abstract class WinoApplication : Application
|
||||
Resuming += OnResuming;
|
||||
Suspending += OnSuspending;
|
||||
|
||||
LogInitializer = Services.GetService<ILogInitializer>();
|
||||
LogInitializer = Services.GetService<IWinoLogger>();
|
||||
AppConfiguration = Services.GetService<IApplicationConfiguration>();
|
||||
|
||||
AppServiceConnectionManager = Services.GetService<IWinoServerConnectionManager<AppServiceConnection>>();
|
||||
@@ -245,4 +245,5 @@ public abstract class WinoApplication : Application
|
||||
string logFilePath = Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.ClientLogFile);
|
||||
LogInitializer.SetupLogger(logFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,17 +6,17 @@ using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Core.ViewModels;
|
||||
|
||||
public partial class AboutPageViewModel : CoreBaseViewModel
|
||||
namespace Wino.Core.ViewModels
|
||||
{
|
||||
public partial class AboutPageViewModel : CoreBaseViewModel
|
||||
{
|
||||
private readonly IStoreRatingService _storeRatingService;
|
||||
private readonly IMailDialogService _dialogService;
|
||||
private readonly INativeAppService _nativeAppService;
|
||||
private readonly IApplicationConfiguration _appInitializerService;
|
||||
private readonly IClipboardService _clipboardService;
|
||||
private readonly IFileService _fileService;
|
||||
private readonly ILogInitializer _logInitializer;
|
||||
private readonly IWinoLogger _logInitializer;
|
||||
|
||||
public string VersionName => _nativeAppService.GetFullAppVersion();
|
||||
public string DiscordChannelUrl => "https://discord.gg/windows-apps-hub-714581497222398064";
|
||||
@@ -33,7 +33,7 @@ public partial class AboutPageViewModel : CoreBaseViewModel
|
||||
IApplicationConfiguration appInitializerService,
|
||||
IClipboardService clipboardService,
|
||||
IFileService fileService,
|
||||
ILogInitializer logInitializer)
|
||||
IWinoLogger logInitializer)
|
||||
{
|
||||
_storeRatingService = storeRatingService;
|
||||
_dialogService = dialogService;
|
||||
@@ -126,4 +126,5 @@ public partial class AboutPageViewModel : CoreBaseViewModel
|
||||
}
|
||||
|
||||
private Task ShowRateDialogAsync() => _storeRatingService.LaunchStorePageForReviewAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using MailKit.Net.Smtp;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Connectivity;
|
||||
@@ -53,5 +54,14 @@ public class ImapTestService : IImapTestService
|
||||
|
||||
clientPool.Release(client);
|
||||
}
|
||||
|
||||
// Test SMTP connectivity.
|
||||
using var smtpClient = new SmtpClient();
|
||||
|
||||
if (!smtpClient.IsConnected)
|
||||
await smtpClient.ConnectAsync(serverInformation.OutgoingServer, int.Parse(serverInformation.OutgoingServerPort), MailKit.Security.SecureSocketOptions.Auto);
|
||||
|
||||
if (!smtpClient.IsAuthenticated)
|
||||
await smtpClient.AuthenticateAsync(serverInformation.OutgoingServerUsername, serverInformation.OutgoingServerPassword);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Exceptions;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Authentication;
|
||||
using Wino.Core.Domain.Models.Connectivity;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.Domain.Models.Synchronization;
|
||||
using Wino.Core.ViewModels;
|
||||
@@ -28,6 +29,7 @@ public partial class AccountManagementViewModel : AccountManagementPageViewModel
|
||||
{
|
||||
private readonly ISpecialImapProviderConfigResolver _specialImapProviderConfigResolver;
|
||||
private readonly IImapTestService _imapTestService;
|
||||
private readonly IWinoLogger _winoLogger;
|
||||
|
||||
public IMailDialogService MailDialogService { get; }
|
||||
|
||||
@@ -39,12 +41,14 @@ public partial class AccountManagementViewModel : AccountManagementPageViewModel
|
||||
IProviderService providerService,
|
||||
IImapTestService imapTestService,
|
||||
IStoreManagementService storeManagementService,
|
||||
IWinoLogger winoLogger,
|
||||
IAuthenticationProvider authenticationProvider,
|
||||
IPreferencesService preferencesService) : base(dialogService, winoServerConnectionManager, navigationService, accountService, providerService, storeManagementService, authenticationProvider, preferencesService)
|
||||
{
|
||||
MailDialogService = dialogService;
|
||||
_specialImapProviderConfigResolver = specialImapProviderConfigResolver;
|
||||
_imapTestService = imapTestService;
|
||||
_winoLogger = winoLogger;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
@@ -111,6 +115,7 @@ public partial class AccountManagementViewModel : AccountManagementPageViewModel
|
||||
};
|
||||
|
||||
await creationDialog.ShowDialogAsync(accountCreationCancellationTokenSource);
|
||||
|
||||
creationDialog.State = AccountCreationDialogState.SigningIn;
|
||||
|
||||
string tokenInformation = string.Empty;
|
||||
@@ -146,7 +151,18 @@ public partial class AccountManagementViewModel : AccountManagementPageViewModel
|
||||
createdAccount.SenderName = accountCreationDialogResult.SpecialImapProviderDetails.SenderName;
|
||||
createdAccount.Address = customServerInformation.Address;
|
||||
|
||||
await _imapTestService.TestImapConnectionAsync(customServerInformation, true);
|
||||
// Let server validate the imap/smtp connection.
|
||||
var testResultResponse = await WinoServerConnectionManager.GetResponseAsync<ImapConnectivityTestResults, ImapConnectivityTestRequested>(new ImapConnectivityTestRequested(customServerInformation, true));
|
||||
|
||||
if (!testResultResponse.IsSuccess)
|
||||
{
|
||||
throw new Exception($"{Translator.IMAPSetupDialog_ConnectionFailedTitle}\n{testResultResponse.Message}");
|
||||
}
|
||||
else if (!testResultResponse.Data.IsSuccess)
|
||||
{
|
||||
// Server connectivity might succeed, but result might be failed.
|
||||
throw new ImapClientPoolException(testResultResponse.Data.FailedReason, customServerInformation, testResultResponse.Data.FailureProtocolLog);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -266,7 +282,18 @@ public partial class AccountManagementViewModel : AccountManagementPageViewModel
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
catch (ImapClientPoolException clientPoolException)
|
||||
catch (ImapClientPoolException testClientPoolException) when (testClientPoolException.CustomServerInformation != null)
|
||||
{
|
||||
var properties = testClientPoolException.CustomServerInformation.GetConnectionProperties();
|
||||
|
||||
properties.Add("ProtocolLog", testClientPoolException.ProtocolLog);
|
||||
properties.Add("DiagnosticId", PreferencesService.DiagnosticId);
|
||||
|
||||
_winoLogger.TrackEvent("IMAP Test Failed", properties);
|
||||
|
||||
DialogService.InfoBarMessage(Translator.Info_AccountCreationFailedTitle, testClientPoolException.Message, InfoBarMessageType.Error);
|
||||
}
|
||||
catch (ImapClientPoolException clientPoolException) when (clientPoolException.InnerException != null)
|
||||
{
|
||||
DialogService.InfoBarMessage(Translator.Info_AccountCreationFailedTitle, clientPoolException.InnerException.Message, InfoBarMessageType.Error);
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ public partial class App : Application
|
||||
applicationFolderConfiguration.ApplicationTempFolderPath = ApplicationData.Current.TemporaryFolder.Path;
|
||||
|
||||
// Setup logger
|
||||
var logInitializer = Services.GetService<ILogInitializer>();
|
||||
var logInitializer = Services.GetService<IWinoLogger>();
|
||||
var logFilePath = Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.ServerLogFile);
|
||||
|
||||
logInitializer.SetupLogger(logFilePath);
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Services.Threading;
|
||||
|
||||
namespace Wino.Services;
|
||||
|
||||
public static class ServicesContainerSetup
|
||||
namespace Wino.Services
|
||||
{
|
||||
public static class ServicesContainerSetup
|
||||
{
|
||||
public static void RegisterSharedServices(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<ITranslationService, TranslationService>();
|
||||
services.AddSingleton<IDatabaseService, DatabaseService>();
|
||||
|
||||
services.AddSingleton<IApplicationConfiguration, ApplicationConfiguration>();
|
||||
services.AddSingleton<ILogInitializer, LogInitializer>();
|
||||
services.AddSingleton<IWinoLogger, WinoLogger>();
|
||||
services.AddSingleton<ILaunchProtocolService, LaunchProtocolService>();
|
||||
services.AddSingleton<IMimeFileService, MimeFileService>();
|
||||
|
||||
@@ -31,5 +31,6 @@ public static class ServicesContainerSetup
|
||||
services.AddTransient<IImapThreadingStrategy, ImapThreadingStrategy>();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Microsoft.ApplicationInsights.Extensibility;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.ApplicationInsights;
|
||||
using Microsoft.ApplicationInsights.Extensibility;
|
||||
using Serilog;
|
||||
using Serilog.Core;
|
||||
using Serilog.Exceptions;
|
||||
@@ -7,20 +9,21 @@ using Wino.Services.Misc;
|
||||
|
||||
namespace Wino.Services;
|
||||
|
||||
public class LogInitializer : ILogInitializer
|
||||
public class WinoLogger : IWinoLogger
|
||||
{
|
||||
private readonly LoggingLevelSwitch _levelSwitch = new LoggingLevelSwitch();
|
||||
private readonly IPreferencesService _preferencesService;
|
||||
private readonly IApplicationConfiguration _applicationConfiguration;
|
||||
private readonly TelemetryConfiguration _telemetryConfiguration;
|
||||
|
||||
public LogInitializer(IPreferencesService preferencesService, IApplicationConfiguration applicationConfiguration)
|
||||
public TelemetryClient TelemetryClient { get; private set; }
|
||||
|
||||
public WinoLogger(IPreferencesService preferencesService, IApplicationConfiguration applicationConfiguration)
|
||||
{
|
||||
_preferencesService = preferencesService;
|
||||
_applicationConfiguration = applicationConfiguration;
|
||||
|
||||
_telemetryConfiguration = new TelemetryConfiguration(applicationConfiguration.ApplicationInsightsInstrumentationKey);
|
||||
|
||||
TelemetryClient = new TelemetryClient(_telemetryConfiguration);
|
||||
|
||||
RefreshLoggingLevel();
|
||||
}
|
||||
|
||||
@@ -41,9 +44,16 @@ public class LogInitializer : ILogInitializer
|
||||
.MinimumLevel.ControlledBy(_levelSwitch)
|
||||
.WriteTo.File(fullLogFilePath, retainedFileCountLimit: 3, rollOnFileSizeLimit: true, rollingInterval: RollingInterval.Day)
|
||||
.WriteTo.Debug()
|
||||
.WriteTo.ApplicationInsights(_telemetryConfiguration, insightsTelemetryConverter, restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Error)
|
||||
.WriteTo.ApplicationInsights(TelemetryClient, insightsTelemetryConverter, restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Error)
|
||||
.Enrich.FromLogContext()
|
||||
.Enrich.WithExceptionDetails()
|
||||
.CreateLogger();
|
||||
}
|
||||
|
||||
public void TrackEvent(string eventName, Dictionary<string, string> properties = null)
|
||||
{
|
||||
if (TelemetryClient == null) return;
|
||||
|
||||
TelemetryClient.TrackEvent(eventName, properties);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user