If you need to troubleshoot the caching feature, you can enable verbose logging.
With dependency injection
If your application utilizes dependency injection, add the .NET logging service as usual using the AddLogging extension method. The the AddMetalamaCaching extension method automatically uses logging when available.
Therefore, to troubleshoot caching, just set the minimum caching level to Debug
using the SetMinimumLevel method.
The following code snippet illustrates this:
16 // Add logging.
17 builder.ConfigureLogging(
18 logging =>
19 logging.SetMinimumLevel( LogLevel.Debug ) );
Example: Logging of caching with dependency injection
The following is an update to the getting started example, with logging enabled. You can observe detailed logging in the program output.
1using Metalama.Patterns.Caching.Aspects;
2using System;
3
4namespace Doc.Logging;
5
6public sealed class CloudCalculator
7{
8 public int OperationCount { get; private set; }
9
10 [Cache]
11 public int Add( int a, int b )
12 {
13 Console.WriteLine( "Doing some very hard work." );
14
15 this.OperationCount++;
16
17 return a + b;
18 }
19}
1using Metalama.Patterns.Caching;
2using Metalama.Patterns.Caching.Aspects;
3using Metalama.Patterns.Caching.Aspects.Helpers;
4using System;
5using System.Reflection;
6
7namespace Doc.Logging;
8
9public sealed class CloudCalculator
10{
11 public int OperationCount { get; private set; }
12
13 [Cache]
14 public int Add(int a, int b)
15 {
16 static object? Invoke(object? instance, object?[] args)
17 {
18 return ((CloudCalculator)instance).Add_Source((int)args[0], (int)args[1]);
19 }
20
21 return _cachingService.GetFromCacheOrExecute<int>(_cacheRegistration_Add, this, new object[] { a, b }, Invoke);
22 }
23
24 private int Add_Source(int a, int b)
25 {
26 Console.WriteLine("Doing some very hard work.");
27
28 this.OperationCount++;
29
30 return a + b;
31 }
32
33 private static readonly CachedMethodMetadata _cacheRegistration_Add;
34 private ICachingService _cachingService;
35
36 static CloudCalculator()
37 {
38 _cacheRegistration_Add = CachedMethodMetadata.Register(typeof(CloudCalculator).GetMethod("Add", BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(int), typeof(int) }, null).ThrowIfMissing("CloudCalculator.Add(int, int)"), new CachedMethodConfiguration() { AbsoluteExpiration = null, AutoReload = null, IgnoreThisParameter = null, Priority = null, ProfileName = (string?)null, SlidingExpiration = null }, false);
39 }
40
41 public CloudCalculator(ICachingService? cachingService = default)
42 {
43 this._cachingService = cachingService ?? throw new System.ArgumentNullException(nameof(cachingService));
44 }
45}
1using Microsoft.Extensions.Hosting;
2using System;
3using Metalama.Documentation.Helpers.ConsoleApp;
4
5namespace Doc.Logging;
6
7public sealed class ConsoleMain : IConsoleMain
8{
9 private readonly CloudCalculator _cloudCalculator;
10
11 public ConsoleMain( CloudCalculator cloudCalculator )
12 {
13 this._cloudCalculator = cloudCalculator;
14 }
15
16 public void Execute()
17 {
18 for ( var i = 0; i < 3; i++ )
19 {
20 var value = this._cloudCalculator.Add( 1, 1 );
21 Console.WriteLine( $"CloudCalculator returned {value}." );
22 }
23
24 Console.WriteLine(
25 $"In total, CloudCalculator performed {this._cloudCalculator.OperationCount} operation(s)." );
26 }
27}
Processing invocation of method Int32 Add(Int32, Int32): Starting Key="Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)". GetItem( backend = "{MemoryCachingBackend Id=27718499-55d6-4a98-96ad-3c122582f5e2, Status=Default}" key = "Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)" ): Starting GetItem( backend = "{MemoryCachingBackend Id=27718499-55d6-4a98-96ad-3c122582f5e2, Status=Default}" key = "Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)" ): Succeeded, result = Cache miss. Cache miss: Key="Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)". Doing some very hard work. SetItem( backend = "{MemoryCachingBackend Id=27718499-55d6-4a98-96ad-3c122582f5e2, Status=Initialized}" key = "Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)" ): Starting SetItem( backend = "{MemoryCachingBackend Id=27718499-55d6-4a98-96ad-3c122582f5e2, Status=Initialized}" key = "Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)" ): Succeeded Processing invocation of method Int32 Add(Int32, Int32): Succeeded CloudCalculator returned 2. Processing invocation of method Int32 Add(Int32, Int32): Starting Key="Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)". GetItem( backend = "{MemoryCachingBackend Id=27718499-55d6-4a98-96ad-3c122582f5e2, Status=Initialized}" key = "Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)" ): Starting GetItem( backend = "{MemoryCachingBackend Id=27718499-55d6-4a98-96ad-3c122582f5e2, Status=Initialized}" key = "Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)" ): Succeeded, result = Cache hit. Cache hit: Key="Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)". Processing invocation of method Int32 Add(Int32, Int32): Succeeded CloudCalculator returned 2. Processing invocation of method Int32 Add(Int32, Int32): Starting Key="Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)". GetItem( backend = "{MemoryCachingBackend Id=27718499-55d6-4a98-96ad-3c122582f5e2, Status=Initialized}" key = "Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)" ): Starting GetItem( backend = "{MemoryCachingBackend Id=27718499-55d6-4a98-96ad-3c122582f5e2, Status=Initialized}" key = "Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)" ): Succeeded, result = Cache hit. Cache hit: Key="Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)". Processing invocation of method Int32 Add(Int32, Int32): Succeeded CloudCalculator returned 2. In total, CloudCalculator performed 1 operation(s).
1using Flashtrace;
2using Metalama.Documentation.Helpers.ConsoleApp;
3using Metalama.Patterns.Caching.Building;
4using Microsoft.Extensions.DependencyInjection;
5using Microsoft.Extensions.Logging;
6
7namespace Doc.Logging;
8
9internal static class Program
10{
11 public static void Main()
12 {
13 var builder = ConsoleApp.CreateBuilder();
14
15 //
16 // Add logging.
17 builder.ConfigureLogging(
18 logging =>
19 logging.SetMinimumLevel( LogLevel.Debug ) );
20 //
21
22 // Add the caching service.
23 builder.Services.AddMetalamaCaching();
24
25 // Add other components as usual, then run the application.
26 builder.Services.AddConsoleMain<ConsoleMain>();
27 builder.Services.AddSingleton<CloudCalculator>();
28
29 using var app = builder.Build();
30 app.Run();
31 }
32}
Without dependency injection
The CachingService object and other components of Metalama Caching acquire the IFlashtraceLoggerFactory interface through the IServiceProvider. To enable logging, you must provide an implementation of IServiceProvider that supports the IFlashtraceLoggerFactory interface. Then, pass this IServiceProvider to the CachingService.Create method. You can use the TraceSourceLoggerFactory class, which relies on the TraceSource system class.
If you plan to implement the IFlashtraceLoggerFactory yourself, you may find the SimpleFlashtraceLogger useful.