Skip to content

Commit

Permalink
Added Minimum Log Filter
Browse files Browse the repository at this point in the history
Used useReducer React Hook to modify the payload as this component will be changed differently each time
  • Loading branch information
TBThomas56 committed May 23, 2024
1 parent 430f122 commit cb96b90
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 64 deletions.
124 changes: 60 additions & 64 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { ThemeProvider } from "@emotion/react";
import { useEffect, useState } from "react";
import { useEffect, useState, useReducer } from "react";
import Log_Menu from "./components/Log_Menu.tsx";
import { theme } from "./theme";
import BoxBasic from "./components/Box";
import {PayloadInterface,ActionType,QueryString} from "./schema/interfaces.ts";
import { payload } from "./schema/payload.ts";

import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
Expand All @@ -10,18 +13,59 @@ import TableContainer from '@mui/material/TableContainer';
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper';
import { TableHead } from "@mui/material";
import { log_levels } from "./schema/Log_Levels.ts";

type getMessageReturn = [string[],string[],string[],string[],number[],string[]]
const apiURL = "/api/views/search/sync";
const password = "token";
let username: string;
const query: QueryString = {};

const ACTIONS = {
LOGFILTER: "level",
BEAMLINE: "beamline",
APP: "application",
};


type getMessageReturn = [string[],string[],string[],string[],number[],string[]];

