-
Notifications
You must be signed in to change notification settings - Fork 15
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
Local object cache viewer #36
Merged
Merged
Changes from 4 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
33dccab
added Local Object Cache functionality
joemayberry 80b0e6f
some minor code fixes and refactorings
valdisiljuconoks 7cfa4d3
added object size
valdisiljuconoks 45d8c35
Added ViewObjectSize as optional action
valdisiljuconoks 3f3c41c
Added .Take(10k) to prevent potential out of mem case for installatio…
valdisiljuconoks File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
125 changes: 125 additions & 0 deletions
125
DeveloperTools/Controllers/LocalObjectCacheController.cs
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,125 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Runtime.Serialization.Formatters.Binary; | ||
using System.Web.Mvc; | ||
using System.Web.Routing; | ||
using DeveloperTools.Core; | ||
using DeveloperTools.Models; | ||
using EPiServer.Core; | ||
using EPiServer.Framework.Cache; | ||
|
||
namespace DeveloperTools.Controllers | ||
{ | ||
public class LocalObjectCacheController : DeveloperToolsController | ||
{ | ||
private readonly ISynchronizedObjectInstanceCache _cache; | ||
|
||
public LocalObjectCacheController(ISynchronizedObjectInstanceCache cache) | ||
{ | ||
_cache = cache; | ||
} | ||
|
||
public ActionResult Index(string FilteredBy, bool os = false) | ||
{ | ||
return View(PrepareViewModel(FilteredBy, os)); | ||
} | ||
|
||
[HttpParamAction] | ||
public ActionResult RemoveLocalCache(string[] cacheKeys, bool os) | ||
{ | ||
if(cacheKeys != null) | ||
{ | ||
foreach (string key in cacheKeys) | ||
{ | ||
_cache.RemoveLocal(key); | ||
} | ||
} | ||
|
||
return RedirectToAction("Index", new RouteValueDictionary(new { os })); | ||
} | ||
|
||
[HttpParamAction] | ||
public ActionResult RemoveLocalRemoteCache(string[] cacheKeys, bool os) | ||
{ | ||
if(cacheKeys != null) | ||
{ | ||
foreach (string key in cacheKeys) | ||
{ | ||
_cache.RemoveLocal(key); | ||
_cache.RemoveRemote(key); | ||
} | ||
} | ||
|
||
return RedirectToAction("Index", new RouteValueDictionary(new { os })); | ||
} | ||
|
||
[HttpParamAction] | ||
public ActionResult ViewObjectSize() | ||
{ | ||
return RedirectToAction("Index", new RouteValueDictionary(new { os = true })); | ||
} | ||
|
||
private LocalObjectCache PrepareViewModel(string FilteredBy, bool viewObjectSize) | ||
{ | ||
var model = new LocalObjectCache(); | ||
|
||
var cachedEntries = HttpContext.Cache.Cast<DictionaryEntry>(); | ||
|
||
switch (FilteredBy) | ||
{ | ||
case "pages": | ||
model.CachedItems = ConvertToListItem(cachedEntries.Where(item => item.Value is PageData), viewObjectSize); | ||
break; | ||
case "content": | ||
model.CachedItems = ConvertToListItem(cachedEntries.Where(item => item.Value is IContent), viewObjectSize); | ||
break; | ||
default: | ||
model.CachedItems = ConvertToListItem(cachedEntries, viewObjectSize); | ||
break; | ||
} | ||
|
||
model.FilteredBy = FilteredBy; | ||
model.Choices = new[] | ||
{ | ||
new SelectListItem { Text = "All Cached Objects", Value = "all" }, | ||
new SelectListItem { Text = "Any Content", Value = "content" }, | ||
new SelectListItem { Text = "Pages Only", Value = "pages" } | ||
}; | ||
|
||
model.ViewObjectSize = viewObjectSize; | ||
return model; | ||
} | ||
|
||
private IEnumerable<LocalObjectCacheItem> ConvertToListItem(IEnumerable<DictionaryEntry> cachedEntries, bool viewObjectSize) => | ||
cachedEntries.Select(e => new LocalObjectCacheItem | ||
{ | ||
Key = e.Key.ToString(), | ||
Value = e.Value, | ||
Size = viewObjectSize ? GetObjectSize(e.Value) : 0 | ||
}).ToList(); | ||
|
||
private static long GetObjectSize(object obj) | ||
{ | ||
if(obj == null) | ||
return 0; | ||
|
||
try | ||
{ | ||
using (Stream s = new MemoryStream()) | ||
{ | ||
var formatter = new BinaryFormatter(); | ||
formatter.Serialize(s, obj); | ||
|
||
return s.Length; | ||
} | ||
} | ||
catch (Exception) | ||
{ | ||
return -1; | ||
} | ||
} | ||
} | ||
} |
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
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,21 @@ | ||
using System; | ||
using System.Reflection; | ||
using System.Web.Mvc; | ||
|
||
namespace DeveloperTools.Core | ||
{ | ||
public class HttpParamActionAttribute : ActionNameSelectorAttribute | ||
{ | ||
public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) | ||
{ | ||
if(actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase)) | ||
return true; | ||
|
||
if(!actionName.Equals("Action", StringComparison.InvariantCultureIgnoreCase)) | ||
return false; | ||
|
||
var request = controllerContext.RequestContext.HttpContext.Request; | ||
return request[methodInfo.Name] != null; | ||
} | ||
} | ||
} |
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
Binary file not shown.
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,25 @@ | ||
using System.Collections.Generic; | ||
using System.Web.Mvc; | ||
|
||
namespace DeveloperTools.Models | ||
{ | ||
public class LocalObjectCache | ||
{ | ||
public IEnumerable<LocalObjectCacheItem> CachedItems { get; set; } | ||
|
||
public string FilteredBy { get; set; } | ||
|
||
public IEnumerable<SelectListItem> Choices { get; set; } | ||
|
||
public bool ViewObjectSize { get; set; } | ||
} | ||
|
||
public class LocalObjectCacheItem | ||
{ | ||
public string Key { get; set; } | ||
|
||
public object Value { get; set; } | ||
|
||
public long Size { get; set; } | ||
} | ||
} |
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
108 changes: 108 additions & 0 deletions
108
DeveloperTools/modules/_protected/EPiServer.DeveloperTools/Views/LocalObjectCache/Index.aspx
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,108 @@ | ||
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<DeveloperTools.Models.LocalObjectCache>" MasterPageFile="../Shared/DeveloperTools.Master" %> | ||
|
||
<asp:Content ID="Styles" runat="server" ContentPlaceHolderID="HeaderStyles"> | ||
<style type="text/css"> | ||
.table-column-width { | ||
width: 30%; | ||
} | ||
.stripe tbody tr:nth-child(even) { | ||
background-color: #f0f2f2; | ||
} | ||
</style> | ||
</asp:Content> | ||
|
||
<asp:Content ID="Content" runat="server" ContentPlaceHolderID="MainRegion"> | ||
<link rel="stylesheet" type="text/css" href="//ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/css/jquery.dataTables.css" /> | ||
<script type="text/javascript" language="javascript" src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js"></script> | ||
<script src="//ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/jquery.dataTables.min.js" type="text/javascript"></script> | ||
|
||
<div class="epi-contentContainer epi-padding"> | ||
<div class="epi-contentArea"> | ||
<h1>Local Object Cache</h1> | ||
<p class="EP-systemInfo">This tool shows all of the current items in the local object cache, and allows the deletion of one or more cached items.</p> | ||
</div> | ||
|
||
<div class="epi-contentArea epi-formArea"> | ||
<%using (Html.BeginForm("Index", "LocalObjectCache", FormMethod.Post)) | ||
{ %> | ||
<%= Html.AntiForgeryToken() %> | ||
|
||
<table class="table"> | ||
<tr> | ||
<td>Filter By</td> | ||
<td><%= Html.DropDownListFor(m => m.FilteredBy, Model.Choices) %></td> | ||
<td> | ||
<span class="epi-cmsButton"> | ||
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Refresh" type="submit" name="filter" id="filter" value="Filter" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" /> | ||
</span> | ||
</td> | ||
</tr> | ||
</table> | ||
<% } %> | ||
|
||
<% using (Html.BeginForm("Action", "LocalObjectCache", FormMethod.Post)) | ||
{ %> | ||
<div class="epi-contentArea"> | ||
<p class="EP-systemInfo">Total count of cached items: <%= Model.CachedItems.Count() %></p> | ||
</div> | ||
<div class="epi-buttonDefault"> | ||
<span class="epi-cmsButton"> | ||
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Delete" type="submit" name="RemoveLocalCache" id="RemoveLocalCache" value="Remove Local Cache Items" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" /> | ||
</span> | ||
<span class="epi-cmsButton"> | ||
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Delete" type="submit" name="removeLocalRemoteCache" id="removeLocalRemoteCache" value="Remove Local and Remote Cache Items" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" /> | ||
</span> | ||
<span class="epi-cmsButton"> | ||
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-ViewMode" type="submit" name="ViewObjectSize" id="ViewObjectSize" value="View Object Size" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" /> | ||
</span> | ||
</div> | ||
|
||
<table class="table table-condensed table-bordered table-condensed stripe"> | ||
<thead> | ||
<tr> | ||
<th><input type="checkbox" id="clearAll" name="clearAll" onClick="toggle(this)" value="true" /></th> | ||
<th class="table-column-width">Key</th> | ||
<th class="table-column-width">Type</th> | ||
<th>Size</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<% foreach (var item in Model.CachedItems) | ||
{ %> | ||
<tr> | ||
<td class="center"><input type="checkbox" id="<%= item.Key %>" name="cacheKeys" value="<%= item.Key %>" /></td> | ||
<td><%= item.Key %></td> | ||
<td><%= item.Value.GetType() %></td> | ||
<td><%= item.Size %></td> | ||
</tr> | ||
<% } %> | ||
</tbody> | ||
</table> | ||
|
||
<div class="epi-buttonDefault"> | ||
<span class="epi-cmsButton"> | ||
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Delete" type="submit" name="RemoveLocalCache" id="RemoveLocalCacheBottom" value="Remove Local Cache Items" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" /> | ||
</span> | ||
<span class="epi-cmsButton"> | ||
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Delete" type="submit" name="removeLocalRemoteCache" id="removeLocalRemoteCacheBottom" value="Remove Local and Remote Cache Items" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" /> | ||
</span> | ||
<span class="epi-cmsButton"> | ||
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-ViewMode" type="submit" name="ViewObjectSize" id="ViewObjectSize" value="View Object Size" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" /> | ||
</span> | ||
</div> | ||
|
||
<input type="hidden" id="os" name="os" value="<%= Model.ViewObjectSize %>"/> | ||
<% } %> | ||
</div> | ||
</div> | ||
|
||
<script language="JavaScript"> | ||
function toggle(source) { | ||
checkboxes = document.getElementsByName('cacheKeys'); | ||
for (var i = 0, n = checkboxes.length; i < n; i++) { | ||
checkboxes[i].checked = source.checked; | ||
} | ||
} | ||
</script> | ||
</asp:Content> |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think just adding a Take(10,000) here would protect against issues with really large caches until server side paging is in place. This code otherwise have the potential of running a server out of memory.