Skip to content
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

Improve logs download: adding query parameters #365

Merged
merged 13 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 71 additions & 5 deletions dashboard/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.0",
"@mui/material": "^5.15.14",
"@mui/x-date-pickers": "^7.2.0",
"@rainbow-me/rainbowkit": "^2.0.2",
"@tanstack/react-query": "^5.28.4",
"classnames": "^2.5.0",
"dayjs": "^1.11.10",
"ethers": "^6.10.0",
"express": "^4.18.2",
"micromodal": "^0.4.10",
Expand Down
183 changes: 145 additions & 38 deletions dashboard/src/components/Admin/DownloadLogs.tsx
Original file line number Diff line number Diff line change
@@ -1,55 +1,162 @@
import React, { useState } from 'react'
import React, { useCallback, useState } from 'react'
import Image from 'next/image'
import { useAdminContext } from '@context/AdminProvider'
import {
Button,
TextField,
Select,
MenuItem,
FormControl,
InputLabel
} from '@mui/material'
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'
import { LocalizationProvider, DateTimePicker } from '@mui/x-date-pickers'
import dayjs, { Dayjs } from 'dayjs'

import DownloadSVG from '../../assets/download.svg'
import styles from './index.module.css'
import Button from '@mui/material/Button'
import { useAdminContext } from '@context/AdminProvider' // Assuming the context is available

export default function DownloadLogs() {
export default function DownloadButton() {
const [showFilters, setShowFilters] = useState(false)
const [isLoading, setLoading] = useState(false)
const [startDate, setStartDate] = useState<Dayjs | null>(dayjs())
const [endDate, setEndDate] = useState<Dayjs | null>(dayjs())
const [maxLogs, setMaxLogs] = useState('')
const [moduleName, setModuleName] = useState('')
const [level, setLevel] = useState('')
const { signature, expiryTimestamp } = useAdminContext()

const Spinner = () => {
return <span className={styles.loader}></span>
}

async function downloadLogs() {
if (!expiryTimestamp || !signature) {
console.error('Missing expiryTimestamp or signature')
return
}
const downloadLogs = useCallback(async () => {
const startDateParam = startDate ? `&startTime=${startDate.toISOString()}` : ''
const endDateParam = endDate ? `&endTime=${endDate.toISOString()}` : ''
const maxLogsParam = maxLogs ? `&maxLogs=${maxLogs}` : ''
const moduleNameParam =
moduleName && moduleName !== 'all' ? `&moduleName=${moduleName}` : ''
const levelParam = level && level !== 'all' ? `&level="${level}"` : ''

setLoading(true)
try {
const response = await fetch(`/logs`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ expiryTimestamp, signature })
})

if (!response.ok) {
throw new Error('Network response was not ok')
if (!expiryTimestamp || !signature) {
console.error('Missing expiryTimestamp or signature')
return
}

const response = await fetch(
`/logs?${startDateParam}${endDateParam}${maxLogsParam}${moduleNameParam}${levelParam}`,
{
headers: {
'Content-Type': 'application/json'
},
method: 'POST',
body: JSON.stringify({ expiryTimestamp, signature })
}
)
const data = await response.json()
const dataStr =
'data:application/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data))
const download = document.createElement('a')
download.setAttribute('href', dataStr)
download.setAttribute('download', 'LogsData.json')
document.body.appendChild(download)
download.click()
download.remove()
if (data) {
const dataStr =
'data:application/json;charset=utf-8,' +
encodeURIComponent(JSON.stringify(data))
const download = document.createElement('a')
download.setAttribute('href', dataStr)
download.setAttribute('download', 'LogsData.json')
document.body.appendChild(download)
download.click()
download.remove()
}
setLoading(false)
} catch (error) {
console.error('Error downloading logs:', error)
} finally {
console.error(error)
setLoading(false)
}
}
}, [startDate, endDate, maxLogs, moduleName, level])

