|
18 | 18 | temporary objects to the database, and moving them to their final locations,
|
19 | 19 | live here.
|
20 | 20 | """
|
21 |
| -from __future__ import absolute_import |
22 |
| -from __future__ import print_function |
23 | 21 |
|
24 | 22 | import time
|
25 |
| -from logging import DEBUG |
| 23 | +import logging |
26 | 24 |
|
27 | 25 | from zope.interface import implementer
|
28 | 26 |
|
|
37 | 35 | from relstorage._util import do_log_duration_info
|
38 | 36 | from relstorage._util import TRACE
|
39 | 37 | from relstorage._util import METRIC_SAMPLE_RATE
|
| 38 | +from relstorage._util import get_positive_integer_from_environ |
40 | 39 | from relstorage.options import COMMIT_EXIT_CRITICAL_SECTION_EARLY
|
41 | 40 | from relstorage.adapters.interfaces import UnableToAcquireLockError
|
42 | 41 | from ..interfaces import VoteReadConflictError
|
|
46 | 45 | from . import AbstractTPCStateDatabaseAvailable
|
47 | 46 | from .finish import Finish
|
48 | 47 |
|
49 |
| -LOG_LEVEL_TID = DEBUG |
| 48 | +LOG_LEVEL_TID = logging.DEBUG |
50 | 49 |
|
51 |
| -logger = __import__('logging').getLogger(__name__) |
| 50 | +logger = logging.getLogger(__name__) |
52 | 51 | perf_logger = logger.getChild('timing')
|
53 | 52 |
|
54 | 53 | class DatabaseLockedForTid(object):
|
@@ -663,14 +662,36 @@ def loadSerial(self, oid, serial):
|
663 | 662 | assert bytes8_to_int64(serial) == tid
|
664 | 663 | return state
|
665 | 664 |
|
| 665 | +#: The maximum number of characters to allow in each portion |
| 666 | +#: of lock detail errors. |
| 667 | +DETAIL_TRUNCATION_LEN = get_positive_integer_from_environ( |
| 668 | + 'RS_LOCK_ERROR_MAX_LEN', |
| 669 | + # 2k seems a reasonable default. If you are actually getting |
| 670 | + # truncated, then chances are the transaction is much larger |
| 671 | + # than that |
| 672 | + 2048, |
| 673 | + logger=logger |
| 674 | +) |
| 675 | + |
666 | 676 | def add_details_to_lock_error(ex, shared_state, required_tids):
|
667 | 677 | # type: (Exception, SharedState, required_tids)
|
| 678 | + |
| 679 | + obj_msg = str(shared_state.temp_storage) if shared_state.has_temp_data() else 'None' |
| 680 | + tid_msg = str(dict(required_tids)) # May be a BTree, which has no useful str/repr |
| 681 | + |
| 682 | + obj_msg = (obj_msg[:DETAIL_TRUNCATION_LEN] + '...' |
| 683 | + if len(obj_msg) > DETAIL_TRUNCATION_LEN |
| 684 | + else obj_msg) |
| 685 | + tid_msg = (tid_msg[:DETAIL_TRUNCATION_LEN] + '...' |
| 686 | + if len(tid_msg) > DETAIL_TRUNCATION_LEN |
| 687 | + else tid_msg) |
| 688 | + |
668 | 689 | message = '\n'.join((
|
669 |
| - 'Stored Objects', |
670 |
| - str(shared_state.temp_storage) if shared_state.has_temp_data() else 'None', |
671 |
| - 'readCurrent {oid: tid}', |
672 |
| - str(dict(required_tids)) # May be a BTree, which has no |
673 |
| - )) |
| 690 | + 'Stored Objects', |
| 691 | + obj_msg, |
| 692 | + 'readCurrent {oid: tid}', |
| 693 | + tid_msg, |
| 694 | + )) |
674 | 695 |
|
675 | 696 | if hasattr(ex, 'message'):
|
676 | 697 | # A ConflictError subclass *or* we're on Python 2.
|
|
0 commit comments