Skip to content

fix(provider)!: RaygunMessage object in on_grouping_key method #118

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

Merged
merged 13 commits into from
May 21, 2025

Conversation

miquelbeltran
Copy link
Contributor

@miquelbeltran miquelbeltran commented May 16, 2025

Description 📝

Purpose:

In the ticket #96 the customer reported that the object provided to the on_grouping_key callback was not a RaygunMessage object but rather a Dictionary.

This was caused by a bug in the filter_keys method as the customer pointed out.

Approach:

After some iterations, the filter_keys function has been changed so it does not accept RaygunMessage objects, and instead it can only be used with dictionaries (e.g. the RaygunMessage.details). This simplifies the implementation and avoids bugs like the one reported in #96 where the RaygunMessage was overridden.

This ensures that filter_keys doesn't break the class definition of RaygunMessage.

Then, the rest of the _post() method had to be fixed to access the details of the RaygunMessage object correctly.

For that I created methods to set_details and set_error.

As well, I created unit tests that check that what the documentation says is correct.

Finally, I also fixed the documentation formatting a bit.

This is potentially a breaking change if customers were accessing the object as a dictionary, as they will have to change the code, so a major version should be released.

While implementing this fix, I also made sure that functions are pure and that they don't modify the provided RaygunMessage, but rather modify a copy and then return it.

Type of change

  • fix: Bug fix (non-breaking change which fixes an issue)
  • feat: New feature (non-breaking change which adds functionality)
  • chore: Chore task, release or small impact change
  • ci: CI configuration change
  • Other type of change (specify)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Related issues

Test plan 🧪

  • Tested through existing and new unit tests

Author to check 👓

  • Project and all contained modules builds successfully
  • Self-/dev-tested
  • Unit/UI/Automation/Integration tests provided where applicable
  • Code is written to standards
  • Appropriate documentation written (code comments, internal docs)

Reviewer to check ✔️

  • Project and all contained modules builds successfully
  • Change has been dev-/reviewer-tested, where possible
  • Unit/UI/Automation/Integration tests provided where applicable
  • Code is written to standards
  • Appropriate documentation written (code comments, internal docs)

@@ -129,15 +129,30 @@ def set_user(self, user):
class RaygunMessage(object):

def __init__(self):
self.occurredOn = datetime.utcnow()
self.occurredOn = datetime.now(UTC)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixes deprecated utcnow warning

Comment on lines +135 to +143
def __copy__(self):
new_instance = RaygunMessage()
new_instance.details = self.details.copy()
new_instance.occurredOn = self.occurredOn
return new_instance

def copy(self):
return self.__copy__()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Necessary to avoid modifying the original object in pure functions

@@ -295,42 +295,42 @@ def _create_message(
)

def _transform_message(self, message):
message = message.copy()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

_transform_message should be pure and not modify the original message object

message = utilities.ignore_exceptions(self.ignored_exceptions, message)

if message is not None:
message = utilities.filter_keys(self.filtered_keys, message)
message["details"]["groupingKey"] = utilities.execute_grouping_key(
message.get_details()["groupingKey"] = utilities.execute_grouping_key(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

message should be a RaygunMessage object and not a dict, access properties using accessors.

else:
return None

return message

def _post(self, raygunMessage):
raygunMessage = raygunMessage.copy()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

_post should be a pure function and not modify the original raygunMessage

Comment on lines 33 to 37
if isinstance(object, raygunmsgs.RaygunMessage):
updated_object = object.copy()
updated_object.__dict__.update(iteration_target)
return updated_object

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If the original object was a RaygunMessage, then we need to create a copy of the object and apply the changes to the internal __dict__

@miquelbeltran miquelbeltran requested a review from Copilot May 19, 2025 07:30
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes a bug where the on_grouping_key callback received a raw dictionary instead of a RaygunMessage, and adjusts related methods to treat messages as immutable copies. It also updates tests, adds new setters/getters in RaygunMessage, and refines documentation.

  • Refactored filter_keys to detect and return a modified RaygunMessage instead of plain dict
  • Changed RaygunSender to use copy(), get_details(), set_details(), and set_error()
  • Added new getters/setters (get_error, get_details, set_details, set_error) and corresponding unit tests

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
python3/tests/test_utilities.py Updated tests to capture and assert the return value of filter_keys.
python3/tests/test_raygunprovider.py Assigned the result of _transform_message to msg in existing tests and added an error‐callback test.
python3/tests/test_raygunmsgs.py Added tests for get_error() and get_details().
python3/raygun4py/utilities.py Refactored filter_keys to copy the underlying dict and return a RaygunMessage if applicable.
python3/raygun4py/raygunprovider.py Updated _transform_message and _post to use RaygunMessage API methods and make copies.
python3/raygun4py/raygunmsgs.py Made timestamps timezone‐aware and added copy(), getters, and setters for message details and error.
README.rst Improved formatting around RaygunMessage usage in custom grouping docs.
Comments suppressed due to low confidence (3)

python3/raygun4py/utilities.py:14

  • The parameter name object shadows a Python built-in and is ambiguous. Consider renaming it to obj or target for clarity.
def filter_keys(filtered_keys, object):

python3/tests/test_raygunmsgs.py:162

  • We should add unit tests for the new set_error() and set_details() methods to ensure they correctly update the RaygunMessage state.
def test_get_error(self):

python3/tests/test_utilities.py:7

  • Add a test case where filter_keys is called on a RaygunMessage instance to verify it returns a RaygunMessage (not a dict) with filtered fields.
def test_filter_keys(self):

@miquelbeltran miquelbeltran requested a review from Copilot May 19, 2025 07:57
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR ensures that the on_grouping_key callback always receives a RaygunMessage object (not a raw dict), fixes the key‐filtering bug, updates internal message handling methods, and adds corresponding tests and documentation tweaks.

  • filter_keys now detects RaygunMessage, returns a modified copy, and preserves message methods.
  • Added set_details/set_error and updated _transform_message/_post to use get_details/get_error/set_* APIs.
  • Expanded unit tests for these changes and improved README code formatting.

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
python3/tests/test_utilities.py Updated tests to assign the return of filter_keys and added RaygunMessage case
python3/tests/test_raygunprovider.py Changed grouping key tests to capture and inspect the returned message object
python3/tests/test_raygunmsgs.py Added tests for get_error, get_details, set_error, and set_details
python3/raygun4py/utilities.py filter_keys now supports RaygunMessage inputs and returns a message copy
python3/raygun4py/raygunprovider.py _transform_message/_post updated to use new accessors and copy semantics
python3/raygun4py/raygunmsgs.py Added __copy__, copy, and set_* methods to RaygunMessage
README.rst Improved code references formatting
Comments suppressed due to low confidence (2)

python3/raygun4py/utilities.py:14

  • [nitpick] Consider renaming the parameter 'filtered_keys' to 'keys_to_filter' for clearer intent, since 'filtered_keys' can be misread as keys already filtered.
def filter_keys(filtered_keys, obj):

python3/tests/test_utilities.py:32

  • Add tests for nested dictionaries inside RaygunMessage.details to ensure filter_keys recurses and filters nested keys correctly.
def test_filter_keys_raygun_message(self):

Comment on lines +302 to +303
details = message.get_details()
details = utilities.filter_keys(self.filtered_keys, details)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Pass the details to the filter_keys function instead of passing the whole message object

Returns:
dict: The filtered dictionary.
"""
iteration_target = dict(obj)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

make a copy to avoid modifying the original object

Comment on lines -17 to -18
if isinstance(object, raygunmsgs.RaygunMessage):
iteration_target = object.__dict__
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The filter_keys function shouldn't be used with RaygunMessage directly, instead it should be applied to the details

Copy link

@Olwiba Olwiba left a comment

Choose a reason for hiding this comment

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

Changes look good 😃 thanks for adding the additional notes throughout the changes!

@miquelbeltran miquelbeltran merged commit 4c0ab4f into master May 21, 2025
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Documentation for Custom grouping logic has incorrect definition of the callback parameter
2 participants