diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index a08365125b48166d4136a631a625c64a581943d1..7d4ee4c576774347826e14123ebbf82761a589e9 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -20,6 +20,7 @@ const AdminUsers = lazy(() => import("@/pages/Admin/Users"));
 const AdminInvites = lazy(() => import("@/pages/Admin/Invitations"));
 const AdminWorkspaces = lazy(() => import("@/pages/Admin/Workspaces"));
 const AdminSystem = lazy(() => import("@/pages/Admin/System"));
+const AdminLogs = lazy(() => import("@/pages/Admin/Logging"));
 const GeneralChats = lazy(() => import("@/pages/GeneralSettings/Chats"));
 const GeneralAppearance = lazy(
   () => import("@/pages/GeneralSettings/Appearance")
@@ -79,6 +80,10 @@ export default function App() {
                 path="/settings/vector-database"
                 element={<AdminRoute Component={GeneralVectorDatabase} />}
               />
+              <Route
+                path="/settings/event-logs"
+                element={<AdminRoute Component={AdminLogs} />}
+              />
               <Route
                 path="/settings/embed-config"
                 element={<AdminRoute Component={EmbedConfigSetup} />}
diff --git a/frontend/src/components/SettingsSidebar/index.jsx b/frontend/src/components/SettingsSidebar/index.jsx
index 2eba84a9d1d332fcdc36ad2c2bc134c8f90dd4e3..5fe81363c8442240fec6498717008654eb70c531 100644
--- a/frontend/src/components/SettingsSidebar/index.jsx
+++ b/frontend/src/components/SettingsSidebar/index.jsx
@@ -19,6 +19,7 @@ import {
   List,
   FileCode,
   Plugs,
+  Notepad,
   CodeBlock,
   Barcode,
 } from "@phosphor-icons/react";
@@ -63,7 +64,7 @@ export default function SettingsSidebar() {
           {/* Primary Body */}
           <div className="h-[100%] flex flex-col w-full justify-between pt-4 overflow-y-hidden">
             <div className="h-auto sidebar-items">
-              <div className="flex flex-col gap-y-2 h-[65vh] pb-8 overflow-y-scroll no-scroll">
+              <div className="flex flex-col gap-y-2 h-[100%] pb-8 overflow-y-scroll no-scroll">
                 <Option
                   href={paths.settings.system()}
                   btnText="System Preferences"
@@ -177,6 +178,14 @@ export default function SettingsSidebar() {
                   flex={true}
                   allowedRole={["admin", "manager"]}
                 />
+                <Option
+                  href={paths.settings.logs()}
+                  btnText="Events Logs"
+                  icon={<Notepad className="h-5 w-5 flex-shrink-0" />}
+                  user={user}
+                  flex={true}
+                  allowedRole={["admin"]}
+                />
               </div>
             </div>
             <div>
@@ -299,7 +308,7 @@ export function SidebarMobileHeader() {
             <div className="h-full flex flex-col w-full justify-between pt-4 overflow-y-hidden ">
               <div className="h-auto md:sidebar-items md:dark:sidebar-items">
                 <div
-                  style={{ height: "calc(100vw - -3rem)" }}
+                  style={{ height: "calc(100vw-3rem)" }}
                   className=" flex flex-col gap-y-4 pb-8 overflow-y-scroll no-scroll"
                 >
                   <Option
@@ -417,6 +426,14 @@ export function SidebarMobileHeader() {
                     flex={true}
                     allowedRole={["admin", "manager"]}
                   />
+                  <Option
+                    href={paths.settings.logs()}
+                    btnText="Events Logs"
+                    icon={<Notepad className="h-5 w-5 flex-shrink-0" />}
+                    user={user}
+                    flex={true}
+                    allowedRole={["admin"]}
+                  />
                 </div>
               </div>
               <div>
diff --git a/frontend/src/models/system.js b/frontend/src/models/system.js
index 596348ede8df14ff6c2a32d44f494ea84183b68f..0ffbae69013ddb75cd43e77db502288f216f050b 100644
--- a/frontend/src/models/system.js
+++ b/frontend/src/models/system.js
@@ -389,6 +389,29 @@ const System = {
         return [];
       });
   },
+  eventLogs: async (offset = 0) => {
+    return await fetch(`${API_BASE}/system/event-logs`, {
+      method: "POST",
+      headers: baseHeaders(),
+      body: JSON.stringify({ offset }),
+    })
+      .then((res) => res.json())
+      .catch((e) => {
+        console.error(e);
+        return [];
+      });
+  },
+  clearEventLogs: async () => {
+    return await fetch(`${API_BASE}/system/event-logs`, {
+      method: "DELETE",
+      headers: baseHeaders(),
+    })
+      .then((res) => res.json())
+      .catch((e) => {
+        console.error(e);
+        return { success: false, error: e.message };
+      });
+  },
   deleteChat: async (chatId) => {
     return await fetch(`${API_BASE}/system/workspace-chats/${chatId}`, {
       method: "DELETE",
diff --git a/frontend/src/pages/Admin/Logging/LogRow/index.jsx b/frontend/src/pages/Admin/Logging/LogRow/index.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..0ce89b35a93d05ec5cfa133cb7eba889c1f6b8b6
--- /dev/null
+++ b/frontend/src/pages/Admin/Logging/LogRow/index.jsx
@@ -0,0 +1,105 @@
+import { CaretDown, CaretUp } from "@phosphor-icons/react";
+import { useEffect, useState } from "react";
+
+export default function LogRow({ log }) {
+  const [expanded, setExpanded] = useState(false);
+  const [metadata, setMetadata] = useState(null);
+  const [hasMetadata, setHasMetadata] = useState(false);
+
+  useEffect(() => {
+    function parseAndSetMetadata() {
+      try {
+        let data = JSON.parse(log.metadata);
+        setHasMetadata(Object.keys(data)?.length > 0);
+        setMetadata(data);
+      } catch {}
+    }
+    parseAndSetMetadata();
+  }, [log.metadata]);
+
+  const handleRowClick = () => {
+    if (log.metadata !== "{}") {
+      setExpanded(!expanded);
+    }
+  };
+
+  return (
+    <>
+      <tr
+        onClick={handleRowClick}
+        className={`bg-transparent text-white text-opacity-80 text-sm font-medium ${
+          hasMetadata ? "cursor-pointer hover:bg-white/5" : ""
+        }`}
+      >
+        <EventBadge event={log.event} />
+        <td className="px-6 py-4 border-transparent transform transition-transform duration-200">
+          {log.user.username}
+        </td>
+        <td className="px-6 py-4 border-transparent transform transition-transform duration-200">
+          {log.occurredAt}
+        </td>
+        {hasMetadata && (
+          <>
+            {expanded ? (
+              <td
+                className={`px-2 gap-x-1 flex items-center justify-center transform transition-transform duration-200 hover:scale-105`}
+              >
+                <CaretUp weight="bold" size={20} />
+                <p className="text-xs text-white/50 w-[20px]">hide</p>
+              </td>
+            ) : (
+              <td
+                className={`px-2 gap-x-1 flex items-center justify-center transform transition-transform duration-200 hover:scale-105`}
+              >
+                <CaretDown weight="bold" size={20} />
+                <p className="text-xs text-white/50 w-[20px]">show</p>
+              </td>
+            )}
+          </>
+        )}
+      </tr>
+      <EventMetadata metadata={metadata} expanded={expanded} />
+    </>
+  );
+}
+
+const EventMetadata = ({ metadata, expanded = false }) => {
+  if (!metadata || !expanded) return null;
+  return (
+    <tr className="bg-sidebar">
+      <td
+        colSpan="2"
+        className="px-6 py-4 font-medium text-white rounded-l-2xl"
+      >
+        Event Metadata
+      </td>
+      <td colSpan="4" className="px-6 py-4 rounded-r-2xl">
+        <div className="w-full rounded-lg bg-main-2 p-2 text-white shadow-sm border-white border bg-opacity-10">
+          <pre className="overflow-scroll">
+            {JSON.stringify(metadata, null, 2)}
+          </pre>
+        </div>
+      </td>
+    </tr>
+  );
+};
+
+const EventBadge = ({ event }) => {
+  let colorTheme = { bg: "bg-sky-600/20", text: "text-sky-400 " };
+  if (event.includes("update"))
+    colorTheme = { bg: "bg-yellow-600/20", text: "text-yellow-400 " };
+  if (event.includes("failed_") || event.includes("deleted"))
+    colorTheme = { bg: "bg-red-600/20", text: "text-red-400 " };
+  if (event === "login_event")
+    colorTheme = { bg: "bg-green-600/20", text: "text-green-400 " };
+
+  return (
+    <td className="px-6 py-4 font-medium whitespace-nowrap text-white flex items-center">
+      <span
+        className={`rounded-full ${colorTheme.bg} px-2 py-0.5 text-sm font-medium ${colorTheme.text} shadow-sm`}
+      >
+        {event}
+      </span>
+    </td>
+  );
+};
diff --git a/frontend/src/pages/Admin/Logging/index.jsx b/frontend/src/pages/Admin/Logging/index.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..0219b54a391cce6cd90bc82199e5fe28764ed38f
--- /dev/null
+++ b/frontend/src/pages/Admin/Logging/index.jsx
@@ -0,0 +1,138 @@
+import Sidebar, { SidebarMobileHeader } from "@/components/SettingsSidebar";
+import useQuery from "@/hooks/useQuery";
+import System from "@/models/system";
+import { useEffect, useState } from "react";
+import { isMobile } from "react-device-detect";
+import * as Skeleton from "react-loading-skeleton";
+import LogRow from "./LogRow";
+import showToast from "@/utils/toast";
+
+export default function AdminLogs() {
+  const handleResetLogs = async () => {
+    if (
+      !window.confirm(
+        "Are you sure you want to clear all event logs? This action is irreversible."
+      )
+    )
+      return;
+    const { success, error } = await System.clearEventLogs();
+    if (success) {
+      showToast("Event logs cleared successfully.", "success");
+      setTimeout(() => {
+        window.location.reload();
+      }, 1000);
+    } else {
+      showToast(`Failed to clear logs: ${error}`, "error");
+    }
+  };
+  return (
+    <div className="w-screen h-screen overflow-hidden bg-sidebar flex">
+      {!isMobile && <Sidebar />}
+      <div
+        style={{ height: isMobile ? "100%" : "calc(100% - 32px)" }}
+        className="transition-all duration-500 relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[26px] bg-main-gradient w-full h-full overflow-y-scroll border-4 border-accent"
+      >
+        {isMobile && <SidebarMobileHeader />}
+        <div className="flex flex-col w-full px-1 md:px-20 md:py-12 py-16">
+          <div className="w-full flex flex-col gap-y-1 pb-6 border-white border-b-2 border-opacity-10">
+            <div className="items-center flex gap-x-4">
+              <p className="text-2xl font-semibold text-white">Event Logs</p>
+              <button
+                onClick={handleResetLogs}
+                className="px-4 py-1 rounded-lg text-slate-200/50 text-sm items-center flex gap-x-2 hover:bg-slate-200 hover:text-slate-800"
+              >
+                Clear event logs
+              </button>
+            </div>
+            <p className="text-sm font-base text-white text-opacity-60">
+              View all actions and events happening on this instance for
+              monitoring.
+            </p>
+          </div>
+          <LogsContainer />
+        </div>
+      </div>
+    </div>
+  );
+}
+
+function LogsContainer() {
+  const query = useQuery();
+  const [loading, setLoading] = useState(true);
+  const [logs, setLogs] = useState([]);
+  const [offset, setOffset] = useState(Number(query.get("offset") || 0));
+  const [canNext, setCanNext] = useState(false);
+
+  const handlePrevious = () => {
+    setOffset(Math.max(offset - 1, 0));
+  };
+  const handleNext = () => {
+    setOffset(offset + 1);
+  };
+
+  useEffect(() => {
+    async function fetchLogs() {
+      const { logs: _logs, hasPages = false } = await System.eventLogs(offset);
+      setLogs(_logs);
+      setCanNext(hasPages);
+      setLoading(false);
+    }
+    fetchLogs();
+  }, [offset]);
+
+  if (loading) {
+    return (
+      <Skeleton.default
+        height="80vh"
+        width="100%"
+        highlightColor="#3D4147"
+        baseColor="#2C2F35"
+        count={1}
+        className="w-full p-4 rounded-b-2xl rounded-tr-2xl rounded-tl-sm mt-6"
+        containerClassName="flex w-full"
+      />
+    );
+  }
+
+  return (
+    <>
+      <table className="md:w-5/6 w-full text-sm text-left rounded-lg mt-5">
+        <thead className="text-white text-opacity-80 text-sm font-bold uppercase border-white border-b border-opacity-60">
+          <tr>
+            <th scope="col" className="px-6 py-3">
+              Event Type
+            </th>
+            <th scope="col" className="px-6 py-3">
+              User
+            </th>
+            <th scope="col" className="px-6 py-3">
+              Occurred At
+            </th>
+            <th scope="col" className="px-6 py-3 rounded-tr-lg">
+              {" "}
+            </th>
+          </tr>
+        </thead>
+        <tbody>
+          {!!logs && logs.map((log) => <LogRow key={log.id} log={log} />)}
+        </tbody>
+      </table>
+      <div className="flex w-full justify-between items-center">
+        <button
+          onClick={handlePrevious}
+          className="px-4 py-2 rounded-lg border border-slate-200 text-slate-200 text-sm items-center flex gap-x-2 hover:bg-slate-200 hover:text-slate-800 disabled:invisible"
+          disabled={offset === 0}
+        >
+          Previous Page
+        </button>
+        <button
+          onClick={handleNext}
+          className="px-4 py-2 rounded-lg border border-slate-200 text-slate-200 text-sm items-center flex gap-x-2 hover:bg-slate-200 hover:text-slate-800 disabled:invisible"
+          disabled={!canNext}
+        >
+          Next Page
+        </button>
+      </div>
+    </>
+  );
+}
diff --git a/frontend/src/utils/paths.js b/frontend/src/utils/paths.js
index 8fbaacecd2c8cd4e410e4b0e2bf8eaf01523ed3b..06428c608ffa8764bc5cba7df2f7221d3bfff5ba 100644
--- a/frontend/src/utils/paths.js
+++ b/frontend/src/utils/paths.js
@@ -96,6 +96,9 @@ export default {
     apiKeys: () => {
       return "/settings/api-keys";
     },
+    logs: () => {
+      return "/settings/event-logs";
+    },
     embedSetup: () => {
       return `/settings/embed-config`;
     },
diff --git a/server/endpoints/admin.js b/server/endpoints/admin.js
index b107a11b424e7f26da394fd491727621fc1956d5..d9e1f9a0bf383b8e3eb846644c8845e0e31bf413 100644
--- a/server/endpoints/admin.js
+++ b/server/endpoints/admin.js
@@ -1,7 +1,9 @@
 const { ApiKey } = require("../models/apiKeys");
 const { Document } = require("../models/documents");
+const { EventLogs } = require("../models/eventLogs");
 const { Invite } = require("../models/invite");
 const { SystemSettings } = require("../models/systemSettings");
+const { Telemetry } = require("../models/telemetry");
 const { User } = require("../models/user");
 const { DocumentVectors } = require("../models/vectors");
 const { Workspace } = require("../models/workspace");
@@ -56,6 +58,14 @@ function adminEndpoints(app) {
         }
 
         const { user: newUser, error } = await User.create(newUserParams);
+        await EventLogs.logEvent(
+          "user_created",
+          {
+            userName: newUser.username,
+            createdBy: currUser.username,
+          },
+          currUser.id
+        );
         response.status(200).json({ user: newUser, error });
       } catch (e) {
         console.error(e);
@@ -121,6 +131,14 @@ function adminEndpoints(app) {
         }
 
         await User.delete({ id: Number(id) });
+        await EventLogs.logEvent(
+          "user_deleted",
+          {
+            userName: user.username,
+            deletedBy: currUser.username,
+          },
+          currUser.id
+        );
         response.status(200).json({ success: true, error: null });
       } catch (e) {
         console.error(e);
@@ -150,6 +168,14 @@ function adminEndpoints(app) {
       try {
         const user = await userFromSession(request, response);
         const { invite, error } = await Invite.create(user.id);
+        await EventLogs.logEvent(
+          "invite_created",
+          {
+            inviteCode: invite.code,
+            createdBy: response.locals?.user?.username,
+          },
+          response.locals?.user?.id
+        );
         response.status(200).json({ invite, error });
       } catch (e) {
         console.error(e);
@@ -165,6 +191,11 @@ function adminEndpoints(app) {
       try {
         const { id } = request.params;
         const { success, error } = await Invite.deactivate(id);
+        await EventLogs.logEvent(
+          "invite_deleted",
+          { deletedBy: response.locals?.user?.username },
+          response.locals?.user?.id
+        );
         response.status(200).json({ success, error });
       } catch (e) {
         console.error(e);
@@ -323,6 +354,13 @@ function adminEndpoints(app) {
       try {
         const user = await userFromSession(request, response);
         const { apiKey, error } = await ApiKey.create(user.id);
+
+        await Telemetry.sendTelemetry("api_key_created");
+        await EventLogs.logEvent(
+          "api_key_created",
+          { createdBy: user?.username },
+          user?.id
+        );
         return response.status(200).json({
           apiKey,
           error,
@@ -341,6 +379,12 @@ function adminEndpoints(app) {
       try {
         const { id } = request.params;
         await ApiKey.delete({ id: Number(id) });
+
+        await EventLogs.logEvent(
+          "api_key_deleted",
+          { deletedBy: response.locals?.user?.username },
+          response?.locals?.user?.id
+        );
         return response.status(200).end();
       } catch (e) {
         console.error(e);
diff --git a/server/endpoints/api/admin/index.js b/server/endpoints/api/admin/index.js
index 1f2a5bae74cbb4bf60591e5d5529508244acaa65..e91672e0077cb61f9572f7cae3bbb7aa31a0b055 100644
--- a/server/endpoints/api/admin/index.js
+++ b/server/endpoints/api/admin/index.js
@@ -1,3 +1,4 @@
+const { EventLogs } = require("../../../models/eventLogs");
 const { Invite } = require("../../../models/invite");
 const { SystemSettings } = require("../../../models/systemSettings");
 const { User } = require("../../../models/user");
@@ -259,7 +260,11 @@ function apiAdminEndpoints(app) {
         }
 
         const { id } = request.params;
-        await User.delete({ id });
+        const user = await User.get({ id: Number(id) });
+        await User.delete({ id: user.id });
+        await EventLogs.logEvent("api_user_deleted", {
+          userName: user.username,
+        });
         response.status(200).json({ success: true, error: null });
       } catch (e) {
         console.error(e);
diff --git a/server/endpoints/api/document/index.js b/server/endpoints/api/document/index.js
index 817043526b83ed9d6344bbd12a3cd1308ceee43a..b72debbdbb24d26c3870799412d13cec7341cb6f 100644
--- a/server/endpoints/api/document/index.js
+++ b/server/endpoints/api/document/index.js
@@ -12,6 +12,7 @@ const {
   findDocumentInDocuments,
 } = require("../../../utils/files");
 const { reqBody } = require("../../../utils/http");
+const { EventLogs } = require("../../../models/eventLogs");
 const { handleUploads } = setupMulter();
 
 function apiDocumentEndpoints(app) {
@@ -22,7 +23,7 @@ function apiDocumentEndpoints(app) {
     [validApiKey],
     handleUploads.single("file"),
     async (request, response) => {
-      /* 
+      /*
     #swagger.tags = ['Documents']
     #swagger.description = 'Upload a new file to AnythingLLM to be parsed and prepared for embedding.'
     #swagger.requestBody = {
@@ -68,9 +69,9 @@ function apiDocumentEndpoints(app) {
               ]
             }
           }
-        }           
+        }
       }
-    }  
+    }
     #swagger.responses[403] = {
       schema: {
         "$ref": "#/definitions/InvalidAPIKey"
@@ -105,6 +106,9 @@ function apiDocumentEndpoints(app) {
           `Document ${originalname} uploaded processed and successfully. It is now available in documents.`
         );
         await Telemetry.sendTelemetry("document_uploaded");
+        await EventLogs.logEvent("api_document_uploaded", {
+          documentName: originalname,
+        });
         response.status(200).json({ success: true, error: null, documents });
       } catch (e) {
         console.log(e.message, e);
@@ -117,7 +121,7 @@ function apiDocumentEndpoints(app) {
     "/v1/document/upload-link",
     [validApiKey],
     async (request, response) => {
-      /* 
+      /*
     #swagger.tags = ['Documents']
     #swagger.description = 'Upload a valid URL for AnythingLLM to scrape and prepare for embedding.'
     #swagger.requestBody = {
@@ -132,7 +136,7 @@ function apiDocumentEndpoints(app) {
                 "link": "https://useanything.com"
               }
             }
-          }           
+          }
         }
     }
     #swagger.responses[200] = {
@@ -161,9 +165,9 @@ function apiDocumentEndpoints(app) {
               ]
             }
           }
-        }           
+        }
       }
-    }  
+    }
     #swagger.responses[403] = {
       schema: {
         "$ref": "#/definitions/InvalidAPIKey"
@@ -196,7 +200,10 @@ function apiDocumentEndpoints(app) {
         console.log(
           `Link ${link} uploaded processed and successfully. It is now available in documents.`
         );
-        await Telemetry.sendTelemetry("document_uploaded");
+        await Telemetry.sendTelemetry("link_uploaded");
+        await EventLogs.logEvent("api_link_uploaded", {
+          link,
+        });
         response.status(200).json({ success: true, error: null, documents });
       } catch (e) {
         console.log(e.message, e);
@@ -206,7 +213,7 @@ function apiDocumentEndpoints(app) {
   );
 
   app.get("/v1/documents", [validApiKey], async (_, response) => {
-    /* 
+    /*
     #swagger.tags = ['Documents']
     #swagger.description = 'List of all locally-stored documents in instance'
     #swagger.responses[200] = {
@@ -231,9 +238,9 @@ function apiDocumentEndpoints(app) {
              }
             }
           }
-        }           
+        }
       }
-    }  
+    }
     #swagger.responses[403] = {
       schema: {
         "$ref": "#/definitions/InvalidAPIKey"
@@ -250,7 +257,7 @@ function apiDocumentEndpoints(app) {
   });
 
   app.get("/v1/document/:docName", [validApiKey], async (request, response) => {
-    /* 
+    /*
     #swagger.tags = ['Documents']
     #swagger.description = 'Get a single document by its unique AnythingLLM document name'
     #swagger.parameters['docName'] = {
@@ -281,9 +288,9 @@ function apiDocumentEndpoints(app) {
              }
             }
           }
-        }           
+        }
       }
-    }  
+    }
     #swagger.responses[403] = {
       schema: {
         "$ref": "#/definitions/InvalidAPIKey"
@@ -308,7 +315,7 @@ function apiDocumentEndpoints(app) {
     "/v1/document/accepted-file-types",
     [validApiKey],
     async (_, response) => {
-      /* 
+      /*
     #swagger.tags = ['Documents']
     #swagger.description = 'Check available filetypes and MIMEs that can be uploaded.'
     #swagger.responses[200] = {
@@ -337,9 +344,9 @@ function apiDocumentEndpoints(app) {
               }
             }
           }
-        }           
+        }
       }
-    } 
+    }
     #swagger.responses[403] = {
       schema: {
         "$ref": "#/definitions/InvalidAPIKey"
diff --git a/server/endpoints/api/workspace/index.js b/server/endpoints/api/workspace/index.js
index c1642ce4aaf542b09750caae181c3e7dfc1e8a61..885d0f1ae7112618994fdfe6318d11e7f5c42d33 100644
--- a/server/endpoints/api/workspace/index.js
+++ b/server/endpoints/api/workspace/index.js
@@ -16,6 +16,7 @@ const {
   writeResponseChunk,
   VALID_CHAT_MODE,
 } = require("../../../utils/chats/stream");
+const { EventLogs } = require("../../../models/eventLogs");
 
 function apiWorkspaceEndpoints(app) {
   if (!app) return;
@@ -73,6 +74,9 @@ function apiWorkspaceEndpoints(app) {
         Embedder: process.env.EMBEDDING_ENGINE || "inherit",
         VectorDbSelection: process.env.VECTOR_DB || "pinecone",
       });
+      await EventLogs.logEvent("api_workspace_created", {
+        workspaceName: workspace?.name || "Unknown Workspace",
+      });
       response.status(200).json({ workspace, message });
     } catch (e) {
       console.log(e.message, e);
@@ -206,6 +210,10 @@ function apiWorkspaceEndpoints(app) {
         await DocumentVectors.deleteForWorkspace(workspaceId);
         await Document.delete({ workspaceId: workspaceId });
         await Workspace.delete({ id: workspaceId });
+
+        await EventLogs.logEvent("api_workspace_deleted", {
+          workspaceName: workspace?.name || "Unknown Workspace",
+        });
         try {
           await VectorDb["delete-namespace"]({ namespace: slug });
         } catch (e) {
@@ -519,6 +527,10 @@ function apiWorkspaceEndpoints(app) {
           Embedder: process.env.EMBEDDING_ENGINE || "inherit",
           VectorDbSelection: process.env.VECTOR_DB || "pinecone",
         });
+        await EventLogs.logEvent("api_sent_chat", {
+          workspaceName: workspace?.name,
+          chatModel: workspace?.chatModel || "System Default",
+        });
         response.status(200).json({ ...result });
       } catch (e) {
         response.status(500).json({
@@ -637,6 +649,10 @@ function apiWorkspaceEndpoints(app) {
           Embedder: process.env.EMBEDDING_ENGINE || "inherit",
           VectorDbSelection: process.env.VECTOR_DB || "pinecone",
         });
+        await EventLogs.logEvent("api_sent_chat", {
+          workspaceName: workspace?.name,
+          chatModel: workspace?.chatModel || "System Default",
+        });
         response.end();
       } catch (e) {
         console.error(e);
diff --git a/server/endpoints/chat.js b/server/endpoints/chat.js
index 23739084a7a2d3c1dbb82cd1b5b8bd845648b8d6..848a7a3633930e8000b180847ccc6c4d4b0d1c80 100644
--- a/server/endpoints/chat.js
+++ b/server/endpoints/chat.js
@@ -14,6 +14,7 @@ const {
   ROLES,
   flexUserRoleValid,
 } = require("../utils/middleware/multiUserProtected");
+const { EventLogs } = require("../models/eventLogs");
 
 function chatEndpoints(app) {
   if (!app) return;
@@ -98,6 +99,15 @@ function chatEndpoints(app) {
           Embedder: process.env.EMBEDDING_ENGINE || "inherit",
           VectorDbSelection: process.env.VECTOR_DB || "pinecone",
         });
+
+        await EventLogs.logEvent(
+          "sent_chat",
+          {
+            workspaceName: workspace?.name,
+            chatModel: workspace?.chatModel || "System Default",
+          },
+          user?.id
+        );
         response.end();
       } catch (e) {
         console.error(e);
diff --git a/server/endpoints/embedManagement.js b/server/endpoints/embedManagement.js
index c3a27ce411ddc2329a427e71a166d313d2aacab9..7ebab23e7be3574e5fd2b79c02019670f1bdb628 100644
--- a/server/endpoints/embedManagement.js
+++ b/server/endpoints/embedManagement.js
@@ -1,5 +1,7 @@
 const { EmbedChats } = require("../models/embedChats");
 const { EmbedConfig } = require("../models/embedConfig");
+const { EventLogs } = require("../models/eventLogs");
+const { Workspace } = require("../models/workspace");
 const { reqBody, userFromSession } = require("../utils/http");
 const { validEmbedConfigId } = require("../utils/middleware/embedMiddleware");
 const {
@@ -32,9 +34,14 @@ function embedManagementEndpoints(app) {
     [validatedRequest, flexUserRoleValid([ROLES.admin])],
     async (request, response) => {
       try {
-        const user = userFromSession(request, response);
+        const user = await userFromSession(request, response);
         const data = reqBody(request);
         const { embed, message: error } = await EmbedConfig.new(data, user?.id);
+        await EventLogs.logEvent(
+          "embed_created",
+          { embedId: embed.id },
+          user?.id
+        );
         response.status(200).json({ embed, error });
       } catch (e) {
         console.error(e);
@@ -48,9 +55,11 @@ function embedManagementEndpoints(app) {
     [validatedRequest, flexUserRoleValid([ROLES.admin]), validEmbedConfigId],
     async (request, response) => {
       try {
+        const user = await userFromSession(request, response);
         const { embedId } = request.params;
         const updates = reqBody(request);
         const { success, error } = await EmbedConfig.update(embedId, updates);
+        await EventLogs.logEvent("embed_updated", { embedId }, user?.id);
         response.status(200).json({ success, error });
       } catch (e) {
         console.error(e);
@@ -66,6 +75,11 @@ function embedManagementEndpoints(app) {
       try {
         const { embedId } = request.params;
         await EmbedConfig.delete({ id: Number(embedId) });
+        await EventLogs.logEvent(
+          "embed_deleted",
+          { embedId },
+          response?.locals?.user?.id
+        );
         response.status(200).json({ success: true, error: null });
       } catch (e) {
         console.error(e);
diff --git a/server/endpoints/invite.js b/server/endpoints/invite.js
index 4fd8d15450caed878be7ecf2c74c91aaf4223e2f..38eb71de81f96b99f3ef72286d0409bfb6b0cea4 100644
--- a/server/endpoints/invite.js
+++ b/server/endpoints/invite.js
@@ -1,3 +1,4 @@
+const { EventLogs } = require("../models/eventLogs");
 const { Invite } = require("../models/invite");
 const { User } = require("../models/user");
 const { reqBody } = require("../utils/http");
@@ -56,6 +57,14 @@ function inviteEndpoints(app) {
       }
 
       await Invite.markClaimed(invite.id, user);
+      await EventLogs.logEvent(
+        "invite_accepted",
+        {
+          username: user.username,
+        },
+        user.id
+      );
+
       response.status(200).json({ success: true, error: null });
     } catch (e) {
       console.error(e);
diff --git a/server/endpoints/system.js b/server/endpoints/system.js
index 100d0a4b68fd8fe79369857054d1d9b576da7bed..823de7f1cbb9e8e8161087691bbee639d6f9ed5b 100644
--- a/server/endpoints/system.js
+++ b/server/endpoints/system.js
@@ -48,6 +48,7 @@ const {
   prepareWorkspaceChatsForExport,
   exportChatsAsType,
 } = require("../utils/helpers/chat/convertTo");
+const { EventLogs } = require("../models/eventLogs");
 
 function systemEndpoints(app) {
   if (!app) return;
@@ -114,6 +115,14 @@ function systemEndpoints(app) {
         const existingUser = await User.get({ username });
 
         if (!existingUser) {
+          await EventLogs.logEvent(
+            "failed_login_invalid_username",
+            {
+              ip: request.ip || "Unknown IP",
+              username: username || "Unknown user",
+            },
+            existingUser?.id
+          );
           response.status(200).json({
             user: null,
             valid: false,
@@ -124,6 +133,14 @@ function systemEndpoints(app) {
         }
 
         if (!bcrypt.compareSync(password, existingUser.password)) {
+          await EventLogs.logEvent(
+            "failed_login_invalid_password",
+            {
+              ip: request.ip || "Unknown IP",
+              username: username || "Unknown user",
+            },
+            existingUser?.id
+          );
           response.status(200).json({
             user: null,
             valid: false,
@@ -134,6 +151,14 @@ function systemEndpoints(app) {
         }
 
         if (existingUser.suspended) {
+          await EventLogs.logEvent(
+            "failed_login_account_suspended",
+            {
+              ip: request.ip || "Unknown IP",
+              username: username || "Unknown user",
+            },
+            existingUser?.id
+          );
           response.status(200).json({
             user: null,
             valid: false,
@@ -148,6 +173,16 @@ function systemEndpoints(app) {
           { multiUserMode: false },
           existingUser?.id
         );
+
+        await EventLogs.logEvent(
+          "login_event",
+          {
+            ip: request.ip || "Unknown IP",
+            username: existingUser.username || "Unknown user",
+          },
+          existingUser?.id
+        );
+
         response.status(200).json({
           valid: true,
           user: existingUser,
@@ -166,6 +201,10 @@ function systemEndpoints(app) {
             bcrypt.hashSync(process.env.AUTH_TOKEN, 10)
           )
         ) {
+          await EventLogs.logEvent("failed_login_invalid_password", {
+            ip: request.ip || "Unknown IP",
+            multiUserMode: false,
+          });
           response.status(401).json({
             valid: false,
             token: null,
@@ -175,6 +214,10 @@ function systemEndpoints(app) {
         }
 
         await Telemetry.sendTelemetry("login_event", { multiUserMode: false });
+        await EventLogs.logEvent("login_event", {
+          ip: request.ip || "Unknown IP",
+          multiUserMode: false,
+        });
         response.status(200).json({
           valid: true,
           token: makeJWT({ p: password }, "30d"),
@@ -288,7 +331,11 @@ function systemEndpoints(app) {
     async (request, response) => {
       try {
         const body = reqBody(request);
-        const { newValues, error } = await updateENV(body);
+        const { newValues, error } = await updateENV(
+          body,
+          false,
+          response?.locals?.user?.id
+        );
         if (process.env.NODE_ENV === "production") await dumpENV();
         response.status(200).json({ newValues, error });
       } catch (e) {
@@ -364,6 +411,7 @@ function systemEndpoints(app) {
         await Telemetry.sendTelemetry("enabled_multi_user_mode", {
           multiUserMode: true,
         });
+        await EventLogs.logEvent("multi_user_mode_enabled", {}, user?.id);
         response.status(200).json({ success: !!user, error });
       } catch (e) {
         await User.delete({});
@@ -694,6 +742,12 @@ function systemEndpoints(app) {
         }
 
         const { apiKey, error } = await ApiKey.create();
+        await Telemetry.sendTelemetry("api_key_created");
+        await EventLogs.logEvent(
+          "api_key_created",
+          {},
+          response?.locals?.user?.id
+        );
         return response.status(200).json({
           apiKey,
           error,
@@ -715,6 +769,11 @@ function systemEndpoints(app) {
       }
 
       await ApiKey.delete();
+      await EventLogs.logEvent(
+        "api_key_deleted",
+        { deletedBy: response.locals?.user?.username },
+        response?.locals?.user?.id
+      );
       return response.status(200).end();
     } catch (error) {
       console.error(error);
@@ -744,6 +803,45 @@ function systemEndpoints(app) {
     }
   );
 
+  app.post(
+    "/system/event-logs",
+    [validatedRequest, flexUserRoleValid([ROLES.admin])],
+    async (request, response) => {
+      try {
+        const { offset = 0, limit = 20 } = reqBody(request);
+        const logs = await EventLogs.whereWithData({}, limit, offset * limit, {
+          id: "desc",
+        });
+        const totalLogs = await EventLogs.count();
+        const hasPages = totalLogs > (offset + 1) * limit;
+
+        response.status(200).json({ logs: logs, hasPages, totalLogs });
+      } catch (e) {
+        console.error(e);
+        response.sendStatus(500).end();
+      }
+    }
+  );
+
+  app.delete(
+    "/system/event-logs",
+    [validatedRequest, flexUserRoleValid([ROLES.admin])],
+    async (_, response) => {
+      try {
+        await EventLogs.delete();
+        await EventLogs.logEvent(
+          "event_logs_cleared",
+          {},
+          response?.locals?.user?.id
+        );
+        response.json({ success: true });
+      } catch (e) {
+        console.error(e);
+        response.sendStatus(500).end();
+      }
+    }
+  );
+
   app.post(
     "/system/workspace-chats",
     [validatedRequest, flexUserRoleValid([ROLES.admin, ROLES.manager])],
@@ -790,6 +888,13 @@ function systemEndpoints(app) {
         const { type = "jsonl" } = request.query;
         const chats = await prepareWorkspaceChatsForExport();
         const { contentType, data } = await exportChatsAsType(chats, type);
+        await EventLogs.logEvent(
+          "exported_chats",
+          {
+            type,
+          },
+          response.locals.user?.id
+        );
         response.setHeader("Content-Type", contentType);
         response.status(200).send(data);
       } catch (e) {
diff --git a/server/endpoints/workspaces.js b/server/endpoints/workspaces.js
index b04d23376f3de30262f919a5d82d2697b21eedaf..574180627b9d4d7dfea9c68f4487255897b2bb4a 100644
--- a/server/endpoints/workspaces.js
+++ b/server/endpoints/workspaces.js
@@ -17,6 +17,7 @@ const {
   flexUserRoleValid,
   ROLES,
 } = require("../utils/middleware/multiUserProtected");
+const { EventLogs } = require("../models/eventLogs");
 const {
   WorkspaceSuggestedMessages,
 } = require("../models/workspacesSuggestedMessages");
@@ -43,6 +44,14 @@ function workspaceEndpoints(app) {
           },
           user?.id
         );
+
+        await EventLogs.logEvent(
+          "workspace_created",
+          {
+            workspaceName: workspace?.name || "Unknown Workspace",
+          },
+          user?.id
+        );
         if (onboardingComplete === true)
           await Telemetry.sendTelemetry("onboarding_complete");
 
@@ -112,6 +121,13 @@ function workspaceEndpoints(app) {
         `Document ${originalname} uploaded processed and successfully. It is now available in documents.`
       );
       await Telemetry.sendTelemetry("document_uploaded");
+      await EventLogs.logEvent(
+        "document_uploaded",
+        {
+          documentName: originalname,
+        },
+        response.locals?.user?.id
+      );
       response.status(200).json({ success: true, error: null });
     }
   );
@@ -144,6 +160,11 @@ function workspaceEndpoints(app) {
         `Link ${link} uploaded processed and successfully. It is now available in documents.`
       );
       await Telemetry.sendTelemetry("link_uploaded");
+      await EventLogs.logEvent(
+        "link_uploaded",
+        { link },
+        response.locals?.user?.id
+      );
       response.status(200).json({ success: true, error: null });
     }
   );
@@ -165,10 +186,15 @@ function workspaceEndpoints(app) {
           return;
         }
 
-        await Document.removeDocuments(currWorkspace, deletes);
+        await Document.removeDocuments(
+          currWorkspace,
+          deletes,
+          response.locals?.user?.id
+        );
         const { failedToEmbed = [], errors = [] } = await Document.addDocuments(
           currWorkspace,
-          adds
+          adds,
+          response.locals?.user?.id
         );
         const updatedWorkspace = await Workspace.get({ id: currWorkspace.id });
         response.status(200).json({
@@ -209,6 +235,14 @@ function workspaceEndpoints(app) {
         await Document.delete({ workspaceId: Number(workspace.id) });
         await Workspace.delete({ id: Number(workspace.id) });
 
+        await EventLogs.logEvent(
+          "workspace_deleted",
+          {
+            workspaceName: workspace?.name || "Unknown Workspace",
+          },
+          response.locals?.user?.id
+        );
+
         try {
           await VectorDb["delete-namespace"]({ namespace: slug });
         } catch (e) {
diff --git a/server/models/apiKeys.js b/server/models/apiKeys.js
index b6242397ba225649faaa27f701234b019026087e..32727fec8d223b6b78e4d144acee95e0afbf0f41 100644
--- a/server/models/apiKeys.js
+++ b/server/models/apiKeys.js
@@ -1,4 +1,3 @@
-const { Telemetry } = require("./telemetry");
 const prisma = require("../utils/prisma");
 
 const ApiKey = {
@@ -19,7 +18,6 @@ const ApiKey = {
         },
       });
 
-      await Telemetry.sendTelemetry("api_key_created");
       return { apiKey, error: null };
     } catch (error) {
       console.error("FAILED TO CREATE API KEY.", error.message);
diff --git a/server/models/documents.js b/server/models/documents.js
index bdb29dc77b5be0c0752d03392d3bf540d9facc53..9f50aa9159c2f9cbc3eec065affdfbb40c001bd8 100644
--- a/server/models/documents.js
+++ b/server/models/documents.js
@@ -3,6 +3,7 @@ const { v4: uuidv4 } = require("uuid");
 const { getVectorDbClass } = require("../utils/helpers");
 const prisma = require("../utils/prisma");
 const { Telemetry } = require("./telemetry");
+const { EventLogs } = require("./eventLogs");
 
 const Document = {
   forWorkspace: async function (workspaceId = null) {
@@ -34,7 +35,7 @@ const Document = {
     }
   },
 
-  addDocuments: async function (workspace, additions = []) {
+  addDocuments: async function (workspace, additions = [], userId = null) {
     const VectorDb = getVectorDbClass();
     if (additions.length === 0) return { failed: [], embedded: [] };
     const embedded = [];
@@ -84,10 +85,18 @@ const Document = {
       Embedder: process.env.EMBEDDING_ENGINE || "inherit",
       VectorDbSelection: process.env.VECTOR_DB || "pinecone",
     });
+    await EventLogs.logEvent(
+      "workspace_documents_added",
+      {
+        workspaceName: workspace?.name || "Unknown Workspace",
+        numberOfDocumentsAdded: additions.length,
+      },
+      userId
+    );
     return { failedToEmbed, errors: Array.from(errors), embedded };
   },
 
-  removeDocuments: async function (workspace, removals = []) {
+  removeDocuments: async function (workspace, removals = [], userId = null) {
     const VectorDb = getVectorDbClass();
     if (removals.length === 0) return;
 
@@ -119,6 +128,14 @@ const Document = {
       Embedder: process.env.EMBEDDING_ENGINE || "inherit",
       VectorDbSelection: process.env.VECTOR_DB || "pinecone",
     });
+    await EventLogs.logEvent(
+      "workspace_documents_removed",
+      {
+        workspaceName: workspace?.name || "Unknown Workspace",
+        numberOfDocuments: removals.length,
+      },
+      userId
+    );
     return true;
   },
 
diff --git a/server/models/eventLogs.js b/server/models/eventLogs.js
new file mode 100644
index 0000000000000000000000000000000000000000..51240431a75276f0781a8ed46cd3fe8e3a996465
--- /dev/null
+++ b/server/models/eventLogs.js
@@ -0,0 +1,129 @@
+const prisma = require("../utils/prisma");
+
+const EventLogs = {
+  logEvent: async function (event, metadata = {}, userId = null) {
+    try {
+      const eventLog = await prisma.event_logs.create({
+        data: {
+          event,
+          metadata: metadata ? JSON.stringify(metadata) : null,
+          userId: userId ? Number(userId) : null,
+          occurredAt: new Date(),
+        },
+      });
+      console.log(`\x1b[32m[Event Logged]\x1b[0m - ${event}`);
+      return { eventLog, message: null };
+    } catch (error) {
+      console.error(
+        `\x1b[31m[Event Logging Failed]\x1b[0m - ${event}`,
+        error.message
+      );
+      return { eventLog: null, message: error.message };
+    }
+  },
+
+  getByEvent: async function (event, limit = null, orderBy = null) {
+    try {
+      const logs = await prisma.event_logs.findMany({
+        where: { event },
+        ...(limit !== null ? { take: limit } : {}),
+        ...(orderBy !== null
+          ? { orderBy }
+          : { orderBy: { occurredAt: "desc" } }),
+      });
+      return logs;
+    } catch (error) {
+      console.error(error.message);
+      return [];
+    }
+  },
+
+  getByUserId: async function (userId, limit = null, orderBy = null) {
+    try {
+      const logs = await prisma.event_logs.findMany({
+        where: { userId },
+        ...(limit !== null ? { take: limit } : {}),
+        ...(orderBy !== null
+          ? { orderBy }
+          : { orderBy: { occurredAt: "desc" } }),
+      });
+      return logs;
+    } catch (error) {
+      console.error(error.message);
+      return [];
+    }
+  },
+
+  where: async function (
+    clause = {},
+    limit = null,
+    orderBy = null,
+    offset = null
+  ) {
+    try {
+      const logs = await prisma.event_logs.findMany({
+        where: clause,
+        ...(limit !== null ? { take: limit } : {}),
+        ...(offset !== null ? { skip: offset } : {}),
+        ...(orderBy !== null
+          ? { orderBy }
+          : { orderBy: { occurredAt: "desc" } }),
+      });
+      return logs;
+    } catch (error) {
+      console.error(error.message);
+      return [];
+    }
+  },
+
+  whereWithData: async function (
+    clause = {},
+    limit = null,
+    offset = null,
+    orderBy = null
+  ) {
+    const { User } = require("./user");
+
+    try {
+      const results = await this.where(clause, limit, orderBy, offset);
+
+      for (const res of results) {
+        const user = res.userId ? await User.get({ id: res.userId }) : null;
+        res.user = user
+          ? { username: user.username }
+          : { username: "unknown user" };
+      }
+
+      return results;
+    } catch (error) {
+      console.error(error.message);
+      return [];
+    }
+  },
+
+  count: async function (clause = {}) {
+    try {
+      const count = await prisma.event_logs.count({
+        where: clause,
+      });
+      return count;
+    } catch (error) {
+      console.error(error.message);
+      return 0;
+    }
+  },
+
+  delete: async function (clause = {}) {
+    try {
+      await prisma.event_logs.deleteMany({
+        where: clause,
+      });
+      return true;
+    } catch (error) {
+      console.error(error.message);
+      return false;
+    }
+  },
+};
+
+module.exports = { EventLogs };
diff --git a/server/models/user.js b/server/models/user.js
index 269219fc89711e793691bec1adc03c0dec5780dd..c447950caa985fb23109dc588ea6b92d47c2e6ee 100644
--- a/server/models/user.js
+++ b/server/models/user.js
@@ -1,4 +1,5 @@
 const prisma = require("../utils/prisma");
+const { EventLogs } = require("./eventLogs");
 
 const User = {
   create: async function ({ username, password, role = "default" }) {
@@ -24,25 +25,52 @@ const User = {
     }
   },
 
+  // Log the changes to a user object, but omit sensitive fields
+  // that are not meant to be logged.
+  loggedChanges: function (updates, prev = {}) {
+    const changes = {};
+    const sensitiveFields = ["password"];
+
+    Object.keys(updates).forEach((key) => {
+      if (!sensitiveFields.includes(key) && updates[key] !== prev[key]) {
+        changes[key] = `${prev[key]} => ${updates[key]}`;
+      }
+    });
+
+    return changes;
+  },
+
   update: async function (userId, updates = {}) {
     try {
-      // Rehash new password if it exists as update field
+      const currentUser = await prisma.users.findUnique({
+        where: { id: parseInt(userId) },
+      });
+      if (!currentUser) {
+        return { success: false, error: "User not found" };
+      }
+
       if (updates.hasOwnProperty("password")) {
         const passwordCheck = this.checkPasswordComplexity(updates.password);
         if (!passwordCheck.checkedOK) {
           return { success: false, error: passwordCheck.error };
         }
-
         const bcrypt = require("bcrypt");
         updates.password = bcrypt.hashSync(updates.password, 10);
-      } else {
-        delete updates.password;
       }
 
-      await prisma.users.update({
+      const user = await prisma.users.update({
         where: { id: parseInt(userId) },
         data: updates,
       });
+
+      await EventLogs.logEvent(
+        "user_updated",
+        {
+          username: user.username,
+          changes: this.loggedChanges(updates, currentUser),
+        },
+        userId
+      );
       return { success: true, error: null };
     } catch (error) {
       console.error(error.message);
diff --git a/server/prisma/migrations/20240206211916_init/migration.sql b/server/prisma/migrations/20240206211916_init/migration.sql
new file mode 100644
index 0000000000000000000000000000000000000000..f2e882a0bb638b4e4b3c965ce7649d51edd4cd03
--- /dev/null
+++ b/server/prisma/migrations/20240206211916_init/migration.sql
@@ -0,0 +1,11 @@
+-- CreateTable
+CREATE TABLE "event_logs" (
+    "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+    "event" TEXT NOT NULL,
+    "metadata" TEXT,
+    "userId" INTEGER,
+    "occurredAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+
+-- CreateIndex
+CREATE INDEX "event_logs_event_idx" ON "event_logs"("event");
diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma
index ede8a1fdebae2b62851fd3c237c14e2cfa3af0fc..1747db329cce2e30125c1fdaefc89d7a8c02faec 100644
--- a/server/prisma/schema.prisma
+++ b/server/prisma/schema.prisma
@@ -181,3 +181,13 @@ model embed_chats {
   embed_config           embed_configs @relation(fields: [embed_id], references: [id], onDelete: Cascade)
   users                  users?        @relation(fields: [usersId], references: [id])
 }
+
+model event_logs {
+  id         Int      @id @default(autoincrement())
+  event      String
+  metadata   String?
+  userId     Int?
+  occurredAt DateTime @default(now())
+
+  @@index([event])
+}
diff --git a/server/utils/helpers/updateENV.js b/server/utils/helpers/updateENV.js
index acd77b2fdb138683a03dfe0e8db68f41a73f1d16..f89a193f6e23c9c944992374c655182dcffcfb28 100644
--- a/server/utils/helpers/updateENV.js
+++ b/server/utils/helpers/updateENV.js
@@ -430,7 +430,7 @@ async function wipeWorkspaceModelPreference(key, prev, next) {
 // read from an ENV file as this seems to be a complicating step for many so allowing people to write
 // to the process will at least alleviate that issue. It does not perform comprehensive validity checks or sanity checks
 // and is simply for debugging when the .env not found issue many come across.
-async function updateENV(newENVs = {}, force = false) {
+async function updateENV(newENVs = {}, force = false, userId = null) {
   let error = "";
   const validKeys = Object.keys(KEY_MAPPING);
   const ENV_KEYS = Object.keys(newENVs).filter(
@@ -458,9 +458,25 @@ async function updateENV(newENVs = {}, force = false) {
       await postUpdateFunc(key, prevValue, nextValue);
   }
 
+  await logChangesToEventLog(newValues, userId);
   return { newValues, error: error?.length > 0 ? error : false };
 }
 
+async function logChangesToEventLog(newValues = {}, userId = null) {
+  const { EventLogs } = require("../../models/eventLogs");
+  const eventMapping = {
+    LLMProvider: "update_llm_provider",
+    EmbeddingEngine: "update_embedding_engine",
+    VectorDB: "update_vector_db",
+  };
+
+  for (const [key, eventName] of Object.entries(eventMapping)) {
+    if (!newValues.hasOwnProperty(key)) continue;
+    await EventLogs.logEvent(eventName, {}, userId);
+  }
+  return;
+}
+
 async function dumpENV() {
   const fs = require("fs");
   const path = require("path");