Skip to content

Commit f50a955

Browse files
authored
State logger (#352)
* State logger Logs the state of an instance, e.g. txbuilder, when an exception is raised. Optionally, the state could be logged every time when the function is called if log level of the parent logger is set to DEBUG. State logger is added to `TransactionBuilder.build()`, `TransactionBuilder.build_and_sign()`, `ChainContext.submit_tx()`. * Remove redundant pytest log level
1 parent 01edc0d commit f50a955

File tree

7 files changed

+63
-14
lines changed

7 files changed

+63
-14
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ clean-test: ## remove test and coverage artifacts
5555
rm -fr .pytest_cache
5656

5757
test: ## runs tests
58-
poetry run pytest -s -vv -n 4
58+
poetry run pytest -vv -n 4
5959

6060
test-single: ## runs tests with "single" markers
6161
poetry run pytest -s -vv -m single

poetry.lock

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pycardano/backend/base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from pycardano.address import Address
88
from pycardano.exception import InvalidArgumentException
9+
from pycardano.logging import log_state
910
from pycardano.network import Network
1011
from pycardano.plutus import ExecutionUnits
1112
from pycardano.transaction import Transaction, UTxO
@@ -160,6 +161,7 @@ def _utxos(self, address: str) -> List[UTxO]:
160161
"""
161162
raise NotImplementedError()
162163

164+
@log_state
163165
def submit_tx(self, tx: Union[Transaction, bytes, str]):
164166
"""Submit a transaction to the blockchain.
165167

pycardano/logging.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import logging
22

3-
__all__ = ["logger"]
3+
from pprintpp import pformat
4+
5+
__all__ = ["logger", "log_state"]
46

57
# create logger
68
logger = logging.getLogger("PyCardano")
7-
logger.setLevel(logging.WARNING)
89

910
# create console handler and set level to debug
1011
ch = logging.StreamHandler()
11-
ch.setLevel(logging.WARNING)
1212

1313
# create formatter
1414
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
@@ -18,3 +18,22 @@
1818

1919
# add ch to logger
2020
logger.addHandler(ch)
21+
22+
23+
def log_state(func):
24+
"""Decorator to log the state of an object after its function call."""
25+
26+
def wrapper(obj, *args, **kwargs):
27+
try:
28+
output = func(obj, *args, **kwargs)
29+
logger.debug(
30+
f"Class: {obj.__class__}, method: {func}, state:\n {pformat(vars(obj), indent=2)}"
31+
)
32+
return output
33+
except Exception as e:
34+
logger.warning(
35+
f"Class: {obj.__class__}, method: {func}, state:\n {pformat(vars(obj), indent=2)}"
36+
)
37+
raise e
38+
39+
return wrapper

pycardano/txbuilder.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
)
3030
from pycardano.hash import DatumHash, ScriptDataHash, ScriptHash, VerificationKeyHash
3131
from pycardano.key import ExtendedSigningKey, SigningKey, VerificationKey
32-
from pycardano.logging import logger
32+
from pycardano.logging import log_state, logger
3333
from pycardano.metadata import AuxiliaryData
3434
from pycardano.nativescript import NativeScript, ScriptAll, ScriptAny, ScriptPubkey
3535
from pycardano.plutus import (
@@ -988,6 +988,7 @@ def _estimate_fee(self):
988988

989989
return estimated_fee
990990

991+
@log_state
991992
def build(
992993
self,
993994
change_address: Optional[Address] = None,
@@ -1357,6 +1358,7 @@ def _estimate_execution_units(
13571358

13581359
return self.context.evaluate_tx(tx)
13591360

1361+
@log_state
13601362
def build_and_sign(
13611363
self,
13621364
signing_keys: List[Union[SigningKey, ExtendedSigningKey]],

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ docker = "^6.1.3"
3939
[tool.poetry.dev-dependencies]
4040
Sphinx = "^4.3.2"
4141
sphinx-rtd-theme = "^1.1.1"
42-
pytest = "^7.4.4"
42+
pytest = "^8.2.0"
4343
pytest-cov = "^4.0.0"
4444
flake8 = "^5.0.4"
4545
isort = "^5.11.4"
@@ -67,6 +67,7 @@ markers = [
6767
"single"
6868
]
6969

70+
7071
[tool.isort]
7172
profile = "black"
7273

test/pycardano/test_txbuilder.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import copy
2+
import logging
23
from dataclasses import replace
34
from fractions import Fraction
45
from test.pycardano.test_key import SK
@@ -220,6 +221,30 @@ def test_tx_builder_raises_utxo_selection(chain_context):
220221
assert "{AssetName(b'NewToken'): 1}" in e.value.args[0]
221222

222223

224+
def test_tx_builder_state_logger_warning_level(chain_context, caplog):
225+
with caplog.at_level(logging.WARNING):
226+
test_tx_builder_raises_utxo_selection(chain_context)
227+
assert "WARNING" in caplog.text
228+
229+
230+
def test_tx_builder_state_logger_error_level(chain_context, caplog):
231+
with caplog.at_level(logging.ERROR):
232+
test_tx_builder_raises_utxo_selection(chain_context)
233+
assert "WARNING" not in caplog.text
234+
235+
236+
def test_tx_builder_state_logger_info_level(chain_context, caplog):
237+
with caplog.at_level(logging.INFO):
238+
test_tx_builder_multi_asset(chain_context)
239+
assert "DEBUG" not in caplog.text
240+
241+
242+
def test_tx_builder_state_logger_debug_level(chain_context, caplog):
243+
with caplog.at_level(logging.DEBUG):
244+
test_tx_builder_multi_asset(chain_context)
245+
assert "DEBUG" in caplog.text
246+
247+
223248
def test_tx_too_big_exception(chain_context):
224249
tx_builder = TransactionBuilder(chain_context)
225250
sender = "addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x"

0 commit comments

Comments
 (0)