MetalamaConceptual documentationUsing Metalama PatternsCachingTroubleshooting
Open sandboxFocusImprove this doc

Troubleshooting Metalama Caching

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 <xref:Microsoft.Extensions.DependencyInjection.LoggingServiceCollectionExtensions.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 <xref:Microsoft.Extensions.Logging.LoggingBuilderExtensions.SetMinimumLevel*> method.

The following code snippet illustrates this:

16            builder.ConfigureLogging(
17                logging =>
18                    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 Microsoft.Extensions.Hosting;
2using System;
3using Metalama.Documentation.Helpers.ConsoleApp;
4
5namespace Doc.Logging
6{
7    public 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( $"In total, CloudCalculator performed {this._cloudCalculator.OperationCount} operation(s)." );
25        }
26    }
27}
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{
9    internal static class Program
10    {
11        public static void Main()
12        {
13            var builder = ConsoleApp.CreateBuilder();
14
15            // Add logging.
16            builder.ConfigureLogging(
17                logging =>
18                    logging.SetMinimumLevel( LogLevel.Debug ) );
19
20            // Add the caching service.
21            builder.Services.AddMetalamaCaching();
22
23            // Add other components as usual, then run the application.
24            builder.Services.AddConsoleMain<ConsoleMain>();
25            builder.Services.AddSingleton<CloudCalculator>();
26
27            using var app = builder.Build();
28            app.Run();
29        }
30    }
31}
Source Code
1using Metalama.Patterns.Caching.Aspects;
2using System;

3

4namespace Doc.Logging

5{
6    public 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    }















20}
Transformed Code
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{
9    public 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        {
39            CloudCalculator._cacheRegistration_Add = CachedMethodMetadata.Register(RunTimeHelpers.ThrowIfMissing(typeof(CloudCalculator).GetMethod("Add", BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(int), typeof(int) }, null)!, "CloudCalculator.Add(int, int)"), new CachedMethodConfiguration() { AbsoluteExpiration = null, AutoReload = null, IgnoreThisParameter = null, Priority = null, ProfileName = (string?)null, SlidingExpiration = null }, false);
40        }
41
42        public CloudCalculator
43        (ICachingService? cachingService = default)
44        {
45            this._cachingService = cachingService ?? throw new System.ArgumentNullException(nameof(cachingService));
46        }
47    }
48}
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=ae214eac-fae7-4e3e-bd48-230c5d14b4b9, Status=Default}" key = "Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)" ): Starting
GetItem( backend = "{MemoryCachingBackend Id=ae214eac-fae7-4e3e-bd48-230c5d14b4b9, 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=ae214eac-fae7-4e3e-bd48-230c5d14b4b9, Status=Initialized}" key = "Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)" ): Starting
SetItem( backend = "{MemoryCachingBackend Id=ae214eac-fae7-4e3e-bd48-230c5d14b4b9, 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=ae214eac-fae7-4e3e-bd48-230c5d14b4b9, Status=Initialized}" key = "Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)" ): Starting
GetItem( backend = "{MemoryCachingBackend Id=ae214eac-fae7-4e3e-bd48-230c5d14b4b9, 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=ae214eac-fae7-4e3e-bd48-230c5d14b4b9, Status=Initialized}" key = "Doc.Logging.CloudCalculator.Add(this={Doc.Logging.CloudCalculator}, (int) 1, (int) 1)" ): Starting
GetItem( backend = "{MemoryCachingBackend Id=ae214eac-fae7-4e3e-bd48-230c5d14b4b9, 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).

Without dependency injection

The CachingService object and other components of Metalama Caching acquire the IFlashtraceLoggerFactory interface through the <xref:System.IServiceProvider>. To enable logging, you must provide an implementation of <xref:System.IServiceProvider> that supports the IFlashtraceLoggerFactory interface. Then, pass this <xref:System.IServiceProvider> to the CachingService.Create method. You can use the TraceSourceLoggerFactory class, which relies on the <xref:System.Diagnostics.TraceSource> system class.

If you plan to implement the IFlashtraceLoggerFactory yourself, you may find the SimpleFlashtraceLogger useful.