Skip to content

Commit 3765541

Browse files
committed
refactor: add logging for browser lifecycle and context management events
1 parent ae38618 commit 3765541

File tree

10 files changed

+375
-21
lines changed

10 files changed

+375
-21
lines changed

pydoll/browser/chromium/base.py

Lines changed: 107 additions & 1 deletion
Large diffs are not rendered by default.

pydoll/browser/chromium/chrome.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
import platform
23
from typing import Optional
34

@@ -7,6 +8,8 @@
78
from pydoll.exceptions import UnsupportedOS
89
from pydoll.utils import validate_browser_paths
910

11+
logger = logging.getLogger(__name__)
12+
1013

1114
class Chrome(Browser):
1215
"""Chrome browser implementation for CDP automation."""
@@ -39,6 +42,7 @@ def _get_default_binary_location():
3942
ValueError: If executable not found at default location.
4043
"""
4144
os_name = platform.system()
45+
logger.debug(f"Resolving default Chrome binary for OS: {os_name}")
4246

4347
browser_paths = {
4448
'Windows': [
@@ -57,6 +61,9 @@ def _get_default_binary_location():
5761
browser_path = browser_paths.get(os_name)
5862

5963
if not browser_path:
64+
logger.error(f"Unsupported OS: {os_name}")
6065
raise UnsupportedOS(f'Unsupported OS: {os_name}')
6166

62-
return validate_browser_paths(browser_path)
67+
path = validate_browser_paths(browser_path)
68+
logger.debug(f"Using Chrome binary: {path}")
69+
return path

pydoll/browser/chromium/edge.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
import platform
23
from typing import Optional
34

@@ -7,6 +8,8 @@
78
from pydoll.exceptions import UnsupportedOS
89
from pydoll.utils import validate_browser_paths
910

11+
logger = logging.getLogger(__name__)
12+
1013

1114
class Edge(Browser):
1215
"""Edge browser implementation for CDP automation."""
@@ -39,6 +42,7 @@ def _get_default_binary_location():
3942
ValueError: If executable not found at default location.
4043
"""
4144
os_name = platform.system()
45+
logger.debug(f"Resolving default Edge binary for OS: {os_name}")
4246

