Skip to content

Commit 8fd7504

Browse files
Retention policy for cdb output files
1 parent ec1d1ce commit 8fd7504

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed

nexus_engine/nexus_engine/Internal/CdbSession.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,13 +471,77 @@ private string GetCdbSessionBasedLogPath(string sessionId)
471471
// Ensure the Sessions directory exists
472472
_ = Directory.CreateDirectory(sessionsDirectory);
473473

474+
var retentionDays = m_Settings.Get().Logging.RetentionDays;
475+
if (retentionDays > 0)
476+
{
477+
CleanupOldCdbLogs(sessionsDirectory, retentionDays);
478+
}
479+
474480
var newFileNameWithoutExtension = $"cdb_{sessionId}";
475481
var newFileName = Path.ChangeExtension(newFileNameWithoutExtension, ".log");
476482
var newPath = Path.Combine(sessionsDirectory, newFileName);
477483

478484
return newPath;
479485
}
480486

487+
/// <summary>
488+
/// Cleans up CDB log files older than the configured retention period in the specified Sessions directory.
489+
/// </summary>
490+
/// <param name="sessionsDirectory">The directory containing the CDB log files.</param>
491+
/// <param name="retentionDays">The retention period in days.</param>
492+
protected void CleanupOldCdbLogs(string sessionsDirectory, int retentionDays)
493+
{
494+
if (retentionDays <= 0)
495+
{
496+
return;
497+
}
498+
499+
try
500+
{
501+
var directoryInfo = m_FileSystem.GetDirectoryInfo(sessionsDirectory);
502+
var files = directoryInfo.GetFiles("cdb_*.log");
503+
504+
if (files.Length == 0)
505+
{
506+
return;
507+
}
508+
509+
var cutoff = DateTime.Now.AddDays(-retentionDays);
510+
var deletedCount = 0;
511+
512+
foreach (var file in files)
513+
{
514+
if (file.CreationTime >= cutoff)
515+
{
516+
continue;
517+
}
518+
519+
try
520+
{
521+
m_FileSystem.DeleteFile(file.FullName);
522+
deletedCount++;
523+
}
524+
catch (Exception ex)
525+
{
526+
m_Logger.Warn(ex, "Failed to delete old CDB log file {CdbLogFile}", file.FullName);
527+
}
528+
}
529+
530+
if (deletedCount > 0)
531+
{
532+
m_Logger.Info(
533+
"Deleted {DeletedCount} CDB log files older than {RetentionDays} days in {SessionsDirectory}",
534+
deletedCount,
535+
retentionDays,
536+
sessionsDirectory);
537+
}
538+
}
539+
catch (Exception ex)
540+
{
541+
m_Logger.Warn(ex, "Error while cleaning up old CDB log files in {SessionsDirectory}", sessionsDirectory);
542+
}
543+
}
544+
481545
/// <summary>
482546
/// Builds the command line arguments for starting the CDB process.
483547
/// </summary>

unittests/nexus_engine/nexus_engine_unittests/Internal/CdbSessionTestAccessor.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,16 @@ public bool GetEffectiveProcessExitedForTesting()
183183
return CdbSession.CreateCommandWithSentinels(command);
184184
}
185185

186+
/// <summary>
187+
/// Exposes the CleanupOldCdbLogs method for testing.
188+
/// </summary>
189+
/// <param name="sessionsDirectory">The directory containing the CDB log files.</param>
190+
/// <param name="retentionDays">The retention period in days.</param>
191+
public void CleanupOldCdbLogsForTesting(string sessionsDirectory, int retentionDays)
192+
{
193+
CleanupOldCdbLogs(sessionsDirectory, retentionDays);
194+
}
195+
186196
/// <summary>
187197
/// Sets the process exited state for testing purposes.
188198
/// </summary>

unittests/nexus_engine/nexus_engine_unittests/Internal/CdbSessionTests.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,53 @@ public void ProcessOutputLine_BeforeStartMarker_IgnoresLine()
580580
_ = output.ToString().Should().BeEmpty();
581581
}
582582

583+
/// <summary>
584+
/// Verifies that CleanupOldCdbLogs deletes CDB log files older than the configured retention period
585+
/// based on their creation time and leaves newer files intact.
586+
/// </summary>
587+
[Fact]
588+
public void CleanupOldCdbLogs_DeletesFilesOlderThanRetentionDays()
589+
{
590+
// Arrange
591+
var tempRoot = Path.Combine(Path.GetTempPath(), "MCPNexusCdbRetentionTests", Guid.NewGuid().ToString("N"));
592+
var sessionsDirectory = Path.Combine(tempRoot, "Sessions");
593+
_ = Directory.CreateDirectory(sessionsDirectory);
594+
595+
var oldFilePath = Path.Combine(sessionsDirectory, "cdb_old.log");
596+
var recentFilePath = Path.Combine(sessionsDirectory, "cdb_recent.log");
597+
598+
File.WriteAllText(oldFilePath, "old");
599+
File.WriteAllText(recentFilePath, "recent");
600+
601+
File.SetCreationTime(oldFilePath, DateTime.Now.AddDays(-10));
602+
File.SetCreationTime(recentFilePath, DateTime.Now);
603+
604+
try
605+
{
606+
var directoryInfo = new DirectoryInfo(sessionsDirectory);
607+
_ = m_MockFileSystem.Setup(fs => fs.GetDirectoryInfo(sessionsDirectory)).Returns(directoryInfo);
608+
_ = m_MockFileSystem.Setup(fs => fs.DeleteFile(It.IsAny<string>()))
609+
.Callback<string>(path => File.Delete(path));
610+
611+
var accessor = new CdbSessionTestAccessor(m_Settings.Object, m_MockFileSystem.Object, m_MockProcessManager.Object);
612+
613+
// Act
614+
accessor.CleanupOldCdbLogsForTesting(sessionsDirectory, 7);
615+
616+
// Assert
617+
_ = File.Exists(oldFilePath).Should().BeFalse();
618+
_ = File.Exists(recentFilePath).Should().BeTrue();
619+
m_MockFileSystem.Verify(fs => fs.DeleteFile(oldFilePath), Times.Once);
620+
}
621+
finally
622+
{
623+
if (Directory.Exists(tempRoot))
624+
{
625+
Directory.Delete(tempRoot, true);
626+
}
627+
}
628+
}
629+
583630
/// <summary>
584631
/// Verifies that ThrowIfDisposed throws when session is disposed.
585632
/// </summary>

0 commit comments

Comments
 (0)