Closed joshgachnang closed 6 months ago
PR Description updated to latest commit (https://github.com/FlourishHealth/ferns-api/commit/5ee84a0e23d917c30f07f70e6f454c0aff94209b)
⏱️ Estimated effort to review [1-5] | 2, because the changes are focused and well-defined, involving integration with Sentry for specific logging functionality and the addition of tests to verify this behavior. The changes are not extensive and are localized to specific parts of the code, making the review process straightforward. |
🧪 Relevant tests | Yes |
🔍 Possible issues | Logging Verbosity: The addition of Sentry logging for every query that exceeds a limit without pagination could potentially lead to a high volume of log messages, especially if the API is heavily used. This could clutter the Sentry dashboard and might require filtering or rate limiting strategies. |
Mock Completeness: The mocking of Sentry methods in the test file is a good practice, but it's important to ensure that all relevant Sentry behaviors are accurately represented in the mocks to avoid discrepancies between test and production environments. | |
🔒 Security concerns | No |
Category | Suggestions | ||||||
Best practice |
Use TypeScript utility types for more focused mocking.___ **Consider using TypeScript'sPartial or Pick utility types to mock only the necessary Sentry methods instead of the entire module. This approach can make the test more focused and maintainable.** [src/api.test.ts [29-38]](https://github.com/FlourishHealth/ferns-api/pull/370/files#diff-7859a5148ded19af212367ec9a3558864109c5515dea657bc8f11ee238765dc7R29-R38) ```diff jest.mock("@sentry/node", () => { - // Auto-mock the Sentry module - const originalModule = jest.requireActual("@sentry/node"); - + const { captureMessage, captureException, isInitialized } = jest.requireActual("@sentry/node"); return { - ...originalModule, // Use the original module's implementations captureMessage: jest.fn(), captureException: jest.fn(), - isInitialized: jest.fn(() => true), // Override isInitialized + isInitialized: jest.fn(() => true), }; }); ```
| Abstract Sentry functionality behind a custom logger for better decoupling.___ **Instead of directly usingSentry.isInitialized() and Sentry.captureMessage(msg) in the business logic, consider abstracting Sentry's functionality behind a custom logger or error handler. This can decouple your application logic from a specific logging or error tracking implementation, making it easier to switch or extend in the future.** [src/api.ts [574-576]](https://github.com/FlourishHealth/ferns-api/pull/370/files#diff-769911c416ccf8514d8fd941ae0abe8fb5c606ade0c218e22151a5f5f9f3d700R574-R576) ```diff -if (Sentry.isInitialized()) { - Sentry.captureMessage(msg); -} +logger.warn(msg); ``` Enhancement |
| Verify the number of times a mocked function is called for reliability.___ **To ensure the test's reliability, consider verifying thatSentry.captureMessage was called the expected number of times using expect(Sentry.captureMessage).toHaveBeenCalledTimes(1) or a similar assertion.** [src/api.test.ts [507-509]](https://github.com/FlourishHealth/ferns-api/pull/370/files#diff-7859a5148ded19af212367ec9a3558864109c5515dea657bc8f11ee238765dc7R507-R509) ```diff +expect(Sentry.captureMessage).toHaveBeenCalledTimes(1); expect(Sentry.captureMessage).toHaveBeenCalledWith( 'More than 3 results returned for foods without pagination, data may be silently truncated. req.query: {"limit":"4"}' ); ```
| Validate query parameters early for informative client responses.___ **Consider validating the presence and correctness ofreq.query.page and other query parameters at the beginning of the request handling. This can help in returning a more informative response to the client in case of invalid input, rather than logging a warning.** [src/api.ts [568-577]](https://github.com/FlourishHealth/ferns-api/pull/370/files#diff-769911c416ccf8514d8fd941ae0abe8fb5c606ade0c218e22151a5f5f9f3d700R568-R577) ```diff -if (!req.query.page) { - const msg = - `More than ${limit} results returned for ${model.collection.name} ` + - `without pagination, data may be silently truncated. req.query: ` + - `${JSON.stringify(req.query)}`; - logger.warn(msg); - if (Sentry.isInitialized()) { - Sentry.captureMessage(msg); - } +if (!req.query.page || isNaN(parseInt(req.query.page, 10))) { + return res.status(400).json({error: "Invalid or missing 'page' query parameter."}); } ``` Maintainability |
| Extract pagination warning message generation to a separate function.___ **To improve code readability and maintainability, consider extracting the logic forgenerating the warning message about pagination into a separate function. This can also make it easier to reuse the logic in different parts of your application if needed.** [src/api.ts [569-576]](https://github.com/FlourishHealth/ferns-api/pull/370/files#diff-769911c416ccf8514d8fd941ae0abe8fb5c606ade0c218e22151a5f5f9f3d700R569-R576) ```diff -const msg = - `More than ${limit} results returned for ${model.collection.name} ` + - `without pagination, data may be silently truncated. req.query: ` + - `${JSON.stringify(req.query)}`; +const msg = generatePaginationWarningMessage(model.collection.name, limit, req.query); logger.warn(msg); if (Sentry.isInitialized()) { Sentry.captureMessage(msg); } ``` |
User description
Otherwise we are silently discarding data.
Type
enhancement
Description
Changes walkthrough
api.test.ts
Enhance API Tests with Sentry Integration
src/api.test.ts
Sentry
from@sentry/node
.Sentry
methods (captureMessage
,captureException
,isInitialized
) for testing.Sentry.captureMessage
is called when queryingover the limit without pagination.
api.ts
Log and Capture Sentry Message for Over-limit Queries without
Pagination
src/api.ts
Sentry
andlogger
for logging and capturing messages.returns more results than the limit without pagination.