Skip to content

Commit

Permalink
fix: remove API secrets from web3.py loggers [APE-1486] (#1715)
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Oct 31, 2023
1 parent be57c14 commit 09d9098
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 16 deletions.
17 changes: 14 additions & 3 deletions src/ape/api/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
TransactionNotFoundError,
VirtualMachineError,
)
from ape.logging import LogLevel, logger
from ape.logging import LogLevel, logger, sanitize_url
from ape.types import (
AddressType,
AutoGasLimit,
Expand Down Expand Up @@ -745,6 +745,17 @@ def _increment_call_func_coverage_hit_count(self, txn: TransactionAPI):
self._test_runner.coverage_tracker.hit_function(contract_src, method)


def _sanitize_web3_url(msg: str) -> str:
if "URI: " not in msg:
return msg

parts = msg.split("URI: ")
prefix = parts[0].strip()
rest = parts[1].split(" ")
sanitized_url = sanitize_url(rest[0])
return f"{prefix} URI: {sanitized_url} {' '.join(rest[1:])}"


class Web3Provider(ProviderAPI, ABC):
"""
A base provider mixin class that uses the
Expand All @@ -755,8 +766,8 @@ class Web3Provider(ProviderAPI, ABC):
_client_version: Optional[str] = None

def __init__(self, *args, **kwargs):
logger.create_logger("web3.RequestManager")
logger.create_logger("web3.providers.HTTPProvider")
logger.create_logger("web3.RequestManager", handlers=(_sanitize_web3_url,))
logger.create_logger("web3.providers.HTTPProvider", handlers=(_sanitize_web3_url,))
super().__init__(*args, **kwargs)

@property
Expand Down
38 changes: 30 additions & 8 deletions src/ape/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
import traceback
from enum import IntEnum
from pathlib import Path
from typing import IO, Any, Dict, Optional, Union
from typing import IO, Any, Callable, Dict, Optional, Sequence, Union

import click
from yarl import URL


class LogLevel(IntEnum):
Expand Down Expand Up @@ -86,13 +87,19 @@ def format(self, record):


class ClickHandler(logging.Handler):
def __init__(self, echo_kwargs):
def __init__(
self, echo_kwargs: Dict, handlers: Optional[Sequence[Callable[[str], str]]] = None
):
super().__init__()
self.echo_kwargs = echo_kwargs
self.handlers = handlers or []

def emit(self, record):
try:
msg = self.format(record)
for handler in self.handlers:
msg = handler(msg)

level = record.levelname.lower()
if self.echo_kwargs.get(level):
click.echo(msg, **self.echo_kwargs[level])
Expand Down Expand Up @@ -212,15 +219,19 @@ def log_debug_stack_trace(self):
stack_trace = traceback.format_exc()
self._logger.debug(stack_trace)

def create_logger(self, new_name: str) -> logging.Logger:
_logger = get_logger(new_name, self.fmt)
def create_logger(
self, new_name: str, handlers: Optional[Sequence[Callable[[str], str]]] = None
) -> logging.Logger:
_logger = get_logger(new_name, fmt=self.fmt, handlers=handlers)
_logger.setLevel(self.level)
self._extra_loggers[new_name] = _logger
return _logger


def _format_logger(_logger: logging.Logger, fmt: str):
handler = ClickHandler(echo_kwargs=CLICK_ECHO_KWARGS)
def _format_logger(
_logger: logging.Logger, fmt: str, handlers: Optional[Sequence[Callable[[str], str]]] = None
):
handler = ClickHandler(echo_kwargs=CLICK_ECHO_KWARGS, handlers=handlers)
formatter = ApeColorFormatter(fmt=fmt)
handler.setFormatter(formatter)

Expand All @@ -232,20 +243,23 @@ def _format_logger(_logger: logging.Logger, fmt: str):
_logger.addHandler(handler)


def get_logger(name: str, fmt: Optional[str] = None) -> logging.Logger:
def get_logger(
name: str, fmt: Optional[str] = None, handlers: Optional[Sequence[Callable[[str], str]]] = None
) -> logging.Logger:
"""
Get a logger with the given ``name`` and configure it for usage with Ape.
Args:
name (str): The name of the logger.
fmt (Optional[str]): The format of the logger. Defaults to the Ape
logger's default format: ``"%(levelname)s%(plugin)s: %(message)s"``.
handlers (Optional[Sequence[Callable[[str], str]]]): Additional log message handlers.
Returns:
``logging.Logger``
"""
_logger = logging.getLogger(name)
_format_logger(_logger, fmt=fmt or DEFAULT_LOG_FORMAT)
_format_logger(_logger, fmt=fmt or DEFAULT_LOG_FORMAT, handlers=handlers)
return _logger


Expand All @@ -258,6 +272,14 @@ def _get_level(level: Optional[Union[str, int]] = None) -> str:
return level


def sanitize_url(url: str) -> str:
url_obj = URL(url).with_user(None).with_password(None)

# If there is a path, hide it but show that you are hiding it.
# Use string interpolation to prevent URL-character encoding.
return f"{url_obj.with_path('')}/[hidden]" if url_obj.path else f"{url}"


logger = ApeLogger.create()

# TODO: Can remove this type alias after 0.7
Expand Down
7 changes: 2 additions & 5 deletions src/ape_geth/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
ContractNotFoundError,
ProviderError,
)
from ape.logging import LogLevel, logger
from ape.logging import LogLevel, logger, sanitize_url
from ape.types import AddressType, CallTreeNode, SnapshotID, SourceTraceback, TraceFrame
from ape.utils import (
DEFAULT_NUMBER_OF_TEST_ACCOUNTS,
Expand Down Expand Up @@ -277,10 +277,7 @@ def uri(self) -> str:

@property
def _clean_uri(self) -> str:
url = URL(self.uri).with_user(None).with_password(None)
# If there is a path, hide it but show that you are hiding it.
# Use string interpolation to prevent URL-character encoding.
return f"{url.with_path('')}/[hidden]" if url.path else f"{url}"
return sanitize_url(self.uri)

@property
def ipc_path(self) -> Path:
Expand Down

0 comments on commit 09d9098

Please sign in to comment.