Skip to content
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: 3 additions & 3 deletions notifications/file_event_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ def perform(self):
'user_fullname': self.user.fullname,
'message': self.html_message,
'profile_image_url': self.profile_image_url,
'localized_timestamp': self.timestamp,
'localized_timestamp': str(self.timestamp),
'url': self.url,
},
is_digest=True,
Expand Down Expand Up @@ -312,7 +312,7 @@ def perform(self):
'user_fullname': self.user.fullname,
'message': self.html_message,
'profile_image_url': self.profile_image_url,
'localized_timestamp': self.timestamp,
'localized_timestamp': str(self.timestamp),
'url': self.url,
},
is_digest=True,
Expand All @@ -332,7 +332,7 @@ def perform(self):
'user_fullname': self.user.fullname,
'message': self.html_message,
'profile_image_url': self.profile_image_url,
'localized_timestamp': self.timestamp,
'localized_timestamp': str(self.timestamp),
'url': self.url,
},
is_digest=True,
Expand Down
12 changes: 10 additions & 2 deletions osf_tests/test_archiver.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,15 @@ def test_stat_addon(self):
assert res.target_name == 'osfstorage'
assert res.disk_usage == 128 + 256

def test_compact_traceback_uses_last_lines(self):
traceback_text = '\n'.join(f'line {line_num}' for line_num in range(50))
compact = archiver_utils.compact_traceback(traceback_text, max_lines=5, max_chars=1000)

assert compact == '\n'.join(f'line {line_num}' for line_num in range(45, 50))

def test_compact_traceback_handles_empty(self):
assert archiver_utils.compact_traceback(None) is None

@mock.patch('website.archiver.tasks.archive_addon.delay')
def test_archive_node_pass(self, mock_archive_addon):
settings.MAX_ARCHIVE_SIZE = 1024 ** 3
Expand Down Expand Up @@ -959,8 +968,7 @@ def test_archive_callback_done_errors(self):
assert call_args[1] == self.src
assert call_args[2] == self.dst
assert call_args[3] == self.user
assert call_args[3] == self.user
assert list(call_args[4]) == list(self.dst.archive_job.target_addons.all())
assert call_args[4] == self.dst.archive_job.target_info()

def test_archive_callback_updates_archiving_state_when_done(self):
proj = factories.NodeFactory()
Expand Down
1 change: 1 addition & 0 deletions tests/test_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ def test_user_performing_action_no_email(self):
self.event.perform()
assert len(notifications['emits']) == 1
assert notifications['emits'][0]['type'] == NotificationTypeEnum.ADDON_FILE_COPIED
assert isinstance(notifications['emits'][0]['kwargs']['event_context']['localized_timestamp'], str)


class TestSubscriptionManipulations(OsfTestCase):
Expand Down
2 changes: 1 addition & 1 deletion website/archiver/listeners.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def archive_callback(dst):
root.registered_from,
root,
root.registered_user,
dst.archive_job.target_addons.all(),
dst.archive_job.target_info(),
)


Expand Down
16 changes: 13 additions & 3 deletions website/archiver/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def create_app_context():

logger = get_task_logger(__name__)


class ArchiverSizeExceeded(Exception):

def __init__(self, result):
Expand Down Expand Up @@ -88,12 +89,13 @@ class ArchiverTask(celery.Task):

def on_failure(self, exc, task_id, args, kwargs, einfo):
job = ArchiveJob.load(kwargs.get('job_pk'))
compact_traceback = utils.compact_traceback(einfo)
if not job:
archiver_state_exc = ArchiverStateError({
'exception': exc,
'args': args,
'kwargs': kwargs,
'einfo': einfo,
'einfo': compact_traceback,
})
sentry.log_exception(archiver_state_exc)
raise archiver_state_exc
Expand All @@ -102,7 +104,7 @@ def on_failure(self, exc, task_id, args, kwargs, einfo):
# already captured
return

src, dst, user = job.info()
src, dst, _ = job.info()
errors = []
if isinstance(exc, ArchiverSizeExceeded):
dst.archive_status = ARCHIVER_SIZE_EXCEEDED
Expand All @@ -122,15 +124,23 @@ def on_failure(self, exc, task_id, args, kwargs, einfo):
}
else:
dst.archive_status = ARCHIVER_UNCAUGHT_ERROR
errors = [str(einfo)] if einfo else []
errors = [f'{exc.__class__.__name__}: {exc}']
if compact_traceback:
errors.append(f'Traceback tail:\n{compact_traceback}')
dst.save()

# Always capture full exception; keep log_message payload compact.
sentry.log_exception(exc)
sentry.log_message(
f'An error occurred while archiving node: {src._id} and registration: {dst._id}',
extra_data={
'source node guid': src._id,
'registration node guid': dst._id,
'task_id': task_id,
'task_name': self.name,
'exception_type': exc.__class__.__name__,
'exception_message': str(exc),
'traceback_tail': compact_traceback,
'errors': errors,
},
)
Expand Down
15 changes: 15 additions & 0 deletions website/archiver/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,3 +384,18 @@ def _validate_updated_responses(registration, file_input_qids, updated_responses
registration=registration,
missing_files=missing_responses
)


def compact_traceback(einfo, max_lines=25, max_chars=4000):
"""Return a short traceback tail for logs/notifications."""
if not einfo:
return None
traceback_text = str(einfo)
if not traceback_text:
return None

lines = traceback_text.splitlines()
compact = '\n'.join(lines[-max_lines:])
if len(compact) > max_chars:
compact = compact[-max_chars:]
return compact
Loading