|
16 | 16 | using Coder.Desktop.Vpn.Utilities;
|
17 | 17 | using Grpc.Core;
|
18 | 18 | using Microsoft.Extensions.Options;
|
| 19 | +using Microsoft.Extensions.Logging; |
| 20 | +using Serilog; |
19 | 21 | using DaemonTerminateRequest = Coder.Desktop.MutagenSdk.Proto.Service.Daemon.TerminateRequest;
|
20 | 22 | using MutagenProtocol = Coder.Desktop.MutagenSdk.Proto.Url.Protocol;
|
21 | 23 | using SynchronizationTerminateRequest = Coder.Desktop.MutagenSdk.Proto.Service.Synchronization.TerminateRequest;
|
| 24 | +using Microsoft.Extensions.Hosting; |
22 | 25 |
|
23 | 26 | namespace Coder.Desktop.App.Services;
|
24 | 27 |
|
@@ -110,6 +113,8 @@ public sealed class MutagenController : ISyncSessionController
|
110 | 113 | // Protects all private non-readonly class members.
|
111 | 114 | private readonly RaiiSemaphoreSlim _lock = new(1, 1);
|
112 | 115 |
|
| 116 | + private readonly ILogger<MutagenController> _logger; |
| 117 | + |
113 | 118 | private readonly CancellationTokenSource _stateUpdateCts = new();
|
114 | 119 | private Task? _stateUpdateTask;
|
115 | 120 |
|
@@ -139,15 +144,19 @@ public sealed class MutagenController : ISyncSessionController
|
139 | 144 |
|
140 | 145 | private string MutagenDaemonLog => Path.Combine(_mutagenDataDirectory, "daemon.log");
|
141 | 146 |
|
142 |
| - public MutagenController(IOptions<MutagenControllerConfig> config) |
| 147 | + public MutagenController(IOptions<MutagenControllerConfig> config, ILogger<MutagenController> logger) |
143 | 148 | {
|
144 | 149 | _mutagenExecutablePath = config.Value.MutagenExecutablePath;
|
| 150 | + _logger = logger; |
145 | 151 | }
|
146 | 152 |
|
147 | 153 | public MutagenController(string executablePath, string dataDirectory)
|
148 | 154 | {
|
149 | 155 | _mutagenExecutablePath = executablePath;
|
150 | 156 | _mutagenDataDirectory = dataDirectory;
|
| 157 | + var builder = Host.CreateApplicationBuilder(); |
| 158 | + builder.Services.AddSerilog(); |
| 159 | + _logger = (ILogger<MutagenController>)builder.Build().Services.GetService(typeof(ILogger<MutagenController>))!; |
151 | 160 | }
|
152 | 161 |
|
153 | 162 | public event EventHandler<SyncSessionControllerStateModel>? StateChanged;
|
@@ -437,9 +446,9 @@ private async Task<MutagenClient> EnsureDaemon(CancellationToken ct)
|
437 | 446 | {
|
438 | 447 | await StopDaemon(cts.Token);
|
439 | 448 | }
|
440 |
| - catch |
| 449 | + catch (Exception stopEx) |
441 | 450 | {
|
442 |
| - // ignored |
| 451 | + _logger.LogError(stopEx, "failed to stop daemon"); |
443 | 452 | }
|
444 | 453 |
|
445 | 454 | ReplaceState(new SyncSessionControllerStateModel
|
@@ -491,6 +500,8 @@ private async Task<MutagenClient> StartDaemon(CancellationToken ct)
|
491 | 500 | }
|
492 | 501 | catch (Exception e) when (e is not OperationCanceledException)
|
493 | 502 | {
|
| 503 | + _logger.LogWarning(e, "failed to start daemon process, attempt {attempt} of {maxAttempts}", attempts, |
| 504 | + maxAttempts); |
494 | 505 | if (attempts == maxAttempts)
|
495 | 506 | throw;
|
496 | 507 | // back off a little and try again.
|
@@ -545,8 +556,11 @@ private void StartDaemonProcess()
|
545 | 556 | // https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.environment?view=net-8.0
|
546 | 557 | _daemonProcess.StartInfo.UseShellExecute = false;
|
547 | 558 | _daemonProcess.StartInfo.RedirectStandardError = true;
|
548 |
| - // TODO: log exited process |
549 |
| - // _daemonProcess.Exited += ... |
| 559 | + _daemonProcess.EnableRaisingEvents = true; |
| 560 | + _daemonProcess.Exited += (object? sender, EventArgs e) => |
| 561 | + { |
| 562 | + _logger.LogInformation("mutagen daemon exited with code {exitCode}", _daemonProcess?.ExitCode); |
| 563 | + }; |
550 | 564 | if (!_daemonProcess.Start())
|
551 | 565 | throw new InvalidOperationException("Failed to start mutagen daemon process, Start returned false");
|
552 | 566 |
|
|
0 commit comments