Skip to content
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(instrumentation-mongoose): Fix instrumentation for Mongoose Model methods, save() and remove(), by passing options argument to original method calls #2009

Conversation

ferrelucas
Copy link
Contributor

Which problem is this PR solving?

Fixes #1678

This PR fixes the issue where transactions cannot be used for the Model methods save() and remove() (and their aliases eg. create()) because after instrumentation is applied to these methods, specifically when both options and callback are defined, the final method call loses the first argument option making the final call not take the option.session into consideration when making database operations.
This could lead to save updates in transactions not being properly rolled back as well as multiple operations that are supposed to share the same session not being able to do so because their calls would eventually be made without the session reference.

Short description of the changes

  • Pass the original args into handleCallbackResponse()
  • Updates the implementation of handleCallbackResponse() so that we create newArgs including the original options and the instrumentedcallback function.
  • Added tests to cover the base case of empty-object but defined options argument with callback
  • Added tests cases to cover committed and aborted transactions

@ferrelucas ferrelucas requested a review from a team as a code owner March 14, 2024 02:31
Copy link

linux-foundation-easycla bot commented Mar 14, 2024

CLA Signed

The committers listed above are authorized under a signed CLA.

JSON.stringify(payload),
dbStatementSerializer: (_operation: string, payload) => {
return JSON.stringify(payload, (key, value) => {
return key === 'session' ? '[Session]' : value;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ Note this replacer function was only introduced here to avoid an error due to the Session object having cyclical reference

@ferrelucas
Copy link
Contributor Author

Hi @blumamir, wondering if you could have a look at this PR when you have some time?

@ferrelucas
Copy link
Contributor Author

@open-telemetry/javascript-approvers Hi there, wondering if somebody could have a look at this PR?

@ferrelucas
Copy link
Contributor Author

Hello, @blumamir and @open-telemetry/javascript-approvers just reaching out to check if anyone could have a look at this PR?

Copy link
Member

@blumamir blumamir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the time it took to review and thank you for creating a fix for this issue 🙏

Not sure I fully understood the logic in this PR regarding adding new callback to the existing array.

plugins/node/instrumentation-mongoose/src/utils.ts Outdated Show resolved Hide resolved
plugins/node/instrumentation-mongoose/src/utils.ts Outdated Show resolved Hide resolved
@ferrelucas
Copy link
Contributor Author

@blumamir , I've update the PR to simplify the usage of args

Please let me know what you think
Thanks!

Copy link
Member

@blumamir blumamir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Thanks again for the fix and sorry it took so long to review 🙏

Copy link

codecov bot commented May 22, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 90.01%. Comparing base (dfb2dff) to head (a4336d3).
Report is 139 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2009      +/-   ##
==========================================
- Coverage   90.97%   90.01%   -0.97%     
==========================================
  Files         146      140       -6     
  Lines        7492     6909     -583     
  Branches     1502     1457      -45     
==========================================
- Hits         6816     6219     -597     
- Misses        676      690      +14     

see 50 files with indirect coverage changes

@ferrelucas
Copy link
Contributor Author

No worries!
Thanks for the review! 🙌

@blumamir
Copy link
Member

@ferrelucas let me know if you need any help fixing the CI issues. once it is green we can merge and release this fix

@ferrelucas
Copy link
Contributor Author

ferrelucas commented May 23, 2024

@blumamir thanks, I have fixed the lint issues.

I just realized the Unit Test issues are giving the MongoServerError: Transaction numbers are only allowed on a replica set member or mongos error message.

I happen to not have this issue running the tests locally because I was already running a MongDB Replica Set.
It seems we would need to update the MongoDB test setup to use replica sets so it can support transactions.

I can have a better look on how to do it soon - any directions on it would be helpful
Thanks!

@ferrelucas
Copy link
Contributor Author

Hi @blumamir I've taken one of the CI unit tests as example Run test-all-versions (20).
I've seen that the MongoDB setup is in the step called Initialize containers, under Starting mongo service container.

It is running:

/usr/bin/docker create --name fa2fac6564d8478ebd791968ddae63b9_mongo_11c61e --label 62ce9a --network github_network_60aacba5f9dc4f70be079739b8ce42a8 --network-alias mongo -p 27017:27017  -e GITHUB_ACTIONS=true -e CI=true mongo

I think we could add the --replSet parameter to the command to start the MongoDB instance, then initialize the replica set.

I believe I don't have permissions to make these changes in the Github Actions
Would it be feasible to do it on your side?
Thanks!

@blumamir
Copy link
Member

@blumamir thanks, I have fixed the lint issues.

I just realized the Unit Test issues are giving the MongoServerError: Transaction numbers are only allowed on a replica set member or mongos error message.

I happen to not have this issue running the tests locally because I was already running a MongDB Replica Set. It seems we would need to update the MongoDB test setup to use replica sets so it can support transactions.

I can have a better look on how to do it soon - any directions on it would be helpful Thanks!

perhaps we can use another option property instead of session to make sure it is passed correctly to the driver?

I can see you use this code to test passing both options and callback

await user.save({ session }, async () => {

we can consider using something else instead of session which is simpler and does not require replica set https://mongoosejs.com/docs/6.x/docs/api/model.html#model_Model-save

@blumamir
Copy link
Member

I believe I don't have permissions to make these changes in the Github Actions
Would it be feasible to do it on your side?

If I am not mistake, the mongo service is started here which you can edit, but I really think it would be easier to just use some other option for the test instead of session, if one of them is simpler.

… of transactions in the instrumentation test
@ferrelucas
Copy link
Contributor Author

@blumamir thanks! I've updated the PR unit tests to use wtimeout instead of session in the options object

@blumamir blumamir merged commit 96eb7dc into open-telemetry:main May 24, 2024
19 checks passed
@dyladan dyladan mentioned this pull request May 23, 2024
@ferrelucas
Copy link
Contributor Author

Hey, @blumamir thanks again for the review! 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Transaction is not used in Mongoose create operation after OpenTelemetry auto-instrumentation is added
2 participants