-
Notifications
You must be signed in to change notification settings - Fork 119
[FEAT]: System Logs #528
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
[FEAT]: System Logs #528
Conversation
@VipinDevelops why is the grid for log options re-rendering each time I open an overlay and close it ? Uploading Screen Recording 2024-09-06 at 5.36.19 PM.mov… |
web-server/app/api/stream/route.ts
Outdated
const startWatchers = () => { | ||
LOG_FILES.forEach((logFile) => { | ||
const watcher = watch(logFile.path, async (eventType) => { | ||
if (eventType === 'change' && !streamClosed) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put this 'change' string in a const or Enum.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure I will Make an Enum
eventSource.onmessage = (event) => { | ||
const data = JSON.parse(event.data); | ||
|
||
if (data.type === 'status-update') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same, these string literals should be stored as const or Enums
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure
) : ( | ||
<FlexBox col gap={2}> | ||
{Object.keys(services).map((serviceName) => { | ||
const ServiceName = serviceName as ServiceNames; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var name should be camelcase
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do it
Interesting I haven't added anything in the overlay that might cause Rerendering no state changes and all, can you share the video you tried uploading, please? |
web-server/src/slices/service.ts
Outdated
export type ServiceStatusState = { | ||
[key in ServiceNames]: Service; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional:
can be easily written as Record<ServiceNames, Service>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure will do that
web-server/src/slices/service.ts
Outdated
services: ServiceStatusState; | ||
loading: boolean; | ||
error?: string; | ||
active: string | null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not string,
saw it being implemented like
const active = useSelector((s) => s.service.active) as ServiceNames;
so initialize it as
active: ServiceNames | null;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then use can remove typecasting from here:
const active = useSelector((s) => s.service.active)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am removing this state to minimize the rerender I will pass the active service name as prop to the overlay page
web-server/src/slices/service.ts
Outdated
}, | ||
active: null, | ||
loading: true, | ||
error: undefined |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
undefined is usually never a good state to initliase with.
use null instead.
it means an 'intentional empty value'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure will do that
web-server/src/slices/service.ts
Outdated
type SetStatusPayload = { | ||
statuses: { [key in ServiceNames]: Status }; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional, use Record<ServiceNames, Status>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure
web-server/src/slices/service.ts
Outdated
name: 'services', | ||
initialState, | ||
reducers: { | ||
setActiveService: (state, action: PayloadAction<string | null>) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Payload wont't pe string if you implement previous comments.
instead ServiceNames
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure
|
||
const { addPage } = useOverlayPage(); | ||
|
||
const ServiceTitle: { [key: string]: string } = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Record<ServiceNames, string>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
got it
<Box | ||
component="span" | ||
sx={{ | ||
display: 'inline-block', | ||
marginLeft: '6px', | ||
width: '10px', | ||
height: '10px', | ||
borderRadius: '50%', | ||
backgroundColor: isUp ? '#28a745' : '#dc3545' | ||
}} | ||
></Box> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[optional]:
if empty component, <Box .... />
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
got it
web-server/src/constants/stream.ts
Outdated
export type ServiceStatus = { | ||
[key in ServiceNames]: { isUp: boolean }; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional:
Record<ServiceNames, {isUp: boolean}>
const containerRef = useRef<HTMLDivElement>(null); | ||
|
||
const services = useSelector( | ||
(state: { service: { services: ServiceStatusState } }) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why add type to state, it's derived directly, no need to pass it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will update
width: '10px', | ||
height: '10px', | ||
borderRadius: '50%', | ||
backgroundColor: isUp ? '#28a745' : '#dc3545' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i am assuming this is the online-offline dot on the right of log-title
we have some theme colors inbuilt.
search for how we use theme.colors.success.main
and theme.colors.error.main
in our code-base.
you won't have to create your own colors (mostly!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great thanks for letting me know , we can use similar colors for log as well but I was thinking the colors are useful because in CLI we have a lot of logs at once but in this case we only show log for one service at a time does these make sense in here ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, i don't understand your comment, re-explain?
the colors that you hardcoded (green and red) can be replaced with our own thematic colors of success
and error
. that's all i wanted you to change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got you eshan sorry I miss understood
Hey @samad-yar-khan You were right Actually I was using a state to update the Active service that caused extra rerenders I removed it and used props instead and now the page render is minimal similar to any other page in the project and it only rerenders when there is a new event pushed and state updated |
Hey @e-for-eshaan this is what you meant right? |
Ohk Got it I will update it ASAP |
How about now @e-for-eshaan ? you like it Looking colorful right |
Hey @e-for-eshaan and @samad-yar-khan , Thank you so much for your review—it helped improve the PR's quality alot. I’ve made the requested changes and would appreciate your taking another look. Thanks again! 😄 |
I would appreciate your reviews as well, @adnanhashmi09 and @shivam-bit. 😄 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@VipinDevelops please go through Flexbox
& Line
components with their props.
|
||
useEffect(() => { | ||
if (!serviceName) { | ||
router.push('/system'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't hardcode /system
, instead use ROUTES.SYSTEM.PATH
.
Check codebase for usage of ROUTES
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay use this ROUTES.SYSTEM_LOGS.PATH
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea
const containerRef = useRef<HTMLDivElement>(null); | ||
const services = useSelector((state) => state.service.services); | ||
const logs = useMemo(() => { | ||
return serviceName ? services[serviceName]?.logs || [] : []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on prop types serviceName isn't optional, so it will be always true.
so simply use services[serviceName]?.logs || []
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in that case we don't even have to redirect to system-status
right
<Box | ||
ref={containerRef} | ||
sx={{ | ||
padding: '16px 24px', | ||
borderRadius: 2, | ||
overflowY: 'auto', | ||
maxHeight: '750px', | ||
whiteSpace: 'pre-wrap', | ||
wordBreak: 'break-word', | ||
lineHeight: 1.6, | ||
marginTop: '8px' | ||
}} | ||
> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use FlexBox
,
Most of the styling will be done automatically.
<Typography | ||
key={index} | ||
style={{ | ||
marginBottom: '8px', | ||
fontFamily: 'monospace', | ||
padding: '2px' | ||
}} | ||
> | ||
{log} | ||
</Typography> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use our custom <Line>
component.
Most of the styling will be done automatically.
web-server/src/constants/service.ts
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i am quite sure we already have this const map declared somewhere.
in the cli folder for sure, or check resources.ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@VipinDevelops i think it you can use import { ServiceNames } from '@/constants/service';
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shivam-bit You mean no changes in this we can use it, right?
sx={{ | ||
fontWeight: '500', | ||
fontSize: '0.95em', | ||
color: isUp ? '#28a745' : '#dc3545', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use theme.colors.success.main
and theme.colors.secondary.main
Import useTheme
from mui
<FlexBox col relative fullWidth flexGrow={1}> | ||
<FlexBox | ||
alignCenter | ||
sx={{ width: '100%', paddingTop: '8px' }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather then giving width:100%
use fullwidth
prop on Flexbox
also you can use paddingTop={1}
directly on Flexbox
<CardRoot | ||
key={serviceName} | ||
onClick={() => handleCardClick(serviceKey)} | ||
sx={{ | ||
transition: 'box-shadow 0.2s ease', | ||
'&:hover': { | ||
boxShadow: '0 4px 15px rgba(0, 0, 0, 0.1)' | ||
}, | ||
backgroundColor: 'rgba(255, 255, 255, 0.05)', | ||
borderRadius: '12px', | ||
border: `1px solid ${ | ||
isUp ? borderColor : alpha(theme.colors.error.main, 0.3) | ||
}`, | ||
padding: '16px', | ||
cursor: 'pointer', | ||
position: 'relative', | ||
overflow: 'hidden' | ||
}} | ||
> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather then using CardRoot
use Button
, it will work same way with most styling issues sorted for you.
web-server/pages/system-logs.tsx
Outdated
showEvenIfNoTeamSelected={true} | ||
isLoading={loading} | ||
> | ||
{isGithubIntegrated ? <SystemStatus /> : <Loader />} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't think system log has to do anything with github integration.
<Box | ||
sx={{ | ||
display: 'flex', | ||
alignItems: 'center', | ||
justifyContent: 'center' | ||
}} | ||
> | ||
<CircularProgress color="primary" size={50} /> | ||
</Box> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use <Flexbox alignCenter justifyCenter/> instes of
Box`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or <Flexbox centered/>
Hey @shivam-bit Thanks alot man amazing comments, Here you mean I should Pass props in the FlexBox and Line to provide them styles right ? |
yes correct @VipinDevelops |
Hey @shivam-bit, thank you so much for suggesting custom components! Using them really takes away the pain of writing a lot of CSS. |
<Line | ||
sx={{ | ||
fontWeight: '500', | ||
fontSize: '0.95em', | ||
color: isUp ? '#28a745' : '#dc3545', | ||
lineHeight: '1.4' | ||
}} | ||
fontWeight={'500'} | ||
fontSize={'0.95em'} | ||
lineHeight={'1.4'} | ||
white | ||
> | ||
Status: | ||
</Line> | ||
<Line | ||
fontWeight={'500'} | ||
fontSize={'0.95em'} | ||
lineHeight={'1.4'} | ||
color={ | ||
isUp | ||
? theme.colors.success.main | ||
: theme.colors.error.main | ||
} | ||
marginLeft={'8px'} | ||
> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@VipinDevelops prefer to use something like <Line bold bigish white>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh yeah forgot this one
|
||
return ( | ||
<FlexBox col gap={2} padding={'16px'}> | ||
<Line bold white fontSize="24px" marginBottom={2}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rathe then fontSize="24px"
use huge
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I thought this one looks too small but if you suggest I will update it
<Divider sx={{ mb: 2, backgroundColor: theme.colors.secondary.light }} /> | ||
|
||
{loading ? ( | ||
<FlexBox justifyCenter alignCenter minHeight={'50vh'}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't think anywhere we are showing loader with minHeight={'50vh'}
, please look into other places where we are showing a loader, or fill
as a flexbox prop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep you are correct Sure
Hey @shivam-bit Please take a look, I made the requested Changes |
@VipinDevelops LGTM!!🚀🚀 |
Big stuff @VipinDevelops 🚀 ! Approved! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM @VipinDevelops
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good stuff vipin 🚀
Acceptance Criteria Fulfillment
Created a System page on the app that checks whether the middleware system is fully healthy. Users should be able to view the related logs directly in the UI without needing to open the terminal or any other tool.
How it works?
we monitor services (API Server, Redis, Postgres, Sync Server) and stream real-time updates to the client. It checks each service's status through commands or API requests and reads logs when files change. When a service status changes or logs update, the client is notified via a server-sent event stream, keeping the UI updated with the latest information in realtime.
Proposed Changes (including videos or screenshots)
Screencast.from.2024-09-07.23-48-52.webm