-
Notifications
You must be signed in to change notification settings - Fork 3
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
fix: Unresolved comments in #608 #640
fix: Unresolved comments in #608 #640
Conversation
removed useless test
runner/src/log-entry/log-entry.ts
Outdated
@@ -0,0 +1,22 @@ | |||
import { LogType, LogLevel } from '../indexer-logger/indexer-logger'; |
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 see you created the class but where do you use it? I'm expecting to see it used somewhere. Even if you have to update Indexer and then comment it out again. It at least lets us know you ran it locally and it was still working.
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.
Im under the impression after my last sync with @morgsmccauley that because this is going to role out in a specific order this is strictly for resolving the issues # 1.
- Fix all unresolved comments in original PR
Prefix log indexes with __
Move creation of logs table to abstracted function
Update LogEntry to be a class - Uncomment provisioning of logs, add unit tests in Provisioner, and ensure integration tests pass
- Ensure auto-provisioning of logs for existing users works, and merge feat: Provision logs for existing users #636
- Uncomment logging calls, update unit tests in Indexer, and ensure integration tests pass
Because its rolling out in a specific order I would have to modify the indexer no matter what. Is there a reason we have to do it in step 1 as oppose to step 4. I would be modifying the indexer file regardless of it being commented out that would pollute this current PR by editing all the files again at once despite being commented out
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.
You don't have to actually implement test and release that code. It was more like, we are adding this class, was it actually used locally as a test? To make sure it does everything we need? You can just re-comment out indexer again afterward.
You mention below you used it so that's all good.
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 would go ahead and start using this class, even if the final result is commented out. We can worry about tests etc later, and just use TypeScript to guide/provide confidence. This will reduce the size of future PRs making things a bit easier.
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 integrated the LogEntry class and validated its functionality within the indexer-logger test suites. I have additional comments for the indexer.ts file itself but they are not in this pr. Do let me know if I should include them. I was going to introduce them in beginning stages of step 4 to keep the modifications small despite being commented out.
runner/src/log-entry/log-entry.ts
Outdated
@@ -0,0 +1,22 @@ | |||
import { LogType, LogLevel } from '../indexer-logger/indexer-logger'; |
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 code is tightly coupled with IndexerLogger
and is small enough that I think it could just exist within IndexerLogger
- we will never use one without the other. Can we please move it there?
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.
Yeah I agree it is tightly if not directly dependent and unusable without IndexerLogger
. But I think until we have the full picture of LogEntry keeping it separate allows for easier management and potential future expansions. Towards the end of the Epic if there is still not purpose of keeping them separate I think we can move it back with few issues.
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.
We can still keep a separate file, but house it under indexer-logger/
. It's only purpose is to be used within indexer-logger
so it makes sense to have there.
I want to reduce the noise in the root directory. As this code base starts to grow we should be creating higher level abstractions, housing related functionality, to make navigation easier.
runner/src/log-entry/log-entry.ts
Outdated
@@ -0,0 +1,22 @@ | |||
import { LogType, LogLevel } from '../indexer-logger/indexer-logger'; |
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 would go ahead and start using this class, even if the final result is commented out. We can worry about tests etc later, and just use TypeScript to guide/provide confidence. This will reduce the size of future PRs making things a bit easier.
Can you please update the PR title to something like |
runner/src/log-entry/log-entry.ts
Outdated
this.timestamp = new Date(); | ||
} | ||
|
||
static createLog (message: string, level: LogLevel, type: LogType, blockHeight?: number): LogEntry { |
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.
Introduced a static create method that takes all the necessary parameters for creating a LogEntry instance. This method eliminates the redundancy. Each static method (systemDebug, systemInfo, systemWarn, etc) now just calls the create method with appropriate params, reducing duplication and making the code more DRY.
}; | ||
|
||
await indexerLogger.writeLogs(logEntry); | ||
const debugEntry = LogEntry.systemDebug('Debug 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.
The IndexerLogger class is created with a specified logging level, and a log entry with a lower level is generated using the newly added LogEntry class.
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.
Pretty close! I don't have any comments from 608 which needs to be addressed anymore here. Just some comments on data organization and such. Can approve after remaining comments are resolved.
@@ -30,8 +30,23 @@ describe('IndexerLogger', () => { | |||
const infoEntry = LogEntry.systemInfo('Info message'); | |||
await indexerLogger.writeLogs(infoEntry); | |||
|
|||
const expectedQueryStructure = `INSERT INTO "${functionName}".__logs (block_height, date, timestamp, type, level, message) VALUES`; | |||
expect(query.mock.calls[0][0]).toContain(expectedQueryStructure); | |||
const timestampPattern = '\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d+\\+\\d{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.
I went with the regex approach. Im sure there is also one where we specify the timestamp
const specificDate = new Date(1673491200000) // March 15, 2023 00:00:00 UTC
specificDate.toISOString()
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 would not advise you use complicated things like regex's. Especially when testing correctness. Please use a hardcoded value. Unit tests are where you would want to text hard coded values as you can easily tell what soemthing is supposed to look like and what part of it doesn't match, if it doesnt. If someone told me my unit test failed because it didn't match some arbitrary regex, I'd have no clue why, what is different, and what needs to be fixed. And I would need to then understand this regex too.
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.
Mocking the timestamp for LogEntry instances may be difficult without modifying the constructor to accept an optional timestamp parameter. Since the timestamp is initialized within the constructor with the current system time by default.
constructor (
public readonly message: string,
public readonly level: LogLevel,
public readonly type: LogType,
public readonly blockHeight?: number
) {
this.timestamp = new Date();
}
unless we make timestamp not a readonly or something like this
constructor(
public readonly message: string,
public readonly level: LogLevel,
public readonly type: LogType,
public readonly blockHeight?: number,
timestamp?: Date // Optional parameter for specifying the timestamp
) {
if (timestamp) {
this.timestamp = timestamp; // Use the provided timestamp if available
} else {
this.timestamp = new Date(); // Otherwise, use the current system time
}
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 mentioned in a previous comment we can use Fake Timers, looks like you resolved it but didn't actually implement? Can you make sure to only resolve if you have followed up?
We don't need to inject the Date
/timestamp, we can mock the date like so:
it('should insert a single log entry into the database', async () => {
const date = new Date();
jest.useFakeTimers({ now: date.getTime() });
const indexerLogger = new IndexerLogger(functionName, LogLevel.INFO, mockDatabaseConnectionParameters, pgClient);
await indexerLogger.writeLogs(LogEntry.systemInfo('Info message'));
const expectedDate = date.toISOString().replace('T', ' ').replace('Z', '+00');
expect(query.mock.calls[0][0])
.toEqual(`INSERT INTO "${functionName}".__logs (block_height, date, timestamp, type, level, message) VALUES (NULL, '${expectedDate}', '${expectedDate}', 'system', 'INFO', 'Info message')`);
});
You may need to mock the Date
at the top level, and pass the mocked date value around to avoid mock conflicts across tests.
Also note I had to change the Date format because pgFormat
changes it under the hood. The alternative would be to use format
here in the test to get the same result.
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.
Adding an optional field to the parameter for the purpose of testing isn't outlandish. We do it quite often in fact. Honestly, you can also just say .contains( THE PART AFTER THE TIMESTAMP). The point I was making was we don't validate the query contains all of the expected values. As long as you expect on it, it's fine.
Validating the timestamp in a unit test is a separate problem, and I'm ok not mixing them.
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.
@morgsmccauley Ah I must have tunneled there and resolved it after I reading the initial comment. I didn't realize that implementation need jest to mock. Ill go ahead and mock it with FakeTimers
@@ -57,7 +40,7 @@ export default class IndexerLogger { | |||
async writeLogs ( | |||
logEntries: LogEntry | LogEntry[], | |||
): Promise<void> { | |||
const entriesArray = (Array.isArray(logEntries) ? logEntries : [logEntries]).filter(entry => this.shouldLog(entry.logLevel)); ; | |||
const entriesArray = (Array.isArray(logEntries) ? logEntries : [logEntries]).filter(entry => this.shouldLog(entry.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.
On the previous PR I mentioned changing this writeLogs
method to only take LogEntry[]
so we don't need this logic. Can we go ahead and make that change please?
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! It does require a large rebase, so go ahead and do that and I
l'll approve after skimming it over!
Incorporating Latest Changes in main to branch |
First few commits is from this branch #640. Created this branch based off the initial branch. This PR intends to introduce the creation of the logs table by provisioning the logsSchema and the follow CRON jobs for new Users but does not use or writeLogs to the new logsTable itself. If this is merged by itself new users will have unused log table but the provisioning will occur. To provision existing users - #636
Feat: created logEntry class and test cases
Chore: relocated createLogs to abstracted func
Chore: renamed schema idx to prefix with '__'