return (
<Button onClick={downloadLogs} variant="outlined">
{isLoading ? <Spinner /> : <div>Download logs</div>}
</Button>
<div className={styles.column}>
<Button type="button" onClick={() => setShowFilters(!showFilters)}>
Download Logs
</Button>

{showFilters && (
<div className={styles.filters}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<FormControl fullWidth margin="normal">
<DateTimePicker
label="Start Date"
value={startDate}
onChange={(newDate) => setStartDate(newDate)}
/>
</FormControl>
<FormControl fullWidth margin="normal">
<DateTimePicker
label="End Date"
value={endDate}
onChange={(newDate) => setEndDate(newDate)}
/>
</FormControl>
</LocalizationProvider>
<TextField
label="Max Logs"
type="number"
value={maxLogs}
onChange={(e) => setMaxLogs(e.target.value)}
fullWidth
margin="normal"
variant="outlined"
/>
<FormControl fullWidth margin="normal">
<InputLabel id="select-module-name-label">Module Name</InputLabel>
<Select
labelId="select-module-name-label"
label="Module Name"
id="module-name"
value={moduleName}
onChange={(e) => setModuleName(e.target.value)}
>
<MenuItem value="all">all</MenuItem>
<MenuItem value="http">http</MenuItem>
<MenuItem value="p2p">p2p</MenuItem>
<MenuItem value="indexer">indexer</MenuItem>
<MenuItem value="reindexer">reindexer</MenuItem>
<MenuItem value="provider">provider</MenuItem>
<MenuItem value="database">database</MenuItem>
<MenuItem value="config">config</MenuItem>
<MenuItem value="core">core</MenuItem>
<MenuItem value="OceanNode">OceanNode</MenuItem>
</Select>
</FormControl>

<FormControl fullWidth margin="normal">
<InputLabel id="select-level-label">Level</InputLabel>
<Select
labelId="select-level-label"
label="Level"
id="level"
value={level}
onChange={(e) => setLevel(e.target.value)}
>
<MenuItem value="all">all</MenuItem>
<MenuItem value="error">error</MenuItem>
<MenuItem value="warn">warn</MenuItem>
<MenuItem value="info">info</MenuItem>
<MenuItem value="http">http</MenuItem>
<MenuItem value="verbose">verbose</MenuItem>
<MenuItem value="debug">debug</MenuItem>
<MenuItem value="silly">silly</MenuItem>
</Select>
</FormControl>

<Button
type="button"
onClick={downloadLogs}
variant="outlined"
startIcon={
<Image src={DownloadSVG} alt="download button" width={24} height={24} />
}
disabled={isLoading}
>
Download
</Button>
</div>
)}
</div>
)
}
2 changes: 1 addition & 1 deletion dashboard/src/components/Admin/index.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
min-width: 245px;
display: flex;
flex-direction: column;
padding: 40px;
padding: 20px;
}

.title {
Expand Down
4 changes: 2 additions & 2 deletions dashboard/src/components/Admin/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ export default function AdminActions() {
<div className={styles.unauthorised}>Your account does not have admin access</div>
)}

{(!signature || !validTimestamp) && admin && (
{(!signature || !validTimestamp) && isConnected && admin && (
<button type="button" className={styles.unlockButton} onClick={generateSignature}>
Unlock
</button>
)}
{isConnected && signature && validTimestamp && admin && (
{isConnected && signature && validTimestamp && isConnected && admin && (
<Stack spacing={2} direction="column">
<DownloadLogs />
<StopNode />
Expand Down
28 changes: 28 additions & 0 deletions dashboard/src/components/Dashboard/Menu.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.root {
border-radius: 12px;
background: #FFF;
max-width: 260px;
display: flex;
flex-direction: column;
padding: 40px 28px;
min-width: 260px;
}

.title {
color: #3D4551;
font-family: Helvetica;
font-size: 20px;
font-style: normal;
font-weight: 700;
line-height: 140%;
margin-bottom: 47px;
}

@media screen and (max-width: 700px) {
.root {
max-width: none;
width: 90vw;
margin: 0 auto;
padding: 20px;
}
}
1 change: 1 addition & 0 deletions dashboard/src/components/Dashboard/index.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
flex-direction: row;
gap: 28px;
position: relative;
min-height: 550px;
}

.bodyContainer {
Expand Down
Loading
Loading