4347
browser_paths = {
4448
'Windows': [
@@ -62,6 +66,9 @@ def _get_default_binary_location():
6266
browser_path = browser_paths.get(os_name)
6367

6468
if not browser_path:
69+
logger.error(f"Unsupported OS: {os_name}")
6570
raise UnsupportedOS()
6671

67-
return validate_browser_paths(browser_path)
72+
path = validate_browser_paths(browser_path)
73+
logger.debug(f"Using Edge binary: {path}")
74+
return path

pydoll/browser/managers/browser_options_manager.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
import logging
12
from typing import Optional
23

34
from pydoll.browser.interfaces import BrowserOptionsManager, Options
45
from pydoll.browser.options import ChromiumOptions
56
from pydoll.exceptions import InvalidOptionsObject
67

8+
logger = logging.getLogger(__name__)
9+
710

811
class ChromiumOptionsManager(BrowserOptionsManager):
912
"""
@@ -15,6 +18,10 @@ class ChromiumOptionsManager(BrowserOptionsManager):
1518

1619
def __init__(self, options: Optional[Options] = None):
1720
self.options = options
21+
logger.debug(
22+
f"ChromiumOptionsManager initialized with options="
23+
f"{type(options).__name__ if options is not None else 'None'}"
24+
)
1825

1926
def initialize_options(
2027
self,
@@ -33,14 +40,18 @@ def initialize_options(
3340
"""
3441
if self.options is None:
3542
self.options = ChromiumOptions()
43+
logger.debug("No options provided; created default ChromiumOptions")
3644

3745
if not isinstance(self.options, ChromiumOptions):
46+
logger.error(f"Invalid options type: {type(self.options)}; expected ChromiumOptions")
3847
raise InvalidOptionsObject(f'Expected ChromiumOptions, got {type(self.options)}')
3948

4049
self.add_default_arguments()
50+
logger.debug("Options initialized and default arguments applied")
4151
return self.options
4252

4353
def add_default_arguments(self):
4454
"""Add default arguments required for CDP integration."""
55+
logger.debug("Adding default arguments for Chromium-based browsers")
4556
self.options.add_argument('--no-first-run')
4657
self.options.add_argument('--no-default-browser-check')

pydoll/browser/managers/browser_process_manager.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import logging
12
import subprocess
23
from typing import Callable, Optional
34

5+
logger = logging.getLogger(__name__)
6+
47

58
class BrowserProcessManager:
69
"""
@@ -24,6 +27,10 @@ def __init__(
2427
"""
2528
self._process_creator = process_creator or self._default_process_creator
2629
self._process: Optional[subprocess.Popen] = None
30+
logger.debug(
31+
f"BrowserProcessManager initialized; "
32+
f"custom process_creator={bool(process_creator)}"
33+
)
2734

2835
def start_browser_process(
2936
self,
@@ -45,16 +52,24 @@ def start_browser_process(
4552
Note:
4653
Automatically adds --remote-debugging-port argument.
4754
"""
48-
self._process = self._process_creator([
55+
logger.info(f"Starting browser process: {binary_location} on port {port}")
56+
command = [
4957
binary_location,
5058
f'--remote-debugging-port={port}',
5159
*arguments,
52-
])
60+
]
61+
logger.debug(f"Command: {command}")
62+
self._process = self._process_creator(command)
63+
logger.debug(
64+
f"Browser process started: pid="
65+
f"{self._process.pid if self._process else 'unknown'}"
66+
)
5367
return self._process
5468

5569
@staticmethod
5670
def _default_process_creator(command: list[str]) -> subprocess.Popen:
5771
"""Create browser process with output capture to prevent console clutter."""
72+
logger.debug(f"Creating process: {command}")
5873
return subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
5974

6075
def stop_process(self):
@@ -65,8 +80,12 @@ def stop_process(self):
6580
Safe to call even if no process is running.
6681
"""
6782
if self._process:
83+
logger.info(f"Stopping browser process pid={self._process.pid}")
6884
self._process.terminate()
6985
try:
7086
self._process.wait(timeout=15)
87+
logger.debug("Process terminated gracefully")
7188
except subprocess.TimeoutExpired:
89+
logger.warning("Process did not terminate in 15s; sending SIGKILL")
7290
self._process.kill()
91+
logger.debug("Process killed")

pydoll/browser/managers/proxy_manager.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import logging
12
from typing import Optional
23

34
from pydoll.browser.options import Options
45

6+
logger = logging.getLogger(__name__)
7+
58

69
class ProxyManager:
710
"""
@@ -20,6 +23,7 @@ def __init__(self, options: Options):
2023
Will be modified if credentials are found.
2124
"""
2225
self.options = options
26+
logger.debug("ProxyManager initialized with options")
2327

2428
def get_proxy_credentials(self) -> tuple[bool, tuple[Optional[str], Optional[str]]]:
2529
"""
@@ -44,6 +48,11 @@ def get_proxy_credentials(self) -> tuple[bool, tuple[Optional[str], Optional[str
4448
self._update_proxy_argument(index, clean_proxy)
4549
private_proxy = True
4650
credentials = (username, password)
51+
logger.debug(
52+
f"Proxy credentials extracted (user_set={bool(username)}); argument sanitized"
53+
)
54+
else:
55+
logger.debug("Proxy configured without embedded credentials")
4756

4857
return private_proxy, credentials
4958

@@ -56,7 +65,9 @@ def _find_proxy_argument(self) -> Optional[tuple[int, str]]:
5665
"""
5766
for index, arg in enumerate(self.options.arguments):
5867
if arg.startswith('--proxy-server='):
59-
return index, arg.split('=', 1)[1]
68+
value = arg.split('=', 1)[1]
69+
logger.debug(f"Found proxy argument at index {index}: {value}")
70+
return index, value
6071
return None
6172

6273
@staticmethod
@@ -91,3 +102,4 @@ def _parse_proxy(proxy_value: str) -> tuple[bool, Optional[str], Optional[str],
91102
def _update_proxy_argument(self, index: int, clean_proxy: str) -> None:
92103
"""Replace proxy argument with credential-free version."""
93104
self.options.arguments[index] = f'--proxy-server={clean_proxy}'
105+
logger.debug(f"Proxy argument updated at index {index}: {clean_proxy}")

pydoll/browser/managers/temp_dir_manager.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
import logging
12
import shutil
23
import time
34
from pathlib import Path
45
from tempfile import TemporaryDirectory
56
from typing import Callable
67

8+
logger = logging.getLogger(__name__)
9+
710

811
class TempDirectoryManager:
912
"""
@@ -23,6 +26,7 @@ def __init__(self, temp_dir_factory: Callable[[], TemporaryDirectory] = Temporar
2326
"""
2427
self._temp_dir_factory = temp_dir_factory
2528
self._temp_dirs: list[TemporaryDirectory] = []
29+
logger.debug("TempDirectoryManager initialized")
2630

2731
def create_temp_dir(self) -> TemporaryDirectory:
2832
"""
@@ -33,6 +37,7 @@ def create_temp_dir(self) -> TemporaryDirectory:
3337
"""
3438
temp_dir = self._temp_dir_factory()
3539
self._temp_dirs.append(temp_dir)
40+
logger.debug(f"Created temp directory: {temp_dir.name}")
3641
return temp_dir
3742

3843
@staticmethod
@@ -56,6 +61,9 @@ def retry_process_file(func: Callable[[str], None], path: str, retry_times: int
5661
break
5762
except PermissionError:
5863
time.sleep(0.1)
64+
logger.debug(
65+
f"Retrying file operation due to PermissionError (attempt {retry_time})"
66+
)
5967
else:
6068
raise PermissionError()
6169

@@ -80,6 +88,7 @@ def handle_cleanup_error(self, func: Callable[[str], None], path: str, exc_info:
8088
self.retry_process_file(func, path)
8189
return
8290
except PermissionError:
91+
logger.warning(f"Failed retrying cleanup for locked file: {path}")
8392
raise exc_value
8493
elif exc_type is OSError:
8594
return
@@ -93,4 +102,5 @@ def cleanup(self):
93102
Continues cleanup even if some files resist deletion.
94103
"""
95104
for temp_dir in self._temp_dirs:
105+
logger.info(f"Cleaning up temp directory: {temp_dir.name}")
96106
shutil.rmtree(temp_dir.name, onerror=self.handle_cleanup_error)

0 commit comments

Comments
 (0)