|
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;
|
@@ -440,9 +449,9 @@ private async Task<MutagenClient> EnsureDaemon(CancellationToken ct)
|
440 | 449 | {
|
441 | 450 | await StopDaemon(cts.Token);
|
442 | 451 | }
|
443 |
| - catch |
| 452 | + catch (Exception stopEx) |
444 | 453 | {
|
445 |
| - // ignored |
| 454 | + _logger.LogError(stopEx, "failed to stop daemon"); |
446 | 455 | }
|
447 | 456 |
|
448 | 457 | ReplaceState(new SyncSessionControllerStateModel
|
@@ -494,6 +503,8 @@ private async Task<MutagenClient> StartDaemon(CancellationToken ct)
|
494 | 503 | }
|
495 | 504 | catch (Exception e) when (e is not OperationCanceledException)
|
496 | 505 | {
|
| 506 | + _logger.LogWarning(e, "failed to start daemon process, attempt {attempt} of {maxAttempts}", attempts, |
| 507 | + maxAttempts); |
497 | 508 | if (attempts == maxAttempts)
|
498 | 509 | throw;
|
499 | 510 | // back off a little and try again.
|
@@ -548,8 +559,11 @@ private void StartDaemonProcess()
|
548 | 559 | // https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.environment?view=net-8.0
|
549 | 560 | _daemonProcess.StartInfo.UseShellExecute = false;
|
550 | 561 | _daemonProcess.StartInfo.RedirectStandardError = true;
|
551 |
| - // TODO: log exited process |
552 |
| - // _daemonProcess.Exited += ... |
| 562 | + _daemonProcess.EnableRaisingEvents = true; |
| 563 | + _daemonProcess.Exited += (object? sender, EventArgs e) => |
| 564 | + { |
| 565 | + _logger.LogInformation("mutagen daemon exited with code {exitCode}", _daemonProcess?.ExitCode); |
| 566 | + }; |
553 | 567 | if (!_daemonProcess.Start())
|
554 | 568 | throw new InvalidOperationException("Failed to start mutagen daemon process, Start returned false");
|
555 | 569 |
|
|
0 commit comments