diff --git a/src/snek/app.py b/src/snek/app.py
index 6ffee4f..cb4de21 100644
--- a/src/snek/app.py
+++ b/src/snek/app.py
@@ -44,6 +44,7 @@ from snek.view.status import StatusView
 from snek.view.terminal import TerminalSocketView, TerminalView
 from snek.view.upload import UploadView
 from snek.view.web import WebView
+from snek.view.stats import StatsView
 from snek.webdav import WebdavApplication
 
 SESSION_KEY = b"c79a0c5fda4b424189c427d28c9f7c34"
@@ -169,6 +170,7 @@ class Application(BaseApplication):
         self.router.add_view("/terminal.html", TerminalView)
         self.router.add_view("/drive.json", DriveView)
         self.router.add_view("/drive/{drive}.json", DriveView)
+        self.router.add_view("/stats.json", StatsView)
         self.webdav = WebdavApplication(self)
         self.add_subapp("/webdav", self.webdav)
 
diff --git a/src/snek/system/cache.py b/src/snek/system/cache.py
index e97fdc3..0ecfd47 100644
--- a/src/snek/system/cache.py
+++ b/src/snek/system/cache.py
@@ -13,10 +13,12 @@ class Cache:
         self.app = app
         self.cache = {}
         self.max_items = max_items
+        self.stats = {}
         self.lru = []
         self.version = ((42 + 420 + 1984 + 1990 + 10 + 6 + 71 + 3004 + 7245) ^ 1337) + 4
 
     async def get(self, args):
+        await self.update_stat(args, 'get')
         try:
             self.lru.pop(self.lru.index(args))
         except:
@@ -29,6 +31,25 @@ class Cache:
         # print("Cache hit!", args, flush=True)
         return self.cache[args]
 
+    async def get_stats(self):
+        all_ = []
+        for key in self.lru:
+            all_.append({'key': key, 'set': self.stats[key]['set'], 'get': self.stats[key]['get'], 'delete': self.stats[key]['delete'],'value': str(self.serialize(self.cache[key].record))})
+        return all_
+
+    def serialize(self, obj):
+        cpy = obj.copy()
+        cpy.pop('created_at', None)
+        cpy.pop('deleted_at', None)
+        cpy.pop('email', None)
+        cpy.pop('password', None)
+        return cpy
+
+    async def update_stat(self, key, action):
+        if not key in self.stats:
+            self.stats[key] = {'set':0, 'get':0, 'delete':0}
+        self.stats[key][action] = self.stats[key][action] + 1
+
     def json_default(self, value):
         # if hasattr(value, "to_json"):
         #    return value.to_json()
@@ -49,6 +70,7 @@ class Cache:
     async def set(self, args, result):
         is_new = args not in self.cache
         self.cache[args] = result
+        await self.update_stat(args, 'set')
         try:
             self.lru.pop(self.lru.index(args))
         except (ValueError, IndexError):
@@ -64,6 +86,7 @@ class Cache:
             # print(f"Cache store! {len(self.lru)} items. New version:", self.version, flush=True)
 
     async def delete(self, args):
+        await self.update_stat(args, 'delete')
         if args in self.cache:
             try:
                 self.lru.pop(self.lru.index(args))
diff --git a/src/snek/system/model.py b/src/snek/system/model.py
index 1aef4ae..9e9830d 100644
--- a/src/snek/system/model.py
+++ b/src/snek/system/model.py
@@ -145,6 +145,9 @@ class Validator:
             raise ValueError(f"Errors: {errors}.")
         return True
 
+    def __repr__(self):
+        return str(self.to_json())
+
     @property
     async def is_valid(self):
         try: