Skip to content

Commit

Permalink
Added GetProviders method and some code cleaning. #31 #32
Browse files Browse the repository at this point in the history
  • Loading branch information
dhindrik committed Oct 1, 2024
1 parent 191c252 commit 2faabba
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 57 deletions.
14 changes: 11 additions & 3 deletions TinyInsights.TestApp/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
namespace TinyInsights.TestApp;

namespace TinyInsights.TestApp;

public partial class App : Application
{
public App()
private readonly AppShell shell;

public App(AppShell shell)
{
InitializeComponent();

MainPage = new AppShell();
this.shell = shell;
}

protected override Window CreateWindow(IActivationState? activationState)
{
return new Window(shell);
}
}
34 changes: 32 additions & 2 deletions TinyInsights.TestApp/MainPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,30 @@ public partial class MainPage : ContentPage
{
private readonly IInsights insights;
private readonly InsightsMessageHandler insightsMessageHandler;
private readonly ILogger logger;

public MainPage(IInsights insights, InsightsMessageHandler insightsMessageHandler)
public MainPage(IInsights insights, InsightsMessageHandler insightsMessageHandler, ILogger logger)
{
this.insights = insights;
this.insightsMessageHandler = insightsMessageHandler;

this.logger = logger;
BindingContext = this;
insights.OverrideAnonymousUserId("TestUser");

InitializeComponent();
}

private bool useILogger;
public bool UseILogger
{
get => useILogger;
set
{
useILogger = value;
OnPropertyChanged();
}
}

private async void PageViewButton_OnClicked(object? sender, EventArgs e)
{
var data = new Dictionary<string, string>()
Expand All @@ -27,12 +39,24 @@ private async void PageViewButton_OnClicked(object? sender, EventArgs e)
{"key2", "value2"}
};

if (UseILogger)
{
logger.LogTrace("MainView");
return;
}

await insights.TrackPageViewAsync("MainView", data);
}


private async void EventButton_OnClicked(object? sender, EventArgs e)
{
if (UseILogger)
{
logger.LogInformation("EventButton");
return;
}

await insights.TrackEventAsync("EventButton");
}

Expand All @@ -44,6 +68,12 @@ private async void ExceptionButton_OnClicked(object? sender, EventArgs e)
}
catch (Exception ex)
{
if (UseILogger)
{
logger.LogError(ex, "ExceptionButton");
return;
}

await insights.TrackErrorAsync(ex);
}
}
Expand Down
15 changes: 15 additions & 0 deletions TinyInsights.TestApp/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,26 @@ public static MauiApp CreateMauiApp()
provider.IsAutoTrackPageViewsEnabled = true;
});

builder.Services.AddSingleton<ILogger>((serviceProvider) =>
{
var insights = serviceProvider.GetRequiredService<IInsights>();
var providers = insights.GetProviders();
if (providers.Any())
{
return (ILogger)providers.First();
}
throw new InvalidOperationException("No insights provider found");
});

#if DEBUG
builder.Logging.AddDebug();
#endif

builder.Services.AddTransient<MainPage>();
builder.Services.AddSingleton<AppShell>();

return builder.Build();
}
}
81 changes: 38 additions & 43 deletions TinyInsights/ApplicationInsightsProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ namespace TinyInsights;

