Skip to content

Commit 5e459f8

Browse files
committed
refactor: Add logging to TemplateEngineHelper and DotNetCliTools for better traceability
1 parent 708f111 commit 5e459f8

File tree

2 files changed

+42
-14
lines changed

2 files changed

+42
-14
lines changed

DotNetMcp/DotNetCliTools.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.ComponentModel;
22
using System.Diagnostics;
33
using System.Text;
4+
using Microsoft.Extensions.Logging;
45
using ModelContextProtocol.Protocol;
56
using ModelContextProtocol.Server;
67

@@ -9,24 +10,30 @@ namespace DotNetMcp;
910
[McpServerToolType]
1011
public sealed class DotNetCliTools
1112
{
13+
private readonly ILogger<DotNetCliTools> _logger;
14+
15+
public DotNetCliTools(ILogger<DotNetCliTools> logger)
16+
{
17+
_logger = logger;
18+
}
1219
[McpServerTool, Description("List all installed .NET templates with their metadata using the Template Engine. Provides structured information about available project templates.")]
1320
public async Task<string> DotnetTemplateList()
14-
=> await TemplateEngineHelper.GetInstalledTemplatesAsync();
21+
=> await TemplateEngineHelper.GetInstalledTemplatesAsync(_logger);
1522

1623
[McpServerTool, Description("Search for .NET templates by name or description. Returns matching templates with their details.")]
1724
public async Task<string> DotnetTemplateSearch(
1825
[Description("Search term to find templates (searches in name, short name, and description)")] string searchTerm)
19-
=> await TemplateEngineHelper.SearchTemplatesAsync(searchTerm);
26+
=> await TemplateEngineHelper.SearchTemplatesAsync(searchTerm, _logger);
2027

2128
[McpServerTool, Description("Get detailed information about a specific template including available parameters and options.")]
2229
public async Task<string> DotnetTemplateInfo(
2330
[Description("The template short name (e.g., 'console', 'webapi', 'classlib')")] string templateShortName)
24-
=> await TemplateEngineHelper.GetTemplateDetailsAsync(templateShortName);
31+
=> await TemplateEngineHelper.GetTemplateDetailsAsync(templateShortName, _logger);
2532

2633
[McpServerTool, Description("Clear the template cache to force reload from disk. Use this after installing or uninstalling templates.")]
2734
public async Task<string> DotnetTemplateClearCache()
2835
{
29-
await TemplateEngineHelper.ClearCacheAsync();
36+
await TemplateEngineHelper.ClearCacheAsync(_logger);
3037
return "Template cache cleared successfully. Next template query will reload from disk.";
3138
}
3239

@@ -445,6 +452,8 @@ public async Task<string> DotnetNugetLocals(
445452

446453
private async Task<string> ExecuteDotNetCommand(string arguments)
447454
{
455+
_logger.LogDebug("Executing: dotnet {Arguments}", arguments);
456+
448457
var psi = new ProcessStartInfo
449458
{
450459
FileName = "dotnet",
@@ -502,6 +511,16 @@ private async Task<string> ExecuteDotNetCommand(string arguments)
502511
process.BeginErrorReadLine();
503512
await process.WaitForExitAsync();
504513

514+
_logger.LogDebug("Command completed with exit code: {ExitCode}", process.ExitCode);
515+
if (outputTruncated)
516+
{
517+
_logger.LogWarning("Output was truncated due to size limit");
518+
}
519+
if (errorTruncated)
520+
{
521+
_logger.LogWarning("Error output was truncated due to size limit");
522+
}
523+
505524
var result = new StringBuilder();
506525
if (output.Length > 0) result.AppendLine(output.ToString());
507526
if (error.Length > 0)

DotNetMcp/TemplateEngineHelper.cs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Text;
22
using System.Text.Json;
3+
using Microsoft.Extensions.Logging;
34
using Microsoft.TemplateEngine.Abstractions;
45
using Microsoft.TemplateEngine.Edge;
56
using Microsoft.TemplateEngine.Edge.Settings;
@@ -32,20 +33,27 @@ public class TemplateEngineHelper
3233
/// Get templates from cache or load them if cache is expired.
3334
/// Cache expires after 5 minutes to allow for template installations/updates.
3435
/// </summary>
35-
private static async Task<IEnumerable<ITemplateInfo>> GetTemplatesCachedAsync()
36+
private static async Task<IEnumerable<ITemplateInfo>> GetTemplatesCachedAsync(ILogger? logger = null)
3637
{
3738
await _cacheLock.WaitAsync();
3839
try
3940
{
4041
if (_templatesCache == null || DateTime.UtcNow > _cacheExpiry)
4142
{
43+
logger?.LogDebug("Template cache miss - loading templates from Template Engine");
4244
var engineEnvironmentSettings = new EngineEnvironmentSettings(
4345
new DefaultTemplateEngineHost("dotnet-mcp", "1.0.0"),
4446
virtualizeSettings: true);
4547

4648
var templatePackageManager = new TemplatePackageManager(engineEnvironmentSettings);
4749
_templatesCache = await templatePackageManager.GetTemplatesAsync(default);
4850
_cacheExpiry = DateTime.UtcNow.Add(CacheDuration);
51+
logger?.LogInformation("Loaded {TemplateCount} templates into cache (expires in {CacheDuration})",
52+
_templatesCache.Count(), CacheDuration);
53+
}
54+
else
55+
{
56+
logger?.LogDebug("Template cache hit - returning cached templates");
4957
}
5058
return _templatesCache;
5159
}
@@ -62,13 +70,14 @@ private static async Task<IEnumerable<ITemplateInfo>> GetTemplatesCachedAsync()
6270
/// This method properly uses async/await to prevent potential deadlocks that could occur
6371
/// with synchronous Wait() calls on SemaphoreSlim.
6472
/// </remarks>
65-
public static async Task ClearCacheAsync()
73+
public static async Task ClearCacheAsync(ILogger? logger = null)
6674
{
6775
await _cacheLock.WaitAsync();
6876
try
6977
{
7078
_templatesCache = null;
7179
_cacheExpiry = DateTime.MinValue;
80+
logger?.LogInformation("Template cache cleared");
7281
}
7382
finally
7483
{
@@ -93,12 +102,12 @@ public static void Dispose()
93102
/// <summary>
94103
/// Get a list of all installed templates with their metadata.
95104
/// </summary>
96-
public static async Task<string> GetInstalledTemplatesAsync()
105+
public static async Task<string> GetInstalledTemplatesAsync(ILogger? logger = null)
97106
{
98107
try
99108
{
100109
// Get all installed templates from cache
101-
var templates = await GetTemplatesCachedAsync();
110+
var templates = await GetTemplatesCachedAsync(logger);
102111

103112
if (!templates.Any())
104113
{
@@ -139,11 +148,11 @@ public static async Task<string> GetInstalledTemplatesAsync()
139148
/// <summary>
140149
/// Get detailed information about a specific template.
141150
/// </summary>
142-
public static async Task<string> GetTemplateDetailsAsync(string templateShortName)
151+
public static async Task<string> GetTemplateDetailsAsync(string templateShortName, ILogger? logger = null)
143152
{
144153
try
145154
{
146-
var templates = await GetTemplatesCachedAsync();
155+
var templates = await GetTemplatesCachedAsync(logger);
147156
var template = templates.FirstOrDefault(t =>
148157
t.ShortNameList.Any(sn => sn.Equals(templateShortName, StringComparison.OrdinalIgnoreCase)));
149158

@@ -188,11 +197,11 @@ public static async Task<string> GetTemplateDetailsAsync(string templateShortNam
188197
/// <summary>
189198
/// Search for templates by name or description.
190199
/// </summary>
191-
public static async Task<string> SearchTemplatesAsync(string searchTerm)
200+
public static async Task<string> SearchTemplatesAsync(string searchTerm, ILogger? logger = null)
192201
{
193202
try
194203
{
195-
var templates = await GetTemplatesCachedAsync();
204+
var templates = await GetTemplatesCachedAsync(logger);
196205
var matches = templates.Where(t =>
197206
t.ShortNameList.Any(sn => sn.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) ||
198207
(t.Name?.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) ?? false) ||
@@ -236,11 +245,11 @@ public static async Task<string> SearchTemplatesAsync(string searchTerm)
236245
/// <summary>
237246
/// Validate if a template short name exists.
238247
/// </summary>
239-
public static async Task<bool> ValidateTemplateExistsAsync(string templateShortName)
248+
public static async Task<bool> ValidateTemplateExistsAsync(string templateShortName, ILogger? logger = null)
240249
{
241250
try
242251
{
243-
var templates = await GetTemplatesCachedAsync();
252+
var templates = await GetTemplatesCachedAsync(logger);
244253
return templates.Any(t =>
245254
t.ShortNameList.Any(sn => sn.Equals(templateShortName, StringComparison.OrdinalIgnoreCase)));
246255
}

0 commit comments

Comments
 (0)