-
Notifications
You must be signed in to change notification settings - Fork 106
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
system logs ui changes #571
Conversation
Thanks for your contribution, @vishalmishraa! I would love to accept this PR, but it needs a few improvements to avoid performance issues. Given that there could be thousands of lines being rendered, we do need to keep an eye out for excessive calls to JSON.stringify, Array.includes, and various other places. Additionally, I think the metadata doesn't really need to be printed. What do you think? |
Linter failed. We need to sort out the linting issues but for now you can check our contributing guide to see how to fix that. Let us know if it doesn't work out for you. |
hi , @jayantbh , I’ll remove the metadata entirely, so there’s no need to use JSON.stringify. for array.includes, I’ll use Set() instead, as it takes O(1) time complexity, which is a better approach. . am I taking the correct approach? and yup, I need to fix the linting issues |
Directionally I think yes. I haven't done a proper review but I'll ask the team to check it out. |
This PR could use some tests. Especially with various kinds of logs that might come through. |
And of course, to test the performance of how many lines you're able to process via your functions as a benchmark. |
I ran a quick test myself based on the number of lines, and I think we'll hit other performance limits before we hit perf issues with the regexes and matches. |
okay , i think i need to change my approach ,Could you suggest an alternatives or any way to do that ? I will work on implementing it accordingly. |
No no. I'm saying you might not need to change your approach. |
so , do i need to do any improvements or it is good to go ? |
This. |
Okay, I’m working on it. I’ll be writing tests in ./web-server/src/utils/test, where I’ll create a logFormatter.test.ts file and write the tests. |
@jayantbh I need help regarding generating different types of system logs. Should I generate new logs for testing? If yes, how can I generate other different logs? Or is it better to use the logs that are currently being generated and write test for them only? UPDATE : got some different kind of logs from my own dbs , gonna use them in testing :FOR REDIS :FOR POSTGRES:AND i think for |
I think handle for the variety of logs that are generated today. |
i think the function I wrote is not feasible for parsing all types of logs. There are several different types of logs, such as system-generated logs (some print statements in backend code), HTTP server error logs, and others. i did some research on better logging solutions and found a CNCF-based library called Fluentd, which offers unified logging, better parsing, and improved data collection and observation. It's also lightweight, requiring only 40 to 50 MB of space. I think it could be a good fit for this project. more details: since , i think current approach may not be the right fit right now, I’m focusing on other way to solve it. |
I suspected it could go in this way. |
Then , there will be some logs, which can't be parsed, and they will be displayed as it is without colors. I'll try to add regex for logs that are frequently generated, should i proceed with this ? |
…ata synchronization logs
Yea, I think you could try that. Something is better than nothing after all. But make sure you have tests. |
Thanks, @jayantbh. I've updated the functions and added the tests. Please review them. Reference for RegexesRedis Log Regex
HTTP Gunicorn Log RegexFor details on the HTTP Gunicorn log regex, refer to the official Gunicorn documentation. |
Looks better. :) Could you use Error Boundaries to show the logs in completely plain-text (the view before your changes that is) in case something breaks in the off chance? Basically the idea is, that if something does break, it should at least show the plain version of the logs. Of course they should be shown in a tiny text at the top or bottom, or somewhere that they ran into an error and they should create an issue, which should link to: https://github.com/middlewarehq/middleware/issues/new/choose |
i did this :
But it didn’t work, and I think it should have worked. |
Also i think the approach I'm using now would be work good because the component which should be passed into the ErrorBoundary fallback should also receive serviceName and other props as it should render logs in plain text. So, in the future, if we make any improvements to the UI for SystemLogs like (implementing search feature ,etc..), we would need to apply the same modifications to the custom fallback component as well, since it's rendering system logs in plain text. Therefore, it would be better to handle this in the same position . |
Hi @jayantbh , I’ve implemented the error boundary and apologize for the confusion earlier. You were right , I was testing it incorrectly, which is why it didn’t work. However, I’ve now implemented it properly. I’ve also created a useSystemLog hook for it and separated the component.Please check it now. |
@vishalmishraa could you share screenshots of the error boundary in effect? |
Sure :Error.Test.mov |
Looks great! Meanwhile, we'll give this a round of final reviews. But I think we're looking good visually/functionally. |
Okay, I guess ignore that for now. We'll do the reviews as soon as we're able. :) |
web-server/src/utils/logFormatter.ts
Outdated
export const parseLogLine = (rawLogLine: string): ParsedLog | null => { | ||
const generalLogMatch = rawLogLine.match(generalLogRegex); | ||
if (generalLogMatch) { | ||
const [, timestamp, , logLevel, message] = generalLogMatch; |
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.
const [_pickAname, timestamp, _pickAnotherName, logLevel, message]
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/utils/logFormatter.ts
Outdated
const [method, path] = request.split(' '); | ||
return { | ||
timestamp, | ||
logLevel: 'INFO', // Assuming all HTTP logs are INFO level |
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.
all these string constants should be wrapped in an enum in our src/types/resources.ts
enum YourEnumName
{
INFO = 'INFO',
DEBUG = 'DEBUG'
...other_possible_values...
}
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.
done , created a enum LogLevel.
web-server/src/utils/logFormatter.ts
Outdated
|
||
const postgresLogMatch = rawLogLine.match(postgresLogRegex); | ||
if (postgresLogMatch) { | ||
const [, timestamp, , logLevel, message] = postgresLogMatch; |
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:
const [_pickAname, timestamp, _pickAnotherName, logLevel, message]
web-server/src/utils/logFormatter.ts
Outdated
|
||
const dataSyncLogMatch = rawLogLine.match(dataSyncLogRegex); | ||
if (dataSyncLogMatch) { | ||
const [, logLevel, action, service, message] = dataSyncLogMatch; |
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
export const validLogLevels = new Set([ | ||
'DEBUG', | ||
'INFO', | ||
'NOTICE', | ||
'WARNING', | ||
'ERROR', | ||
'LOG', | ||
'FATAL', | ||
'PANIC', | ||
'STATEMENT', | ||
'DETAIL' | ||
]); |
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.
this should be an enum in our resources
file
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 added these as enums and also removed the validLogLevels logic from the parser. Previously, I was using two approaches to parse PostgreSQL logs, but during testing, I noticed that my first approach, PostgresMultilineLogMatch, can parse both types of PostgreSQL logs. Therefore, there's no need to write separate logic for each type ,refer to the official postgres documentation . and this article also for log levels .
web-server/src/utils/logFormatter.ts
Outdated
export const parseLogLine = (rawLogLine: string): ParsedLog | null => { | ||
const generalLogMatch = rawLogLine.match(generalLogRegex); | ||
if (generalLogMatch) { | ||
const [_fullLog, timestamp, _unused, logLevel, message] = generalLogMatch; |
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.
_unused
this looks off, name it correctly to what this variable stands for, and the underscore is enough to know that this variable is unused
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.
done. ,changing it with _pid
web-server/src/utils/logFormatter.ts
Outdated
_unused, | ||
_unused2, |
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 with these :)
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.
changed the second one to _username , and first one with _ (underscore) refer to this
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, good stuff @vishalmishraa 🎉
export interface ParsedLog { | ||
timestamp: string; | ||
logLevel: string; | ||
message: string; | ||
role?: string; | ||
ip?: 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.
move this interface declaration to resources.ts
. we use that for all our type declaration
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.
done
<Line | ||
key={index} | ||
marginBottom={'8px'} | ||
fontSize={'14px'} | ||
fontFamily={'monospace'} | ||
> |
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.
for fontsize use props on our line component tiny | small | medium |bigish | big | huge
.
for fontFamily directly pass mono
as prop
const logs = useMemo(() => { | ||
return services[serviceName]?.logs || []; | ||
}, [serviceName, services]); |
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.
const logs = useMemo(() => services[serviceName]?.logs || [], [serviceName, services]);
<Line | ||
key={index} | ||
marginBottom={'8px'} | ||
fontSize={'14px'} | ||
fontFamily={'monospace'} |
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 as other requested changes
fontSize={'14px'} | ||
fontFamily={'monospace'} | ||
> | ||
<Line component="span" color="info.main"> |
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 think you can do this like <Line color="info">
|
||
const { timestamp, ip, logLevel, message } = log; | ||
return ( | ||
<Line medium marginBottom={'8px'} fontFamily={'monospace'}> |
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.
Try this<Line mono marginBottom={1}>
|
||
export const PlainLog = ({ log }: { log: string; index: number }) => { | ||
return ( | ||
<Line medium marginBottom={'8px'} fontFamily={'monospace'}> |
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.
Try this <Line mono marginBottom={1}>
, it should ideally give you the same effect.
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.
done
@vishalmishraa LGTM!🚀🚀🚀 |
I think this doesn't need another round of reviews. We can go ahead and merge this. Any remaining changes will probably be minor and can be taken up in subsequent PRs. |
Congrats on getting this merged! |
Linked Issue(s)
issue #555
Acceptance Criteria fulfillment
Proposed changes (including videos or screenshots)
Further comments