WIP event logging - new table for events and new settings view for viewing
This commit is contained in:
parent
9d410496c0
commit
e95d547be6
|
@ -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/Logs"));
|
||||
const GeneralChats = lazy(() => import("@/pages/GeneralSettings/Chats"));
|
||||
const GeneralAppearance = lazy(
|
||||
() => import("@/pages/GeneralSettings/Appearance")
|
||||
|
@ -70,6 +71,10 @@ export default function App() {
|
|||
path="/settings/vector-database"
|
||||
element={<AdminRoute Component={GeneralVectorDatabase} />}
|
||||
/>
|
||||
<Route
|
||||
path="/settings/logs"
|
||||
element={<AdminRoute Component={AdminLogs} />}
|
||||
/>
|
||||
{/* Manager */}
|
||||
<Route
|
||||
path="/settings/security"
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
List,
|
||||
FileCode,
|
||||
Plugs,
|
||||
Notepad,
|
||||
} from "@phosphor-icons/react";
|
||||
import useUser from "@/hooks/useUser";
|
||||
import { USER_BACKGROUND_COLOR } from "@/utils/constants";
|
||||
|
@ -154,6 +155,14 @@ export default function SettingsSidebar() {
|
|||
flex={true}
|
||||
allowedRole={["admin", "manager"]}
|
||||
/>
|
||||
<Option
|
||||
href={paths.settings.logs()}
|
||||
btnText="Logs"
|
||||
icon={<Notepad className="h-5 w-5 flex-shrink-0" />}
|
||||
user={user}
|
||||
flex={true}
|
||||
allowedRole={["admin", "manager"]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
@ -93,6 +93,9 @@ export default {
|
|||
apiKeys: () => {
|
||||
return "/settings/api-keys";
|
||||
},
|
||||
logs: () => {
|
||||
return "/settings/logs";
|
||||
},
|
||||
dataConnectors: {
|
||||
list: () => {
|
||||
return "/settings/data-connectors";
|
||||
|
|
|
@ -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,16 @@ function chatEndpoints(app) {
|
|||
Embedder: process.env.EMBEDDING_ENGINE || "inherit",
|
||||
VectorDbSelection: process.env.VECTOR_DB || "pinecone",
|
||||
});
|
||||
await EventLogs.logEvent({
|
||||
event: "sent_chat",
|
||||
userId: user?.id || null,
|
||||
metadata: {
|
||||
multiUserMode: multiUserMode(response),
|
||||
LLMSelection: process.env.LLM_PROVIDER || "openai",
|
||||
Embedder: process.env.EMBEDDING_ENGINE || "inherit",
|
||||
VectorDbSelection: process.env.VECTOR_DB || "pinecone",
|
||||
},
|
||||
});
|
||||
response.end();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
|
|
@ -48,6 +48,7 @@ const {
|
|||
prepareWorkspaceChatsForExport,
|
||||
exportChatsAsType,
|
||||
} = require("../utils/helpers/chat/convertTo");
|
||||
const { EventLogs } = require("../models/eventLogs");
|
||||
|
||||
function systemEndpoints(app) {
|
||||
if (!app) return;
|
||||
|
@ -148,6 +149,12 @@ function systemEndpoints(app) {
|
|||
{ multiUserMode: false },
|
||||
existingUser?.id
|
||||
);
|
||||
|
||||
await EventLogs.logEvent({
|
||||
event: "login_event",
|
||||
userId: existingUser?.id || null,
|
||||
metadata: {},
|
||||
});
|
||||
response.status(200).json({
|
||||
valid: true,
|
||||
user: existingUser,
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
const prisma = require("../utils/prisma");
|
||||
|
||||
const EventLogs = {
|
||||
logEvent: async function ({
|
||||
event,
|
||||
description = null,
|
||||
metadata = null,
|
||||
userId = null,
|
||||
ipAddress = null,
|
||||
}) {
|
||||
try {
|
||||
const eventLog = await prisma.event_logs.create({
|
||||
data: {
|
||||
event,
|
||||
description,
|
||||
metadata: metadata ? JSON.stringify(metadata) : null,
|
||||
userId,
|
||||
occurredAt: new Date(),
|
||||
ipAddress,
|
||||
},
|
||||
});
|
||||
return { eventLog, message: null };
|
||||
} catch (error) {
|
||||
console.error(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 [];
|
||||
}
|
||||
},
|
||||
|
||||
count: async function (clause = {}) {
|
||||
try {
|
||||
const count = await prisma.event_logs.count({
|
||||
where: clause,
|
||||
});
|
||||
return count;
|
||||
} catch (error) {
|
||||
console.error(error.message);
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = { EventLogs };
|
|
@ -0,0 +1,16 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "event_logs" (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"event" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"metadata" TEXT,
|
||||
"userId" INTEGER,
|
||||
"occurredAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"ipAddress" TEXT
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "event_logs_userId_idx" ON "event_logs"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "event_logs_event_idx" ON "event_logs"("event");
|
|
@ -131,3 +131,16 @@ model cache_data {
|
|||
createdAt DateTime @default(now())
|
||||
lastUpdatedAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model event_logs {
|
||||
id Int @id @default(autoincrement())
|
||||
event String
|
||||
description String?
|
||||
metadata String?
|
||||
userId Int?
|
||||
occurredAt DateTime @default(now())
|
||||
ipAddress String?
|
||||
@@index([userId])
|
||||
@@index([event])
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue