Skip to content

Commit

Permalink
Add Playwright Tracing Feature (#32)
Browse files Browse the repository at this point in the history
* added playwright tracing

* updated readme file for how to use tracing

* created _start_trace() function for generalising

* updated trace code
  • Loading branch information
Shahalt1 authored Jan 24, 2025
1 parent 92621fb commit 65e52e7
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,20 @@ To configure Hercules in detail:

For example: If you would like to run with a "Headful" browser, you can set the environment variable with ```export HEADLESS=false``` before triggering Hercules.

- **How to Use Tracing in Playwright**

Tracing in Playwright allows you to analyze test executions and debug issues effectively. To enable tracing in your Playwright tests, follow these steps:

1. Ensure that tracing is enabled in the configuration.
2. Traces will be saved to the specified path: `{proof_path}/traces/trace.zip`.

#### Enabling Tracing

To enable tracing, set the following environment variable:

```bash
export ENABLE_PLAYWRIGHT_TRACING=true
```

### Understanding `agents_llm_config-example.json`

Expand Down
7 changes: 7 additions & 0 deletions testzeus_hercules/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ def _merge_from_env(self) -> None:
"EXECUTE_BULK",
]

relevant_keys.append("ENABLE_PLAYWRIGHT_TRACING")

for key in relevant_keys:
if key in os.environ:
self._config[key] = os.environ[key]
Expand Down Expand Up @@ -262,6 +264,7 @@ def _finalize_defaults(self) -> None:
self._config.setdefault("GEO_API_KEY", None)
self._config.setdefault("REACTION_DELAY_TIME", "0.1")
self._config.setdefault("EXECUTE_BULK", "false")
self._config.setdefault("ENABLE_PLAYWRIGHT_TRACING", "false")

if self._config["MODE"] == "debug":
self.timestamp = "0"
Expand Down Expand Up @@ -328,6 +331,10 @@ def should_execute_bulk(self) -> bool:
"""Return whether tests should be executed in bulk mode"""
return self._config["EXECUTE_BULK"].lower().strip() == "true"

def should_enable_tracing(self) -> bool:
"""Check if Playwright tracing should be enabled"""
return self._config.get("ENABLE_PLAYWRIGHT_TRACING", "false").lower() == "true"

# -------------------------------------------------------------------------
# Directory creation logic (mirroring your original code)
# -------------------------------------------------------------------------
Expand Down
45 changes: 45 additions & 0 deletions testzeus_hercules/core/playwright_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,13 @@ def __init__(
self._video_dir = proof_path + "/videos"
self.request_response_log_file = proof_path + "/network_logs.json"
self.console_log_file = proof_path + "/console_logs.json"
# Add trace directory path
self._enable_tracing = get_global_conf().should_enable_tracing()
self._trace_dir = None
if self._enable_tracing:
proof_path = get_global_conf().get_proof_path(test_id=self.stake_id)
self._trace_dir = os.path.join(proof_path, "traces")
logger.info(f"Tracing enabled. Traces will be saved to: {self._trace_dir}")

# ----------------------
# 4) LOGS
Expand Down Expand Up @@ -251,6 +258,8 @@ async def async_initialize(self) -> None:
# Create required directories
os.makedirs(self._screenshots_dir, exist_ok=True)
os.makedirs(self._video_dir, exist_ok=True)
if self._enable_tracing:
os.makedirs(self._trace_dir, exist_ok=True)
os.makedirs(os.path.dirname(self.request_response_log_file), exist_ok=True)
os.makedirs(os.path.dirname(self.console_log_file), exist_ok=True)

Expand Down Expand Up @@ -331,6 +340,21 @@ def unzip_archive(zip_path, extract_dir):
elif self.browser_type == "firefox":
self._extension_path = extension_file_path

async def _start_tracing(self, context_type: str = "browser") -> None:
"""Helper method to start tracing for a browser context."""
if not self._enable_tracing:
return

try:
await self._browser_context.tracing.start(
screenshots=True,
snapshots=True,
sources=True,
)
logger.info(f"Tracing started for {context_type} context")
except Exception as e:
logger.error(f"Failed to start tracing for {context_type} context: {e}")

async def create_browser_context(self) -> None:
"""
Creates the browser context with device descriptor if any,
Expand Down Expand Up @@ -402,6 +426,9 @@ async def create_browser_context(self) -> None:
else:
await self._launch_persistent_browser(browser_type, user_dir, disable_args)

# Start tracing only once after browser context is created
await self._start_tracing()

def _build_emulation_context_options(self) -> Dict[str, Any]:
"""
Combine device descriptor with user overrides (locale, timezone, geolocation,
Expand Down Expand Up @@ -786,6 +813,24 @@ def rename_file(src, dst):
logger.info(f"Video recorded at {new_video_path}")
except Exception as e:
logger.error(f"Could not finalize video: {e}")

# Stop and save tracing before closing context
if self._enable_tracing:
try:
timestamp = int(time.time())
trace_file = os.path.join(self._trace_dir, f"trace_{timestamp}.zip")
os.makedirs(self._trace_dir, exist_ok=True)

await self._browser_context.tracing.stop(path=trace_file)

if os.path.exists(trace_file):
logger.info(f"Trace saved successfully at: {trace_file}")
else:
logger.error(f"Trace file was not created at: {trace_file}")
except Exception as e:
logger.error(f"Error stopping trace: {e}")
traceback.print_exc()

await self._browser_context.close()
self._browser_context = None

Expand Down

0 comments on commit 65e52e7

Please sign in to comment.