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 sentry scrubber and logs #7967

Merged
merged 2 commits into from
Apr 12, 2024
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
20 changes: 20 additions & 0 deletions src/tribler/core/sentry_reporter/sentry_reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from typing import Any, Dict, Optional

import sentry_sdk
import sentry_sdk.utils
from faker import Faker
from sentry_sdk.integrations.logging import LoggingIntegration, ignore_logger
from sentry_sdk.integrations.threading import ThreadingIntegration
Expand All @@ -19,6 +20,25 @@
get_value
)


def fix_sentry_logger(sentry_logger):
# Sentry log requires reconfiguration to be useful. By default, Sentry does not show even error-level log records
# until the debug option for Sentry is enabled. That means that unsuccessful attempts to send report are ignored.
# Enabling debug for Sentry is not recommended in production, and it sends the debug messages to stderr via
# a separate handler that is not in line with how Tribler handles logs. As a solution, Sentry developers recommend
# manual logger reconfiguration: https://github.com/getsentry/sentry-python/issues/1191#issuecomment-1023721841

for f in list(sentry_logger.filters):
sentry_logger.removeFilter(f)

for h in list(sentry_logger.handlers):
sentry_logger.removeHandler(h)

sentry_logger.setLevel(logging.WARNING)


fix_sentry_logger(sentry_sdk.utils.logger)

VALUE = 'value'
TYPE = 'type'
LAST_CORE_OUTPUT = 'last_core_output'
Expand Down
9 changes: 7 additions & 2 deletions src/tribler/core/sentry_reporter/sentry_scrubber.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,17 +174,22 @@ def scrub_entity_recursively(self, entity: Union[str, Dict, List, Any], depth=10
if isinstance(entity, dict):
result = {}
for key, value in entity.items():
if key in self.dict_keys_for_scrub:
if key in self.dict_keys_for_scrub and isinstance(value, str):
value = value.strip()
fake_value = obfuscate_string(value)
placeholder = self.create_placeholder(fake_value)
self.add_sensitive_pair(value, placeholder)
result[key] = self.scrub_entity_recursively(value, depth)
result[key] = placeholder
else:
result[key] = self.scrub_entity_recursively(value, depth)
return result

return entity

def add_sensitive_pair(self, text, placeholder):
if not (text and text.strip()): # We should not replace empty substrings in the middle of other strings
return

if text in self.sensitive_occurrences:
return

Expand Down
3 changes: 0 additions & 3 deletions src/tribler/core/sentry_reporter/sentry_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,6 @@ def obfuscate_string(s: str, part_of_speech: str = 'noun') -> str:

The same random words will be generated for the same given strings.
"""
if not s:
return s

faker = Faker(locale='en_US')
faker.seed_instance(s)
return faker.word(part_of_speech=part_of_speech)
23 changes: 14 additions & 9 deletions src/tribler/core/sentry_reporter/tests/test_sentry_scrubber.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,16 @@ def test_scrub_event(scrubber):
}
assert scrubber.scrub_event(event) == {
'the very first item': '<highlight>',
'server_name': '<protection>',
'server_name': '<kid>',
CONTEXTS: {
REPORTER: {
'any': {
'USERNAME': '<father>',
'USERNAME': '<conference>',
'USERDOMAIN_ROAMINGPROFILE': '<protection>',
'PATH': '/users/<highlight>/apps',
'TMP_WIN': 'C:\\Users\\<restaurant>\\AppData\\Local\\Temp',
'USERDOMAIN': '<marriage>',
'COMPUTERNAME': '<message>',
'USERDOMAIN': '<tune>',
'COMPUTERNAME': '<lady>',
},
STACKTRACE: [
'Traceback (most recent call last):',
Expand Down Expand Up @@ -306,15 +306,20 @@ def test_scrub_dict(scrubber):
assert scrubber.scrub_entity_recursively(None) is None
assert scrubber.scrub_entity_recursively({}) == {}

given = {'PATH': '/home/username/some/', 'USERDOMAIN': 'UD', 'USERNAME': 'U', 'REPEATED': 'user username UD U'}
assert scrubber.scrub_entity_recursively({'key': [1]}) == {'key': [1]} # non-string values should not lead to error

given = {'PATH': '/home/username/some/', 'USERDOMAIN': 'UD', 'USERNAME': 'U', 'REPEATED': 'user username UD U',
'key': ''}
assert scrubber.scrub_entity_recursively(given) == {'PATH': '/home/<highlight>/some/',
'REPEATED': 'user <highlight> <school> <night>',
'USERDOMAIN': '<school>',
'USERNAME': '<night>'}
'USERNAME': '<night>',
'key': '<dress>'}

assert 'username' in scrubber.sensitive_occurrences.keys()
assert 'UD' in scrubber.sensitive_occurrences.keys()
assert 'U' in scrubber.sensitive_occurrences.keys()
assert 'username' in scrubber.sensitive_occurrences
assert 'UD' in scrubber.sensitive_occurrences
assert 'U' in scrubber.sensitive_occurrences
assert '' not in scrubber.sensitive_occurrences


def test_scrub_list(scrubber):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,7 @@ def test_extract_dict():


OBFUSCATED_STRINGS = [
(None, None),
('', ''),
('', 'dress'),
('any', 'challenge'),
('string', 'quality'),
]
Expand Down
Loading