-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add cache admin stats and move some shit internally
- Loading branch information
Showing
6 changed files
with
153 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Reflection.Emit; | ||
using Microsoft.Extensions.Caching.Memory; | ||
|
||
namespace ReplayBrowser.Helpers; | ||
|
||
public static class MemoryCacheExtensions | ||
{ | ||
#region Microsoft.Extensions.Caching.Memory_6_OR_OLDER | ||
|
||
private static readonly Lazy<Func<MemoryCache, object>> GetEntries6 = | ||
new Lazy<Func<MemoryCache, object>>(() => (Func<MemoryCache, object>)Delegate.CreateDelegate( | ||
typeof(Func<MemoryCache, object>), | ||
typeof(MemoryCache).GetProperty("EntriesCollection", BindingFlags.NonPublic | BindingFlags.Instance).GetGetMethod(true), | ||
throwOnBindFailure: true)); | ||
|
||
#endregion | ||
|
||
#region Microsoft.Extensions.Caching.Memory_7_OR_NEWER | ||
|
||
private static readonly Lazy<Func<MemoryCache, object>> GetCoherentState = | ||
new Lazy<Func<MemoryCache, object>>(() => | ||
CreateGetter<MemoryCache, object>(typeof(MemoryCache) | ||
.GetField("_coherentState", BindingFlags.NonPublic | BindingFlags.Instance))); | ||
|
||
private static readonly Lazy<Func<object, IDictionary>> GetEntries7 = | ||
new Lazy<Func<object, IDictionary>>(() => | ||
CreateGetter<object, IDictionary>(typeof(MemoryCache) | ||
.GetNestedType("CoherentState", BindingFlags.NonPublic) | ||
.GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance))); | ||
|
||
private static Func<TParam, TReturn> CreateGetter<TParam, TReturn>(FieldInfo field) | ||
{ | ||
var methodName = $"{field.ReflectedType.FullName}.get_{field.Name}"; | ||
var method = new DynamicMethod(methodName, typeof(TReturn), new[] { typeof(TParam) }, typeof(TParam), true); | ||
var ilGen = method.GetILGenerator(); | ||
ilGen.Emit(OpCodes.Ldarg_0); | ||
ilGen.Emit(OpCodes.Ldfld, field); | ||
ilGen.Emit(OpCodes.Ret); | ||
return (Func<TParam, TReturn>)method.CreateDelegate(typeof(Func<TParam, TReturn>)); | ||
} | ||
|
||
#endregion | ||
|
||
private static readonly Func<MemoryCache, IDictionary> GetEntries = | ||
Assembly.GetAssembly(typeof(MemoryCache)).GetName().Version.Major < 7 | ||
? (Func<MemoryCache, IDictionary>)(cache => (IDictionary)GetEntries6.Value(cache)) | ||
: cache => GetEntries7.Value(GetCoherentState.Value(cache)); | ||
|
||
public static ICollection GetKeys(this IMemoryCache memoryCache) => | ||
GetEntries((MemoryCache)memoryCache).Keys; | ||
|
||
public static IEnumerable<T> GetKeys<T>(this IMemoryCache memoryCache) => | ||
memoryCache.GetKeys().OfType<T>(); | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
@page "/account/admin/stats" | ||
@using System.Text.Json | ||
@using Microsoft.AspNetCore.Authorization | ||
@using Microsoft.AspNetCore.Components.Authorization | ||
@using Microsoft.Extensions.Caching.Memory | ||
@using ReplayBrowser.Helpers | ||
@using ReplayBrowser.Services | ||
@using Microsoft.AspNetCore.Components.Web | ||
@attribute [Authorize] | ||
@inject IMemoryCache MemoryCache | ||
@inject AuthenticationStateProvider AuthenticationStateProvider | ||
@inject AccountService AccountService | ||
@inject NavigationManager NavigationManager | ||
|
||
<link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/themes/prism.min.css" rel="stylesheet" /> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/prism.min.js"></script> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/components/prism-json.min.js"></script> | ||
|
||
<PageTitle>Cache Stats</PageTitle> | ||
|
||
<h3>AdminStats</h3> | ||
@if(!_authed) | ||
{ | ||
<div class="alert alert-danger" role="alert"> | ||
Not authorized | ||
</div> | ||
} | ||
else | ||
{ | ||
var stats = MemoryCache.GetCurrentStatistics(); | ||
if (stats == null) | ||
{ | ||
<div class="alert alert-info" role="alert"> | ||
No stats available | ||
</div> | ||
} | ||
else | ||
{ | ||
<div class="card"> | ||
<div class="card-body"> | ||
<p>Total hits: <span class="badge bg-primary">@stats.TotalHits</span></p> | ||
<p>Total misses: <span class="badge bg-danger">@stats.TotalMisses</span></p> | ||
<p>Total entries: <span class="badge bg-info">@stats.CurrentEntryCount</span></p> | ||
<p>Estimated size: <span class="badge bg-warning">@stats.CurrentEstimatedSize</span></p> | ||
</div> | ||
</div> | ||
} | ||
|
||
var keys = MemoryCache.GetKeys(); | ||
foreach (var key in keys) | ||
{ | ||
var entry = MemoryCache.Get(key); | ||
|
||
<div class="card mt-3"> | ||
<div class="card-body"> | ||
<p> | ||
Key: <span class="text-muted">@key</span><br/> | ||
Value: | ||
<pre><code class="language-json">@JsonSerializer.Serialize(entry, new JsonSerializerOptions() { WriteIndented = true })</code></pre><br/> | ||
</p> | ||
</div> | ||
</div> | ||
} | ||
|
||
<script> | ||
$(document).ready(function() { | ||
Prism.highlightAll(); | ||
}); | ||
</script> | ||
} | ||
@code { | ||
private bool _authed = false; | ||
|
||
protected override async Task OnInitializedAsync() | ||
{ | ||
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); | ||
var user = await AccountService.GetAccount(authState); | ||
|
||
if (user == null || !user.IsAdmin) | ||
{ | ||
NavigationManager.NavigateTo("/"); | ||
return; | ||
} | ||
|
||
_authed = true; | ||
} | ||
} |
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters