Skip to content

Commit 5e1ba1d

Browse files
committed
feat: add logging to App
1 parent a58864e commit 5e1ba1d

File tree

8 files changed

+695
-564
lines changed

8 files changed

+695
-564
lines changed

App/App.csproj

+6-3
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,13 @@
6161
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
6262
</PackageReference>
6363
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.2.0" />
64-
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.1" />
65-
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.1" />
66-
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.1" />
64+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.4" />
65+
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.4" />
66+
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.4" />
6767
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.6.250108002" />
68+
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
69+
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
70+
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
6871
<PackageReference Include="WinUIEx" Version="2.5.1" />
6972
</ItemGroup>
7073

App/App.xaml.cs

+55-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Diagnostics;
33
using System.IO;
4+
using System.Linq;
45
using System.Threading;
56
using System.Threading.Tasks;
67
using Coder.Desktop.App.Models;
@@ -16,6 +17,8 @@
1617
using Microsoft.Win32;
1718
using Microsoft.Windows.AppLifecycle;
1819
using Windows.ApplicationModel.Activation;
20+
using Microsoft.Extensions.Logging;
21+
using Serilog;
1922

2023
namespace Coder.Desktop.App;
2124

@@ -24,22 +27,51 @@ public partial class App : Application
2427
private readonly IServiceProvider _services;
2528

2629
private bool _handleWindowClosed = true;
30+
private const string MutagenControllerConfigSection = "MutagenController";
31+
32+
private const string logTemplate =
33+
"{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {SourceContext} - {Message:lj}{NewLine}{Exception}";
2734

2835
#if !DEBUG
29-
private const string MutagenControllerConfigSection = "AppMutagenController";
36+
private const string ConfigSubKey = @"SOFTWARE\Coder Desktop\App";
37+
private const string logFilename = "app.log";
3038
#else
31-
private const string MutagenControllerConfigSection = "DebugAppMutagenController";
39+
private const string ConfigSubKey = @"SOFTWARE\Coder Desktop\DebugApp";
40+
private const string logFilename = "debug-app.log";
3241
#endif
3342

43+
private readonly ILogger<App> _logger;
44+
3445
public App()
3546
{
3647
var builder = Host.CreateApplicationBuilder();
3748

3849
(builder.Configuration as IConfigurationBuilder).Add(
39-
new RegistryConfigurationSource(Registry.LocalMachine, @"SOFTWARE\Coder Desktop"));
50+
new RegistryConfigurationSource(Registry.LocalMachine, ConfigSubKey));
4051

4152
var services = builder.Services;
4253

54+
// Logging
55+
builder.Services.AddSerilog((_, loggerConfig) =>
56+
{
57+
loggerConfig.ReadFrom.Configuration(builder.Configuration);
58+
var sinkConfig = builder.Configuration.GetSection("Serilog").GetSection("WriteTo");
59+
if (!sinkConfig.GetChildren().Any())
60+
{
61+
// no log sink defined in the registry, so we'll add one here.
62+
// We can't generally define these in the registry because we don't
63+
// know, a priori, what user will execute Coder Desktop, and therefore
64+
// what directories are writable by them. But, it's nice to be able to
65+
// directly customize Serilog via the registry if you know what you are
66+
// doing.
67+
var logPath = Path.Combine(
68+
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
69+
"CoderDesktop",
70+
logFilename);
71+
loggerConfig.WriteTo.File(logPath, outputTemplate: logTemplate, rollingInterval: RollingInterval.Day);
72+
}
73+
});
74+
4375
services.AddSingleton<ICredentialManager, CredentialManager>();
4476
services.AddSingleton<IRpcController, RpcController>();
4577

@@ -69,6 +101,7 @@ public App()
69101
services.AddTransient<TrayWindow>();
70102

71103
_services = services.BuildServiceProvider();
104+
_logger = (ILogger<App>)(_services.GetService(typeof(ILogger<App>))!);
72105

73106
InitializeComponent();
74107
}
@@ -87,6 +120,7 @@ public async Task ExitApplication()
87120

88121
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
89122
{
123+
_logger.LogInformation("new instance launched");
90124
// Start connecting to the manager in the background.
91125
var rpcController = _services.GetRequiredService<IRpcController>();
92126
if (rpcController.GetState().RpcLifecycle == RpcLifecycle.Disconnected)
@@ -110,13 +144,15 @@ protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs ar
110144
_ = credentialManager.LoadCredentials(credentialManagerCts.Token).ContinueWith(t =>
111145
{
112146
// TODO: log
113-
#if DEBUG
114147
if (t.Exception != null)
115148
{
149+
_logger.LogError(t.Exception, "failed to load credentials");
150+
#if DEBUG
116151
Debug.WriteLine(t.Exception);
117152
Debugger.Break();
118-
}
119153
#endif
154+
}
155+
120156
credentialManagerCts.Dispose();
121157
}, CancellationToken.None);
122158

@@ -126,9 +162,13 @@ protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs ar
126162
_ = syncSessionController.RefreshState(syncSessionCts.Token).ContinueWith(t =>
127163
{
128164
// TODO: log
165+
if (t.IsCanceled || t.Exception != null)
166+
{
167+
_logger.LogError(t.Exception, "failed to refresh sync state (canceled = {canceled}", t.IsCanceled);
129168
#if DEBUG
130-
if (t.IsCanceled || t.Exception != null) Debugger.Break();
169+
Debugger.Break();
131170
#endif
171+
}
132172
syncSessionCts.Dispose();
133173
}, CancellationToken.None);
134174

@@ -148,17 +188,24 @@ public void OnActivated(object? sender, AppActivationArguments args)
148188
{
149189
case ExtendedActivationKind.Protocol:
150190
var protoArgs = args.Data as IProtocolActivatedEventArgs;
191+
if (protoArgs == null)
192+
{
193+
_logger.LogWarning("URI activation with null data");
194+
return;
195+
}
196+
151197
HandleURIActivation(protoArgs.Uri);
152198
break;
153199

154200
default:
155-
// TODO: log
201+
_logger.LogWarning("activation for {kind}, which is unhandled", args.Kind);
156202
break;
157203
}
158204
}
159205

160206
public void HandleURIActivation(Uri uri)
161207
{
162-
// TODO: handle
208+
// don't log the query string as that's where we include some sensitive information like passwords
209+
_logger.LogInformation("handling URI activation for {path}", uri.AbsolutePath);
163210
}
164211
}

0 commit comments

Comments
 (0)