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

Skip seated user check for chat segment events #1500

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion ansible_ai_connect/ai/api/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1968,6 +1968,8 @@ def test_feedback_chatbot(self):
"sentiment": "1",
}
}
self.user.rh_user_has_seat = True
self.user.organization = Organization.objects.get_or_create(id=1)[0]
self.client.force_authenticate(user=self.user)
with self.assertLogs(logger="root", level="DEBUG") as log:
r = self.client.post(reverse("feedback"), payload, format="json")
Expand All @@ -1977,7 +1979,7 @@ def test_feedback_chatbot(self):
self.assertTrue(len(segment_events) > 0)
self.assertEqual(
segment_events[0]["properties"]["rh_user_org_id"],
123,
self.user.organization.id,
)
self.assertEqual(
segment_events[0]["properties"]["chat_prompt"],
Expand Down Expand Up @@ -4166,6 +4168,8 @@ def test_chat_with_system_prompt_override(self):

@override_settings(SEGMENT_WRITE_KEY="DUMMY_KEY_VALUE")
def test_operational_telemetry(self):
self.user.rh_user_has_seat = True
self.user.organization = Organization.objects.get_or_create(id=1)[0]
self.client.force_authenticate(user=self.user)
with (
patch.object(
Expand Down
6 changes: 6 additions & 0 deletions ansible_ai_connect/ai/api/utils/seated_users_allow_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,4 +384,10 @@
"rh_user_org_id": None,
"plans": None,
},
"chatFeedbackEvent": {
"*": None,
},
"chatOperationalEvent": {
"*": None,
},
}
4 changes: 4 additions & 0 deletions ansible_ai_connect/ai/api/utils/segment.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,10 @@ def redact_seated_users_data(event: Dict[str, Any], allow_list: Dict[str, Any])
Returns:
- dict: A new dictionary containing only the allowed nested keys from the source dictionary.
"""
# If an asterisk is found in the allow list, just return the given event dict to allow all keys.
if "*" in allow_list:
Copy link
Contributor

Choose a reason for hiding this comment

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

It'd be nice to have a test for these with your new check?

I know SonarCloud says you have 100%... but is that a false positive? I don't see any.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have added two lines to test_operational_telemetry()`

        self.user.rh_user_has_seat = True
        self.user.organization = Organization.objects.get_or_create(id=1)[0]

which forces to run the test case with a "seated" user. Without this allow_list change, the test case failed. Isn't this change enough for the test coverage?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Isn't this change enough for the test coverage?

I found there were some test cases on redact operations in test_segment.py. I'll add two test cases to it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, that's fine @TamiTakamiya

It wasn't clear from your PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hey @TamiTakamiya, @manstis, sorry for late response, just my 2c the idea behind allow list agains block list in this case is making sure you are logging only something you really need to log, and avoid situation we are storing things we are not supposed to store.

Whit the asterisk it is easier to make a mistake and store unintended data.

Copy link
Contributor

Choose a reason for hiding this comment

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

@hasys You're never late to the party and, as author of the original white listing, your opinion is important.. When you wrote the enhancement you no doubt had a clear vision in mind and it should not be bastardized to fit other use-cases (as this is how we end up with spaghetti code!)

What would you have proposed?

IIUC the issue was that the Chat Bot events were not recognised as "valid" events and hence filtered out.

@TamiTakamiya's change means they are no longer blocked by the filter and obviates the need to list all fields.

return event

redacted_event = {}
for key, sub_whitelist in (
allow_list.items() if isinstance(allow_list, dict) else allow_list[0].items()
Expand Down
42 changes: 42 additions & 0 deletions ansible_ai_connect/ai/api/utils/tests/test_segment.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,48 @@ def test_redact_trialExpired_response_data(self, *args):
redact_seated_users_data(test_data, ALLOW_LIST["trialExpired"]), expected_result
)

def test_redact_chat_operational_event(self, *args):
test_data = {
"type": "chatOperationalEvent",
"modelName": "org-model-id",
"rh_user_has_seat": True,
"rh_user_org_id": 101,
"anything": "whatever",
}

expected_result = {
"type": "chatOperationalEvent",
"modelName": "org-model-id",
"rh_user_has_seat": True,
"rh_user_org_id": 101,
"anything": "whatever", # Any properties won't be redacted for chatOperationalEvent
}

self.assertEqual(
redact_seated_users_data(test_data, ALLOW_LIST["chatOperationalEvent"]), expected_result
)

def test_redact_chat_feedback_event(self, *args):
test_data = {
"type": "chatFeedbackEvent",
"modelName": "org-model-id",
"rh_user_has_seat": True,
"rh_user_org_id": 101,
"anything": "whatever",
}

expected_result = {
"type": "chatFeedbackEvent",
"modelName": "org-model-id",
"rh_user_has_seat": True,
"rh_user_org_id": 101,
"anything": "whatever", # Any properties won't be redacted for chatFeedbackEvent
}

self.assertEqual(
redact_seated_users_data(test_data, ALLOW_LIST["chatFeedbackEvent"]), expected_result
)

@mock.patch("ansible_ai_connect.ai.api.utils.segment.analytics.group")
@override_settings(SEGMENT_WRITE_KEY="DUMMY_KEY_VALUE")
def test_send_segment_group(self, group_method):
Expand Down
Loading