public class ApplicationInsightsProvider : IInsightsProvider, ILogger
{
private readonly string _connectionString;
private static ApplicationInsightsProvider provider;
private readonly string connectionString;
private static ApplicationInsightsProvider? provider;

Check warning on line 14 in TinyInsights/ApplicationInsightsProvider.cs

View workflow job for this annotation

GitHub Actions / build

Field 'ApplicationInsightsProvider.provider' is never assigned to, and will always have its default value null

Check warning on line 14 in TinyInsights/ApplicationInsightsProvider.cs

View workflow job for this annotation

GitHub Actions / build

Field 'ApplicationInsightsProvider.provider' is never assigned to, and will always have its default value null

Check warning on line 14 in TinyInsights/ApplicationInsightsProvider.cs

View workflow job for this annotation

GitHub Actions / build

Field 'ApplicationInsightsProvider.provider' is never assigned to, and will always have its default value null
private const string userIdKey = nameof(userIdKey);

private const string crashLogFilename = "crashes.mauiinsights";

private readonly string logPath = FileSystem.CacheDirectory;

private TelemetryClient? _client;
private TelemetryClient? Client => _client ?? CreateTelemetryClient();
private TelemetryClient? client;
private TelemetryClient? Client => client ?? CreateTelemetryClient();

public bool IsTrackErrorsEnabled { get; set; } = true;
public bool IsTrackCrashesEnabled { get; set; } = true;
Expand All @@ -32,7 +32,7 @@ public class ApplicationInsightsProvider : IInsightsProvider, ILogger

public ApplicationInsightsProvider(string connectionString)
{
_connectionString = connectionString;
this.connectionString = connectionString;
provider = this;

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Expand All @@ -58,7 +58,7 @@ void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs
#elif WINDOWS
public ApplicationInsightsProvider(MauiWinUIApplication app, string connectionString)
{
_connectionString = connectionString;
this.connectionString = connectionString;
provider = this;

app.UnhandledException += App_UnhandledException;
Expand All @@ -72,8 +72,9 @@ void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionE
}
}
#elif NET8_0_OR_GREATER
public ApplicationInsightsProvider(string connectionString)
public ApplicationInsightsProvider()
{
connectionString = string.Empty;
// Do nothing. The net8.0 target exists for enabling unit testing, not for actual use.
}
#endif
Expand Down Expand Up @@ -107,51 +108,51 @@ public void Initialize()
private static void OnAppearing(object? sender, Page e)
{
var pageType = e.GetType();
provider.TrackPageViewAsync(pageType.FullName ?? pageType.Name, new Dictionary<string, string> { { "DisplayName", pageType.Name } });
provider?.TrackPageViewAsync(pageType.FullName ?? pageType.Name, new Dictionary<string, string> { { "DisplayName", pageType.Name } });
}

readonly Dictionary<string, string> _globalProperties = [];

private TelemetryClient? CreateTelemetryClient()
{
if (_client is not null)
if (client is not null)
{
return _client;
return client;
}

try
{
var configuration = new TelemetryConfiguration()
{
ConnectionString = _connectionString
ConnectionString = connectionString
};

_client = new TelemetryClient(configuration);
client = new TelemetryClient(configuration);

_client.Context.Device.OperatingSystem = DeviceInfo.Platform.ToString();
_client.Context.Device.Model = DeviceInfo.Model;
_client.Context.Device.Type = DeviceInfo.Idiom.ToString();
client.Context.Device.OperatingSystem = DeviceInfo.Platform.ToString();
client.Context.Device.Model = DeviceInfo.Model;
client.Context.Device.Type = DeviceInfo.Idiom.ToString();

// Role name will show device name if we don't set it to empty and we want it to be so anonymous as possible.
_client.Context.Cloud.RoleName = string.Empty;
_client.Context.Cloud.RoleInstance = string.Empty;
_client.Context.User.Id = GetUserId();
client.Context.Cloud.RoleName = string.Empty;
client.Context.Cloud.RoleInstance = string.Empty;
client.Context.User.Id = GetUserId();

// Add any global properties, the user has already added
foreach (var property in _globalProperties)
{
_client.Context.GlobalProperties[property.Key] = property.Value;
client.Context.GlobalProperties[property.Key] = property.Value;
}

_client.Context.GlobalProperties.TryAdd("Language", CultureInfo.CurrentUICulture.TwoLetterISOLanguageName);
_client.Context.GlobalProperties.TryAdd("Manufacturer", DeviceInfo.Manufacturer);
_client.Context.GlobalProperties.TryAdd("AppVersion", AppInfo.VersionString);
_client.Context.GlobalProperties.TryAdd("AppBuildNumber", AppInfo.BuildString);
_client.Context.GlobalProperties.TryAdd("OperatingSystemVersion", DeviceInfo.VersionString);
client.Context.GlobalProperties.TryAdd("Language", CultureInfo.CurrentUICulture.TwoLetterISOLanguageName);
client.Context.GlobalProperties.TryAdd("Manufacturer", DeviceInfo.Manufacturer);
client.Context.GlobalProperties.TryAdd("AppVersion", AppInfo.VersionString);
client.Context.GlobalProperties.TryAdd("AppBuildNumber", AppInfo.BuildString);
client.Context.GlobalProperties.TryAdd("OperatingSystemVersion", DeviceInfo.VersionString);

Task.Run(SendCrashes);

return _client;
return client;
}
catch (Exception)
{
Expand Down Expand Up @@ -329,13 +330,13 @@ private void HandleCrash(Exception ex)
}
}

public Task TrackErrorAsync(Exception ex, Dictionary<string, string>? properties = null)
public async Task TrackErrorAsync(Exception ex, Dictionary<string, string>? properties = null)
{
try
{
if (Client is null)
{
return Task.CompletedTask;
return;
}

Debug.WriteLine($"TinyInsights: Tracking error {ex.Message}");
Expand All @@ -348,67 +349,61 @@ public Task TrackErrorAsync(Exception ex, Dictionary<string, string>? properties
}

Client.TrackException(ex, properties);
Client.Flush();
await Client.FlushAsync(CancellationToken.None);
}
catch (Exception)
{
Debug.WriteLine("TinyInsights: Error tracking error");
}

return Task.CompletedTask;
}

public Task TrackEventAsync(string eventName, Dictionary<string, string>? properties = null)
public async Task TrackEventAsync(string eventName, Dictionary<string, string>? properties = null)
{
try
{
if (Client is null)
{
return Task.CompletedTask;
return;
}

Debug.WriteLine($"TinyInsights: Tracking event {eventName}");

Client.TrackEvent(eventName, properties);
Client.Flush();
await Client.FlushAsync(CancellationToken.None);
}
catch (Exception)
{
Debug.WriteLine("TinyInsights: Error tracking event");
}

return Task.CompletedTask;
}

public Task TrackPageViewAsync(string viewName, Dictionary<string, string>? properties = null)
public async Task TrackPageViewAsync(string viewName, Dictionary<string, string>? properties = null)
{
try
{
if (Client is null)
{
return Task.CompletedTask;
return;
}

Debug.WriteLine($"TinyInsights: tracking page view {viewName}");

Client.TrackPageView(viewName);
Client.Flush();
await Client.FlushAsync(CancellationToken.None);
}
catch (Exception)
{
Debug.WriteLine("TinyInsights: Error tracking page view");
}

return Task.CompletedTask;
}

public Task TrackDependencyAsync(string dependencyType, string dependencyName, string data, HttpMethod? httpMethod, DateTimeOffset startTime, TimeSpan duration, bool success, int resultCode = 0, Exception? exception = null)
public async Task TrackDependencyAsync(string dependencyType, string dependencyName, string data, HttpMethod? httpMethod, DateTimeOffset startTime, TimeSpan duration, bool success, int resultCode = 0, Exception? exception = null)
{
try
{
if (Client is null)
{
return Task.CompletedTask;
return;
}

Debug.WriteLine($"TinyInsights: Tracking dependency {dependencyName}");
Expand Down Expand Up @@ -452,13 +447,13 @@ public Task TrackDependencyAsync(string dependencyType, string dependencyName, s
}

Client.TrackDependency(dependency);
await Client.FlushAsync(CancellationToken.None);
}
catch (Exception)
{
Debug.WriteLine("TinyInsights: Error tracking dependency");
}

return Task.CompletedTask;
}

public Task TrackDependencyAsync(string dependencyType, string dependencyName, string data, DateTimeOffset startTime, TimeSpan duration, bool success, int resultCode = 0, Exception? exception = null)
Expand Down
1 change: 1 addition & 0 deletions TinyInsights/IInsights.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace TinyInsights;
public interface IInsights
{
void AddProvider(IInsightsProvider provider);
IReadOnlyList<IInsightsProvider> GetProviders();

void UpsertGlobalProperty(string key, string value);

Expand Down
Loading

0 comments on commit 2faabba

Please sign in to comment.