diff --git a/backend/src/index.ts b/backend/src/index.ts index f4e584f6..ff6b35d4 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -7,6 +7,7 @@ import getStats from './routes/getStats'; import logtypeStatus from './routes/logTypeStatus'; import connectToDatabase from './db/connect'; import severityInfo from './routes/severityInfo'; +import getLogAnalytics from './routes/getLogAnalytics'; dotenv.config(); @@ -30,6 +31,7 @@ app.use('/api', allLogs); app.use('/api', getStats) app.use('/api', logtypeStatus) app.use('/api', severityInfo) +app.use('/api', getLogAnalytics) app.listen(PORT, (): void => { console.log(`Server is running on http://localhost:${PORT}`); diff --git a/backend/src/models/LinuxLogModel.ts b/backend/src/models/LinuxLogModel.ts index 4bd826dc..34e624e5 100644 --- a/backend/src/models/LinuxLogModel.ts +++ b/backend/src/models/LinuxLogModel.ts @@ -9,17 +9,20 @@ interface LinuxLogModelType { processId?: number | string; userId?: string; rawLine: string; + analyzed?: boolean; + uploadDate?: Date; + users?: string; } const LinuxLogSchema = new Schema({ - logType: { - type: String, + logType: { + type: String, validate: { - validator: function(v: string) { + validator: function (v: string) { return ["SYSLOG", "AUTH", "KERNEL", "APPLICATION", "UNKNOWN"].includes(v) || v.startsWith("UNKNOWN-"); } }, - required: true + required: true }, timestamp: { type: Date, required: true }, severity: { type: String, enum: ["INFO", "WARNING", "ERROR", "CRITICAL"], required: true }, @@ -27,6 +30,9 @@ const LinuxLogSchema = new Schema({ message: { type: String, required: true }, processId: { type: Schema.Types.Mixed }, userId: { type: String }, + analyzed: { type: Boolean, default: false }, + uploadDate: { type: Date, default: Date.now }, + users: { type: String }, rawLine: { type: String, required: true }, }); diff --git a/backend/src/routes/getLogAnalytics.ts b/backend/src/routes/getLogAnalytics.ts new file mode 100644 index 00000000..49fcc54e --- /dev/null +++ b/backend/src/routes/getLogAnalytics.ts @@ -0,0 +1,37 @@ +import express from 'express'; +import { Request, Response } from 'express'; +import { LinuxLogModel } from '../models/LinuxLogModel'; + +const router = express.Router(); + +router.get('/getLogAnalytics', async (req: Request, res: Response) => { + try { + const logs = await LinuxLogModel.find({}).sort({ timestamp: -1 }).limit(1000); // Fetch the latest 10 logs + + const rows = logs.map(log => ({ + id: log._id, + timeStamp: log.timestamp.toUTCString(), + severity: log.severity, + users: log.users ? log.users : "N/A", + rawLine: log.rawLine, + message: log.message, + uploadDate: log.uploadDate ? log.uploadDate.toISOString() : null, + analyzed: log.analyzed, + EventId: log.eventId, + logType: log.logType, + })); + + res.json(rows); + + } catch (error) { + console.error(error); + res.status(500).json({ error: "Something went wrong." }); + } +}); + + + +export default router; + + + diff --git a/frontend/src/components/Analytics.jsx b/frontend/src/components/Analytics.jsx index 341817c0..7c769bcc 100644 --- a/frontend/src/components/Analytics.jsx +++ b/frontend/src/components/Analytics.jsx @@ -8,7 +8,7 @@ export default function Analytics() { return ( - Details + Total Log Analytics Details diff --git a/frontend/src/components/CustomizedDataGrid.jsx b/frontend/src/components/CustomizedDataGrid.jsx index fba0a74c..c86ff6c6 100644 --- a/frontend/src/components/CustomizedDataGrid.jsx +++ b/frontend/src/components/CustomizedDataGrid.jsx @@ -1,48 +1,97 @@ import * as React from "react"; import { DataGrid } from "@mui/x-data-grid"; -import { columns, rows } from "./internals/data/gridData"; +import { columns } from "./internals/data/gridData"; +import fetchAllLogs from "../utils/api/fetchLogAnalytics"; +import LogDetailsDialog from "./LogDetailsDialog"; export default function CustomizedDataGrid() { - return ( - - params.indexRelativeToCurrentPage % 2 === 0 ? "even" : "odd" + const [rows, setRows] = React.useState([]); + const [loading, setLoading] = React.useState(true); + const [error, setError] = React.useState(null); + // State to track the currently selected row for the overlay + const [selectedRow, setSelectedRow] = React.useState(null); + + React.useEffect(() => { + const fetchData = async () => { + try { + const data = await fetchAllLogs(); + if (!data) { + throw new Error("No data found"); + } + setRows(data); + } catch (error) { + setError(error.message); + } finally { + setLoading(false); } - initialState={{ - pagination: { paginationModel: { pageSize: 20 } }, - }} - pageSizeOptions={[10, 20, 50]} - // disableColumnResize - density="compact" - slotProps={{ - filterPanel: { - filterFormProps: { - logicOperatorInputProps: { - variant: "outlined", - size: "small", - }, - columnInputProps: { - variant: "outlined", - size: "small", - sx: { mt: "auto" }, - }, - operatorInputProps: { - variant: "outlined", - size: "small", - sx: { mt: "auto" }, - }, - valueInputProps: { - InputComponentProps: { + }; + fetchData(); + }, []); + + // Handle row click event to open the overlay with details + const handleRowClick = (params) => { + setSelectedRow(params.row); + }; + + // Close the overlay + const handleCloseOverlay = () => { + setSelectedRow(null); + }; + + if (loading) { + return
Loading...
; + } + if (error) { + return
Error: {error}
; + } + + return ( + <> + + params.indexRelativeToCurrentPage % 2 === 0 ? "even" : "odd" + } + initialState={{ + pagination: { paginationModel: { pageSize: 20 } }, + }} + getRowId={(row) => row.id} + pageSizeOptions={[10, 20, 50]} + density="compact" + onRowClick={handleRowClick} + slotProps={{ + filterPanel: { + filterFormProps: { + logicOperatorInputProps: { variant: "outlined", size: "small", }, + columnInputProps: { + variant: "outlined", + size: "small", + sx: { mt: "auto" }, + }, + operatorInputProps: { + variant: "outlined", + size: "small", + sx: { mt: "auto" }, + }, + valueInputProps: { + InputComponentProps: { + variant: "outlined", + size: "small", + }, + }, }, }, - }, - }} - /> + }} + /> + + + ); } diff --git a/frontend/src/components/Dashboard.jsx b/frontend/src/components/Dashboard.jsx index 9095ded9..5c70a6e0 100644 --- a/frontend/src/components/Dashboard.jsx +++ b/frontend/src/components/Dashboard.jsx @@ -18,6 +18,7 @@ import Chat from "./Chat"; import Analytics from "./Analytics"; import { useRecoilValue } from "recoil"; import { activeViewState } from "../utils/state"; +import Upload from "./Upload"; const xThemeComponents = { ...chartsCustomizations, @@ -37,6 +38,8 @@ export default function Dashboard(props) { return ; case "chat": return ; + case "upload": + return ; default: return ; } diff --git a/frontend/src/components/LogDetailsDialog.jsx b/frontend/src/components/LogDetailsDialog.jsx new file mode 100644 index 00000000..12ed3fc7 --- /dev/null +++ b/frontend/src/components/LogDetailsDialog.jsx @@ -0,0 +1,146 @@ +import * as React from "react"; +import { + Dialog, + DialogTitle, + DialogContent, + IconButton, + Button, + Grid, + Typography, + Box, + Paper, + Stack, +} from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; +import ChatIcon from "@mui/icons-material/Chat"; + +export default function LogDetailsDialog({ selectedRow, onClose }) { + if (!selectedRow) return null; + + // Helper function to format values based on type + const formatValue = (key, value) => { + if (value === null || value === undefined) { + return ( + + None + + ); + } else if (typeof value === "object") { + return ( + theme.palette.grey[100], + p: 2, + borderRadius: 1, + overflow: "auto", + maxHeight: 200, + fontSize: "0.875rem", + }} + > + {JSON.stringify(value, null, 2)} + + ); + } else if (typeof value === "boolean") { + return {value ? "Yes" : "No"}; + } else if ( + key.toLowerCase().includes("time") || + key.toLowerCase().includes("date") + ) { + try { + return ( + + {new Date(value).toLocaleString()} + + ); + } catch { + return {value}; + } + } + return {value}; + }; + + // Convert key strings to a more readable format + const formatLabel = (key) => + key.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()); + + // Prepare entries from the selected row + const entries = Object.entries(selectedRow).map(([key, value]) => ({ + key, + value, + isWide: typeof value === "object", + })); + + return ( + + + + Log Details #{selectedRow.id} + + {/* Conditionally render the Chat button if analyzed is false */} + {selectedRow.analyzed === false && ( + + )} + + + + + + + {entries.map(({ key, value, isWide }) => ( + + theme.shadows[1], + height: "100%", + }} + > + + + {formatLabel(key)} + + {formatValue(key, value)} + + + + ))} + + + + ); +} diff --git a/frontend/src/components/MenuContent.jsx b/frontend/src/components/MenuContent.jsx index caa76046..a51eb915 100644 --- a/frontend/src/components/MenuContent.jsx +++ b/frontend/src/components/MenuContent.jsx @@ -9,6 +9,7 @@ import HomeRoundedIcon from "@mui/icons-material/HomeRounded"; import AnalyticsRoundedIcon from "@mui/icons-material/AnalyticsRounded"; import Chat from "@mui/icons-material/Chat"; import SettingsRoundedIcon from "@mui/icons-material/SettingsRounded"; +import CloudUpload from "@mui/icons-material/CloudUpload"; import InfoRoundedIcon from "@mui/icons-material/InfoRounded"; import HelpRoundedIcon from "@mui/icons-material/HelpRounded"; import { useRecoilState } from "recoil"; @@ -18,7 +19,7 @@ const mainListItems = [ { text: "Home", icon: }, { text: "Analytics", icon: }, { text: "Chat", icon: }, - // { text: "Tasks", icon: }, + { text: "Upload", icon: }, ]; const secondaryListItems = [ diff --git a/frontend/src/components/Upload.jsx b/frontend/src/components/Upload.jsx new file mode 100644 index 00000000..58d2c317 --- /dev/null +++ b/frontend/src/components/Upload.jsx @@ -0,0 +1,230 @@ +import React, { useState } from "react"; +import { + Box, + Button, + FormControl, + FormControlLabel, + Radio, + RadioGroup, + Typography, + Select, + MenuItem, + FormHelperText, + CircularProgress, + Alert, +} from "@mui/material"; +import CloudUploadIcon from "@mui/icons-material/CloudUpload"; +import { styled } from "@mui/material/styles"; + +// Hidden input +const VisuallyHiddenInput = styled("input")({ + display: "none", +}); + +const DropArea = styled(Box)(({ theme }) => ({ + border: `2px dashed ${theme.palette.primary.main}`, + borderRadius: 10, + padding: theme.spacing(4), + textAlign: "center", + backgroundColor: theme.palette.background.default, + cursor: "pointer", + transition: "border-color 0.3s", + "&:hover": { + borderColor: theme.palette.primary.dark, + }, +})); + +const linuxLogTypes = [ + { value: "syslog.log", label: "System Log (syslog.log)" }, + { value: "kernel.log", label: "Kernel Log (kernel.log)" }, + { value: "auth.log", label: "Authentication Log (auth.log)" }, + { value: "other", label: "Other Log File" }, +]; + +const Upload = () => { + const [osType, setOsType] = useState("windows"); + const [linuxLogType, setLinuxLogType] = useState("syslog.log"); + const [selectedFile, setSelectedFile] = useState(null); + const [isUploading, setIsUploading] = useState(false); + const [uploadStatus, setUploadStatus] = useState(null); + + const handleOsChange = (event) => { + setOsType(event.target.value); + setSelectedFile(null); + setUploadStatus(null); + }; + + const handleLogTypeChange = (event) => { + setLinuxLogType(event.target.value); + }; + + const handleFileChange = (file) => { + const isValid = + (osType === "windows" && file.name.toLowerCase().endsWith(".csv")) || + (osType === "linux" && file.name.toLowerCase().endsWith(".log")); + + if (!isValid) { + setUploadStatus({ + type: "error", + message: `Please select a valid ${ + osType === "windows" ? "CSV" : "LOG" + } file.`, + }); + return; + } + + setSelectedFile(file); + setUploadStatus(null); + }; + + const handleFileInputChange = (event) => { + const file = event.target.files?.[0]; + if (file) handleFileChange(file); + }; + + const handleDrop = (event) => { + event.preventDefault(); + const file = event.dataTransfer.files?.[0]; + if (file) handleFileChange(file); + }; + + const handleUpload = async () => { + if (!selectedFile) { + setUploadStatus({ + type: "error", + message: "Please select a file to upload.", + }); + return; + } + + setIsUploading(true); + setUploadStatus(null); + + try { + const formData = new FormData(); + formData.append("logfile", selectedFile); + formData.append("source", osType === "linux" ? linuxLogType : "csv"); + + const response = await fetch( + `${import.meta.env.VITE_BACKEND_URL}/api//upload`, + { + method: "POST", + body: formData, + } + ); + + if (!response.ok) + throw new Error(`Upload failed with status: ${response.status}`); + + setUploadStatus({ + type: "success", + message: "File uploaded successfully!", + }); + + // Add logic for additional questions here (after successful upload) + } catch (error) { + console.error("Upload error:", error); + setUploadStatus({ + type: "error", + message: `Upload failed: ${ + error instanceof Error ? error.message : "Unknown error" + }`, + }); + } finally { + setIsUploading(false); + } + }; + + return ( + + + Log File Upload + + + + + + Select Operating System: + + + } + label="Windows" + /> + } label="Linux" /> + + + + + {osType === "linux" && ( + + + + Select Log Type: + + + Select the type of log file + + + )} + + e.preventDefault()} + onDrop={handleDrop} + sx={{ mb: 3 }} + onClick={() => document.getElementById("hiddenFileInput")?.click()} + > + + + Drag & drop your {osType === "windows" ? "CSV" : "LOG"} file here, + + + or click to select a file + + + + + {selectedFile && ( + + Selected file: {selectedFile.name} + + )} + + + + + + {uploadStatus && ( + + {uploadStatus.message} + + )} + + ); +}; + +export default Upload; diff --git a/frontend/src/components/internals/data/gridData.jsx b/frontend/src/components/internals/data/gridData.jsx index 99acb855..1a8e271e 100644 --- a/frontend/src/components/internals/data/gridData.jsx +++ b/frontend/src/components/internals/data/gridData.jsx @@ -14,45 +14,25 @@ function renderSeverity(severity) { return ; } -export function renderAvatar(params) { - if (params.value == null) { - return ""; - } - - return ( - - {params.value.name.toUpperCase().substring(0, 1)} - - ); -} - export const columns = [ - { field: "id", headerName: "ID", flex: 0.5, minWidth: 50 }, - { field: "timeStamp", headerName: "Timestamp", flex: 1, minWidth: 100 }, + { field: "timeStamp", headerName: "Timestamp", flex: 0.8, minWidth: 100 }, { field: "severity", headerName: "Severity", headerAlign: "center", align: "center", - flex: 0.7, - minWidth: 40, + flex: 0.5, + minWidth: 10, renderCell: (params) => renderSeverity(params.value), }, - { - field: "users", - headerName: "Users", - headerAlign: "center", - align: "center", - flex: 0.7, - minWidth: 40, - }, + // { + // field: "users", + // headerName: "Users", + // headerAlign: "center", + // align: "center", + // flex: 0.5, + // minWidth: 40, + // }, { field: "message", headerName: "Messages", @@ -61,22 +41,22 @@ export const columns = [ flex: 2, minWidth: 200, }, - { - field: "uploadDate", - headerName: "Upload Date", - headerAlign: "left", - align: "left", - flex: 0.5, - minWidth: 120, - }, - { - field: "analyzed", - headerName: "Analyzed", - headerAlign: "center", - align: "center", - flex: 0.5, - minWidth: 100, - }, + // { + // field: "uploadDate", + // headerName: "Upload Date", + // headerAlign: "left", + // align: "left", + // flex: 0.5, + // minWidth: 120, + // }, + // { + // field: "analyzed", + // headerName: "Analyzed", + // headerAlign: "center", + // align: "center", + // flex: 0.5, + // minWidth: 100, + // }, { field: "EventId", headerName: "Event ID/Process ID", @@ -86,336 +66,3 @@ export const columns = [ minWidth: 100, }, ]; - -export const rows = [ - { - id: 1, - timeStamp: "2025-04-01 08:15:23", - severity: "ERROR", - users: "dinesh", - message: "System restart initiated", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2456", - logType: "linux-kernel", - }, - { - id: 2, - timeStamp: "2025-04-01 08:16:10", - severity: "WARNING", - users: "aashu", - message: "Memory utilization ERROR", - uploadDate: "2025-04-01", - analyzed: false, - EventId: "OS-2457", - logType: "linux-auth", - }, - { - id: 3, - timeStamp: "2025-04-01 08:17:05", - severity: "INFO", - users: "dinesh", - message: "Disk space usage normal", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2458", - logType: "window-app", - }, - { - id: 4, - timeStamp: "2025-04-01 08:20:00", - severity: "Critical", - users: "root", - message: "CPU overload", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2459", - logType: "linux-sys", - }, - { - id: 5, - timeStamp: "2025-04-01 08:22:30", - severity: "ERROR", - users: "aashu", - message: "Network latency detected", - uploadDate: "2025-04-01", - analyzed: false, - EventId: "OS-2460", - logType: "linux-kernel", - }, - { - id: 6, - timeStamp: "2025-04-01 08:25:01", - severity: "WARNING", - users: "dinesh", - message: "Firewall access denied", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2461", - logType: "linux-auth", - }, - { - id: 7, - timeStamp: "2025-04-01 08:30:00", - severity: "INFO", - users: "aashu", - message: "System idle", - uploadDate: "2025-04-01", - analyzed: false, - EventId: "OS-2462", - logType: "window-app", - }, - { - id: 8, - timeStamp: "2025-04-01 08:35:10", - severity: "ERROR", - users: "dinesh", - message: "Disk ERROR detected", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2463", - logType: "linux-sys", - }, - { - id: 9, - timeStamp: "2025-04-01 08:40:22", - severity: "WARNING", - users: "root", - message: "Software update completed", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2464", - logType: "linux-auth", - }, - { - id: 10, - timeStamp: "2025-04-01 08:45:30", - severity: "Critical", - users: "dinesh", - message: "System shutdown due to power failure", - uploadDate: "2025-04-01", - analyzed: false, - EventId: "OS-2465", - logType: "linux-kernel", - }, - { - id: 11, - timeStamp: "2025-04-01 08:50:00", - severity: "INFO", - users: "aashu", - message: "User login detected", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2466", - logType: "window-app", - }, - { - id: 12, - timeStamp: "2025-04-01 09:00:10", - severity: "ERROR", - users: "root", - message: "Disk usage critical", - uploadDate: "2025-04-01", - analyzed: false, - EventId: "OS-2467", - logType: "linux-sys", - }, - { - id: 13, - timeStamp: "2025-04-01 09:10:01", - severity: "WARNING", - users: "dinesh", - message: "Memory leak detected", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2468", - logType: "linux-auth", - }, - { - id: 14, - timeStamp: "2025-04-01 09:20:30", - severity: "INFO", - users: "aashu", - message: "System idle", - uploadDate: "2025-04-01", - analyzed: false, - EventId: "OS-2469", - logType: "window-app", - }, - { - id: 15, - timeStamp: "2025-04-01 09:25:45", - severity: "Critical", - users: "root", - message: "Unexpected system crash", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2470", - logType: "linux-kernel", - }, - { - id: 16, - timeStamp: "2025-04-01 09:30:00", - severity: "WARNING", - users: "dinesh", - message: "CPU idle", - uploadDate: "2025-04-01", - analyzed: false, - EventId: "OS-2471", - logType: "linux-sys", - }, - { - id: 17, - timeStamp: "2025-04-01 09:35:23", - severity: "ERROR", - users: "aashu", - message: "Firewall breach detected", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2472", - logType: "linux-auth", - }, - { - id: 18, - timeStamp: "2025-04-01 09:40:00", - severity: "Critical", - users: "root", - message: "Power supply failure", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2473", - logType: "linux-kernel", - }, - { - id: 19, - timeStamp: "2025-04-01 09:45:15", - severity: "INFO", - users: "dinesh", - message: "Routine system check passed", - uploadDate: "2025-04-01", - analyzed: false, - EventId: "OS-2474", - logType: "window-app", - }, - { - id: 20, - timeStamp: "2025-04-01 09:50:40", - severity: "WARNING", - users: "aashu", - message: "Patch update installed", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2475", - logType: "linux-sys", - }, - { - id: 21, - timeStamp: "2025-04-01 09:55:01", - severity: "INFO", - users: "root", - message: "User logout detected", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2476", - logType: "linux-auth", - }, - { - id: 22, - timeStamp: "2025-04-01 10:00:20", - severity: "Critical", - users: "dinesh", - message: "Kernel panic detected", - uploadDate: "2025-04-01", - analyzed: false, - EventId: "OS-2477", - logType: "linux-kernel", - }, - { - id: 23, - timeStamp: "2025-04-01 10:10:25", - severity: "WARNING", - users: "aashu", - message: "Network latency issues", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2478", - logType: "linux-sys", - }, - { - id: 24, - timeStamp: "2025-04-01 10:15:10", - severity: "ERROR", - users: "root", - message: "ERROR I/O operations detected", - uploadDate: "2025-04-01", - analyzed: false, - EventId: "OS-2479", - logType: "linux-auth", - }, - { - id: 25, - timeStamp: "2025-04-01 10:20:45", - severity: "INFO", - users: "dinesh", - message: "Scheduled task completed", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2480", - logType: "window-app", - }, - { - id: 26, - timeStamp: "2025-04-01 10:30:20", - severity: "ERROR", - users: "aashu", - message: "Security breach detected", - uploadDate: "2025-04-01", - analyzed: false, - EventId: "OS-2481", - logType: "linux-kernel", - }, - { - id: 27, - timeStamp: "2025-04-01 10:40:30", - severity: "Critical", - users: "root", - message: "System shutdown due to ERROR", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2482", - logType: "linux-sys", - }, - { - id: 28, - timeStamp: "2025-04-01 10:45:10", - severity: "INFO", - users: "dinesh", - message: "Routine log rotation", - uploadDate: "2025-04-01", - analyzed: false, - EventId: "OS-2483", - logType: "window-app", - }, - { - id: 29, - timeStamp: "2025-04-01 10:50:00", - severity: "WARNING", - users: "aashu", - message: "Memory usage increased", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2484", - logType: "linux-auth", - }, - { - id: 30, - timeStamp: "2025-04-01 10:55:25", - severity: "Critical", - users: "root", - message: "Hard disk failure", - uploadDate: "2025-04-01", - analyzed: true, - EventId: "OS-2485", - logType: "linux-kernel", - }, -]; diff --git a/frontend/src/utils/api/fetchLogAnalytics.js b/frontend/src/utils/api/fetchLogAnalytics.js new file mode 100644 index 00000000..a31912a8 --- /dev/null +++ b/frontend/src/utils/api/fetchLogAnalytics.js @@ -0,0 +1,13 @@ +export default async function fetchAllLogs() { + const data = await fetch(`${import.meta.env.VITE_BACKEND_URL}/api/getLogAnalytics`) + + if(!data.ok) { + throw new Error("Network response was not ok" + data.statusText); + } + + const dataJson = await data.json(); + if (!dataJson) { + throw new Error("No data found"); + } + return dataJson; +}