Repository: apify/crawlee-python
File: src/crawlee/statistics/_error_tracker.py (Python)

Code before:
        error_group_message = self._get_error_message(error)
        error_group_stack_trace = self._get_traceback_text(error)

        # First two levels are grouped only in case of exact match.
        specific_groups = self._errors[error_group_stack_trace][error_group_name]

        # Lowest level group is matched by similarity.
        if error_group_message in specific_groups:
            # Exact match.
            specific_groups.update([error_group_message])
        else:
            for existing_error_group_message in specific_groups:
                # Add to first group with similar text. Modify text with wildcard characters if necessary.
                if new_error_group_message := self._create_generic_message(
                    existing_error_group_message, error_group_message
                ):
                    # Replace old name.
                    specific_groups[new_error_group_message] = specific_groups.pop(existing_error_group_message)
                    # Increment.
                    specific_groups.update([new_error_group_message])
                    break
            else:
                # No similar message found. Create new group.
                self._errors[error_group_stack_trace][error_group_name].update([error_group_message])

    def _get_traceback_text(self, error: Exception) -> str | None:
        if self.show_stack_trace:
            error_traceback = traceback.extract_tb(error.__traceback__)
            return f'{error_traceback[0].filename.split("/")[-1]}:{error_traceback[0].lineno}'
        return None

    def _get_error_message(self, error: Exception) -> str | None:
        if self.show_error_message:
            if self.show_full_message:
                return str(error.args[0])
            return str(error.args[0]).split('\n')[0]
        return None

    @property
    def unique_error_count(self) -> int:
        """Number of distinct kinds of errors."""
        unique_error_count = 0
        for stack_group in self._errors.values():
            for name_group in stack_group.values():
                unique_error_count += len(name_group)
        return unique_error_count

    @property
    def total(self) -> int:
        """Total number of errors."""
        error_count = 0

Review comment (suggestion):
This is just the file and line number where the exception was thrown, isn't it? The name would suggest a complete stacktrace. I'd try and come up with something more fitting.

Code after:

        # First two levels are grouped only in case of exact match.
        specific_groups = self._errors[error_group_file_and_line][error_group_name]

        # Lowest level group is matched by similarity.
        if error_group_message in specific_groups:
            # Exact match.
            specific_groups.update([error_group_message])
        else:
            for existing_error_group_message in specific_groups:
                # Add to first group with similar text. Modify text with wildcard characters if necessary.
                if new_error_group_message := self._create_generic_message(
                    existing_error_group_message, error_group_message
                ):
                    # Replace old name.
                    specific_groups[new_error_group_message] = specific_groups.pop(existing_error_group_message)
                    # Increment.
                    specific_groups.update([new_error_group_message])
                    break
            else:
                # No similar message found. Create new group.
                self._errors[error_group_file_and_line][error_group_name].update([error_group_message])

    def _get_file_and_line(self, error: Exception) -> str | None:
        if self.show_file_and_line_number:
            error_traceback = traceback.extract_tb(error.__traceback__)
            return f'{error_traceback[0].filename.split("/")[-1]}:{error_traceback[0].lineno}'
        return None

    def _get_error_message(self, error: Exception) -> str | None:
        if self.show_error_message:
            if self.show_full_message:
                return str(error.args[0])
            return str(error.args[0]).split('\n')[0]
        return None

    @property
    def unique_error_count(self) -> int:
        """Number of distinct kinds of errors."""
        unique_error_count = 0
        for file_and_line_group in self._errors.values():
            for name_group in file_and_line_group.values():
                unique_error_count += len(name_group)
        return unique_error_count

    @property
    def total(self) -> int:
        """Total number of errors."""
        error_count = 0
        for file_and_line_group in self._errors.values():
            for name_group in file_and_line_group.values():