function App() {
// API responses to be shown
const [time, setTime] = useState<string[]>([]);
const [host, setHost] = useState<string[]>([]);
const [debug, setDebug] = useState<string[]>([]);
const [logs, setLogs] = useState<string[]>([]);
const [log_lvl, setLog_lvl] = useState<number[]>([]);
const [app_name,setApp_name] = useState<string[]>([]);
const [logfilter, setLogfilter] = useState<number>(7);
const [logPayload, handlePayload] = useReducer(reducer, payload);

useEffect(() => {
// Log_Menu Props
const handleLogFilterChange = (newLogFilterValue: number) => {
setLogfilter(newLogFilterValue);
handlePayload({type: ACTIONS.LOGFILTER, log_level: newLogFilterValue});
};

function reducer(payload:PayloadInterface,action:ActionType) {
switch (action.type){
case ACTIONS.LOGFILTER:
query.filter = `level: <=${action.log_level}`;
break;
case ACTIONS.BEAMLINE:
query.beamline = `beamline: ${action.query_condition}`;
break;
case ACTIONS.APP:
query.app_name = `application_name: ${action.query_condition}`;
break;
}
const query_arr:string[] = Object.values(query);
payload.queries[0].query.query_string = query_arr.join(" AND ");
const newPayload = {...payload};
return newPayload
}

useEffect(() => {
console.log(logPayload.queries[0].query.query_string);
async function fetchData(
url: string,
username: string,
Expand Down Expand Up @@ -64,46 +108,6 @@ function App() {
}
}

const apiURL = "/api/views/search/sync";
const password = "token";
let username:string;

// Add payload for the request
const payload = {
// id: "661626cbe7b8a27f59bd1175",
parameters: [],
queries: [
{
query: {
type: "elasticsearch",
query_string: "beamline:i15 AND application_name:gda",
},
timerange: {
from: 300,
type: "relative",
},
filters: [],
search_types: [
{
limit: 100,
offset: 0,
sort: [
{
field: "timestamp",
order: "DESC",
},
],
fields: [],
decorators: [],
type: "messages",
filter: null,
filters: [],
},
],
},
],
};

// reads file from folder - add custom API key to this file
(async () => {
try {
Expand All @@ -123,11 +127,14 @@ function App() {
console.error("Error collecting password:", error);
}
})();
}, []);
}, [logPayload]);



return (
<ThemeProvider theme={theme}>
<h1>Athena Logpanel </h1>
<Log_Menu logFilterValue={logfilter} onLogFilterChange={handleLogFilterChange}/>
<BoxBasic>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
Expand All @@ -141,16 +148,18 @@ function App() {
</TableRow>
</TableHead>
<TableBody>
{logs.map((log,index) => (
<TableRow sx={{backgroundColor:getColor(log_lvl[index])}}>
{logs.map((log,index) => {
return (
<TableRow sx={{backgroundColor:getColor(log_lvl[index])}} key={index}>
<TableCell><pre>{time[index]}</pre></TableCell>
<TableCell><pre>{debug[index]}</pre></TableCell>
<TableCell><pre>{host[index]}</pre></TableCell>
<TableCell><pre>{app_name[index]}</pre></TableCell>
<TableCell><pre>{log}</pre></TableCell>
{/* sx={{ '&:last-child td, &:last-child th': { border: 0 } }} */}
</TableRow>
))}
</TableRow>
);
})},
</TableBody>
</Table>
</TableContainer>
Expand All @@ -175,15 +184,15 @@ function getMessage(logging: JSON): undefined | getMessageReturn {
const logs = id[keys].messages;
// populate different components of logged data and identifying log level
for (const msg in logs) {
const formattedTimestamp = logs[msg]["message"]["timestamp"].replace(/[TZ]/g, ' ')
const formattedTimestamp = logs[msg]["message"]["timestamp"].replace(/[TZ]/g, ' ');
timestamp.push(
`${formattedTimestamp}`
);
host.push(logs[msg]["message"]["source"])
host.push(logs[msg]["message"]["source"]);
app_name.push(logs[msg]["message"]["application_name"]);
const level = logs[msg]["message"]["level"];
const log_message = logs[msg]["message"]["full_message"];
const log_level_str = getLogLevel(level);
const log_level_str = log_levels[level] || "UNKNOWN";
debug.push(log_level_str);
message.push(log_message);
log_level.push(level);
Expand All @@ -196,19 +205,6 @@ function getMessage(logging: JSON): undefined | getMessageReturn {
}
}

function getLogLevel(level_val:number): string {
const log_levels: {[key: number]: string} = {
0:"EMERG",
1:"ALERT",
2:"CRIT",
3:"ERROR",
4:"WARN",
5:"NOTICE",
6:"INFO",
7:"DEBUG",};
const level = log_levels[level_val] || "UNKNOWN";
return level;
}
async function readFile(): Promise<string> {
const filePath = "src/token.txt";
const response = await fetch(filePath) ;
Expand Down
43 changes: 43 additions & 0 deletions src/components/Log_Menu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select, { SelectChangeEvent } from '@mui/material/Select';
import { log_levels } from '../schema/Log_Levels';

interface Props {
logFilterValue: number;
onLogFilterChange: (newLogFilterValue: number) => void;
}

const BasicSelect: React.FC<Props> = ({ logFilterValue, onLogFilterChange }) => {
const handleChange = (event: SelectChangeEvent) => {
const newLogFilterValue = event.target.value as unknown as number;
onLogFilterChange(newLogFilterValue);
};

return (
<Box sx={{ minWidth: 120 }}>
<FormControl fullWidth>
<InputLabel id="log-filter-id">Minimum Log Filter</InputLabel>
<Select
labelId="log-filter-id"
id="log-filter-label"
value={logFilterValue.toString()}
label="Minimum Log Filter"
onChange={handleChange}
>
{Object.entries(log_levels).map(([level_value, level_name]) => (
<MenuItem key={level_value} value={parseInt(level_value)}>
{level_name}
</MenuItem>
))}

</Select>
</FormControl>
</Box>
);
}

export default BasicSelect;
9 changes: 9 additions & 0 deletions src/schema/Log_Levels.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const log_levels: {[key: number]: string} = {
0:"EMERG",
1:"ALERT",
2:"CRIT",
3:"ERROR",
4:"WARN",
5:"NOTICE",
6:"INFO",
7:"DEBUG",};
50 changes: 50 additions & 0 deletions src/schema/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Payload Type Interfaces
export interface PayloadInterface {
parameters: string[];
queries: Query[];
}

export interface Query {
query: QueryDetails;
timerange: Timerange;
filters: string[];
search_types: SearchType[];
}

export interface QueryDetails {
type: string;
query_string: string;
}

export interface Timerange {
from: number;
type: string;
}

export interface SearchType {
limit: number;
offset: number;
sort: Sort[];
fields: string[];
decorators: string[];
type: string;
filter: string | null;
filters: string[];
}

export interface Sort {
field: string;
order: string;
}

export interface ActionType {
type: string;
log_level?: number | 7;
query_condition?: string | "";
}

export interface QueryString {
app_name?: string | "*";
beamline?: string | "*";
filter?: string | "*";
}
34 changes: 34 additions & 0 deletions src/schema/payload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Payload_interface } from "./interfaces";

Check failure on line 1 in src/schema/payload.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'"./interfaces"' has no exported member named 'Payload_interface'. Did you mean 'PayloadInterface'?

Check failure on line 1 in src/schema/payload.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

'"./interfaces"' has no exported member named 'Payload_interface'. Did you mean 'PayloadInterface'?
export const payload: Payload_interface = {
parameters: [],
queries: [
{
query: {
type: "elasticsearch",
query_string: "",
},
timerange: {
from: 300,
type: "relative",
},
filters: [],
search_types: [
{
limit: 100,
offset: 0,
sort: [
{
field: "timestamp",
order: "DESC",
},
],
fields: [],
decorators: [],
type: "messages",
filter: null,
filters: [],
},
],
},
],
};

0 comments on commit cb96b90

Please sign in to comment.