-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Let consumers of MemoryCache access metrics #50406
Comments
Tagging subscribers to this area: @eerhardt, @maryamariyan, @michaelgsharp Issue DetailsBackground and MotivationTBA. API suggestion
class MemoryCache
{
MemoryCacheStatistics GetCurrentStatistics() { ... }
...
}
struct MemoryCacheStatistics
{
long ObjectsStored { get; }
long CacheRequests { get; }
long CacheHits { get; }
long CacheCount { get; }
long EstimatedSize { get; }
... // any other counters we also need
} TODO:
Usage ExamplesTBA. Alternative DesignsPresented here, we'd be implementing EventSource ourselves in the assemblies. RisksThe design assumes the counters are cheap enough that we could track them all the time. If that is not the case then we'd want some APIs that turn the tracking on or subscribes. TBA. cc: @noahfalk
|
I like this design better. How would this work with the fact that the cache is an interface though... |
I would retitle this as 'let consumers of MemoryCache access metrics'. We don't need to presume they will create an EventSource/EventCounters (and I am guessing they won't)
Make a time machine and stop making everything interfaces : D
IMemoryCache cache = ...
if(cache is IMemoryCacheStatistics stats)
{
MemoryCacheStatisticsSnapshot snapshot = stats.GetCurrentStatistics();
}
else
{
// not supported on older builds, user has to deal with it or upgrade to a newer version
} |
OR, we can use default interface members on .NET Core only...😄. |
+1 😄 |
Updated to: public class MemoryCacheExtensions
{
public static MemoryCacheStatistics GetCurrentStatistics(this IMemoryCache) { ... }
} |
I'm not familiar with the potential implementation, but we could consider hinting or enforcing collection interval for these metrics. For example if the stat for ObjectsStored is really expensive to calculate or only updated every 30 seconds there is no point the consumer fetching the statistics more frequently right? In fact they may incur unexpected perf hits doing so. This proposal may hide potential complexity of getting these stats. This is a non-issue of all the stats are cheap to calculate or constantly kept up to date. |
Do we have provision to check the space consumed by each key in the cache ? |
Our team uses memory cache for various scenarios. One of the scenarios is to use several layers of caching to support request routing. Memory cache is used to capture the most up to date routing information. We need to be able to understand the size of the cache in terms of object count vs its usefulness. We also need to be able to monitor memory usage. Having a directional estimate for memory usage is better than not having any estimate and thus relying on available memory or object count to project what the cache might be taking up. We emit some of these metrics by hand currently. Here is the list of helpful metrics in the order of priority as we see it: Number of:
|
Met with @sebastienros to review this API. Here's some new observations: Observation 1: API for IDistributedCacheLooking at ref/Microsoft.Extensions.Caching.Abstractions.cs and ref/Microsoft.Extensions.Caching.Memory.cs and the APIs exposed, it doesn't look like runtime/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryDistributedCache.cs Lines 14 to 16 in 6e05d78
It looks like public static class MemoryCacheExtensions
{
+ public static MemoryCacheStatistics GetCurrentStatistics(this IDistributedCache) { ... }
public static MemoryCacheStatistics GetCurrentStatistics(this IMemoryCache) { ... }
} To inspect a sample usage, I found this API runtime/src/libraries/Microsoft.Extensions.Caching.Memory/tests/CacheServiceExtensionsTests.cs Lines 33 to 56 in 57bfe47
It doesn't seem like there would be a way to access memory cache event counter information for the One concern with exposing this API on the interface is we have no guarantee that (a) IDistributedCache is implemented with a memory cache or not. It might make more sense to expose this API for public static class MemoryCacheExtensions
{
+ public static MemoryCacheStatistics GetCurrentStatistics(this MemoryCache memoryCache) { ... }
} Observation 2: In what ways would the API be used?What would the developer do using the new APIs? For cased where the developer uses the new APIs to create an event counter with them, then they would need to create a timer to extract statistics and show as event counters, rather than querying them using an event pipe. To facilitate with this use case maybe it's worth also adding the event counters, and not just the proposed API. TODO:
Observation 3: Compare approachesUsing event counters is a way for consumers to access the metrics which is the alternative approach presented in #36560). Since there might be multiple instances of the memory cache, using the event counters approach might mean we would have to aggregate statistics (such as cache hit, cache miss) for all memory caches being used. But with the proposed APIs, the memory cache statistics could be retrieved per memory cache. /cc @davidfowl |
@nadyalobalzo I wanted to learn more about your use cases.
UPDATE: Reached out to them offline and learned that they use multiple memory cache instances in their apps so it would be more useful for them to use metrics APIs instead which allows for using dimensions. |
So
|
I think that would be logical yes. |
The feature owners have agreed that they're willing to split the reference assembly to try out a Default Interface Method. We also changed the statistics type to a class (partially from future expansion concerns). public static partial class MemoryCache
{
public MemoryCacheStatistics? GetCurrentStatistics() { throw null; }
}
public partial interface IMemoryCache
{
#if NET_7_OR_GREATER
public MemoryCacheStatistics? GetCurrentStatistics() => null;
#endif
}
public partial class MemoryCacheStatistics
{
public MemoryCacheStatistics() {}
public long TotalMisses { get; init; }
public long TotalHits { get; init; }
public long CurrentEntryCount { get; init; }
public long? CurrentEstimatedSize { get; init; }
} |
Making an API revision request to support opt-in capability. public partial class MemoryCacheOptions : Microsoft.Extensions.Options.IOptions<Microsoft.Extensions.Caching.Memory.MemoryCacheOptions>
{
+ public bool TrackStatistics { get { throw null; } set { } }
} For more information refer to #66479 (comment) |
namespace Microsoft.Extensions.Caching.Memory;
public partial class MemoryCacheOptions : IOptions<MemoryCacheOptions>
{
public bool TrackStatistics { get; set; }
}
// Already approved API:
//
// public static partial class MemoryCache
// {
// public MemoryCacheStatistics? GetCurrentStatistics();
// }
//
// public partial interface IMemoryCache
// {
// #if NET_7_OR_GREATER
// public MemoryCacheStatistics? GetCurrentStatistics() => null;
// #endif
// }
//
// public partial class MemoryCacheStatistics
// {
// public MemoryCacheStatistics() {}
//
// public long TotalMisses { get; init; }
// public long TotalHits { get; init; }
// public long CurrentEntryCount { get; init; }
// public long? CurrentEstimatedSize { get; init; }
// } |
Background and Motivation
We want to add an API to expose memory cache statistics to allow consumers of caching to write their own EventSource/EventCounters and their own metrics.
Usage sample
Check out this gist: https://gist.github.com/maryamariyan/487816f724993c88a39fa29fe397aede
Approved API
Video
The feature owners have agreed that they're willing to split the reference assembly to try out a Default Interface Method.
We also changed the statistics type to a class (partially from future expansion concerns).
Original Description
## API suggestionIn contrast,
System.Runtime.Caching
already presented the following counters:Usage Examples
Microsoft.Extensions.Caching.Memory
:We would have metrics built-in using the proposed API. But developers would also be able to add their own event counters, using the proposed API.
As a developer, I may end up using
GetCurrentStatistics
in a callback passed down to a metrics API or an event counter.We want
MemoryCacheStatistics
to help developer custom build their own metrics such as:or
CacheHitRatio
as CacheHits/CacheRequests.Link to prototype here, does not use the API but shows how we could add built-in metrics.
Sample usage/screenshot for event counter:
Scope for this issue is:
Alternative Designs
Presented here, we'd be implementing EventSource ourselves in the assemblies.
Risks
The design assumes the metrics are cheap enough that we could track them all the time. If that is not the case then we'd want some APIs that turn the tracking on or subscribes.
TBA.
cc: @noahfalk
The text was updated successfully, but these errors were encountered: