Skip to content

Commit 1dd5b81

Browse files
authored
Chore: enrich autoqa log (#5862)
* chore: add app log upload to reportportal
1 parent f59739d commit 1dd5b81

File tree

6 files changed

+153
-3
lines changed

6 files changed

+153
-3
lines changed

autoqa/reportportal_handler.py

Lines changed: 133 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import mimetypes
44
import re
55
import logging
6+
import glob
7+
import platform
68
from reportportal_client.helpers import timestamp
79

810
logger = logging.getLogger(__name__)
@@ -160,7 +162,133 @@ def extract_test_result_from_trajectory(trajectory_dir):
160162
logger.error(f"Error extracting test result: {e}")
161163
return False
162164

163-
def upload_test_results_to_rp(client, launch_id, test_path, trajectory_dir, force_stopped=False, video_path=None):
165+
def get_jan_log_paths(is_nightly=False):
166+
"""
167+
Get Jan application log file paths based on OS and version (nightly vs regular)
168+
Returns list of glob patterns for log files
169+
"""
170+
system = platform.system().lower()
171+
app_name = "Jan-nightly" if is_nightly else "Jan"
172+
173+
if system == "windows":
174+
# Windows: %APPDATA%\Jan(-nightly)\data\logs\*.log
175+
appdata = os.path.expandvars("%APPDATA%")
176+
return [f"{appdata}\\{app_name}\\data\\logs\\*.log"]
177+
178+
elif system == "darwin": # macOS
179+
# macOS: ~/Library/Application Support/Jan(-nightly)/data/logs/*.log
180+
home_dir = os.path.expanduser("~")
181+
return [f"{home_dir}/Library/Application Support/{app_name}/data/logs/*.log"]
182+
183+
elif system == "linux":
184+
# Linux: ~/.local/share/Jan(-nightly)/data/logs/*.log
185+
home_dir = os.path.expanduser("~")
186+
return [f"{home_dir}/.local/share/{app_name}/data/logs/*.log"]
187+
188+
else:
189+
logger.warning(f"Unsupported OS: {system}")
190+
return []
191+
192+
def upload_jan_logs(client, test_item_id, is_nightly=False, max_log_files=5):
193+
"""
194+
Upload Jan application log files to ReportPortal
195+
"""
196+
log_patterns = get_jan_log_paths(is_nightly)
197+
app_type = "nightly" if is_nightly else "regular"
198+
199+
logger.info(f"Looking for Jan {app_type} logs...")
200+
201+
all_log_files = []
202+
for pattern in log_patterns:
203+
try:
204+
log_files = glob.glob(pattern)
205+
all_log_files.extend(log_files)
206+
logger.info(f"Found {len(log_files)} log files matching pattern: {pattern}")
207+
except Exception as e:
208+
logger.error(f"Error searching for logs with pattern {pattern}: {e}")
209+
210+
if not all_log_files:
211+
logger.warning(f"No Jan {app_type} log files found")
212+
client.log(
213+
time=timestamp(),
214+
level="WARNING",
215+
message=f"📝 No Jan {app_type} application logs found",
216+
item_id=test_item_id
217+
)
218+
return
219+
220+
# Sort by modification time (newest first) and limit to max_log_files
221+
try:
222+
all_log_files.sort(key=lambda x: os.path.getmtime(x), reverse=True)
223+
log_files_to_upload = all_log_files[:max_log_files]
224+
225+
logger.info(f"Uploading {len(log_files_to_upload)} most recent Jan {app_type} log files")
226+
227+
for i, log_file in enumerate(log_files_to_upload, 1):
228+
try:
229+
file_size = os.path.getsize(log_file)
230+
file_name = os.path.basename(log_file)
231+
232+
# Check file size limit (50MB = 50 * 1024 * 1024 bytes)
233+
max_file_size = 50 * 1024 * 1024 # 50MB
234+
if file_size > max_file_size:
235+
logger.warning(f"Log file {file_name} is too large ({file_size} bytes > {max_file_size} bytes), skipping upload")
236+
client.log(
237+
time=timestamp(),
238+
level="WARNING",
239+
message=f"📝 Log file {file_name} skipped (size: {file_size} bytes > 50MB limit)",
240+
item_id=test_item_id
241+
)
242+
continue
243+
244+
logger.info(f"Uploading log file {i}/{len(log_files_to_upload)}: {file_name} ({file_size} bytes)")
245+
246+
# Read log file content (safe to read since we checked size)
247+
with open(log_file, 'r', encoding='utf-8', errors='ignore') as f:
248+
log_content = f.read()
249+
250+
# Upload as text attachment
251+
client.log(
252+
time=timestamp(),
253+
level="INFO",
254+
message=f"📝 Jan {app_type} application log: {file_name}",
255+
item_id=test_item_id,
256+
attachment={
257+
"name": f"jan_{app_type}_log_{i}_{file_name}",
258+
"data": log_content.encode('utf-8'),
259+
"mime": "text/plain"
260+
}
261+
)
262+
263+
logger.info(f"Successfully uploaded log: {file_name}")
264+
265+
except Exception as e:
266+
logger.error(f"Error uploading log file {log_file}: {e}")
267+
client.log(
268+
time=timestamp(),
269+
level="ERROR",
270+
message=f"Failed to upload log file {os.path.basename(log_file)}: {str(e)}",
271+
item_id=test_item_id
272+
)
273+
274+
# Add summary log
275+
client.log(
276+
time=timestamp(),
277+
level="INFO",
278+
message=f"📝 Uploaded {len(log_files_to_upload)} Jan {app_type} log files (total available: {len(all_log_files)})",
279+
item_id=test_item_id
280+
)
281+
282+
except Exception as e:
283+
logger.error(f"Error processing Jan logs: {e}")
284+
client.log(
285+
time=timestamp(),
286+
level="ERROR",
287+
message=f"Error processing Jan {app_type} logs: {str(e)}",
288+
item_id=test_item_id
289+
)
290+
291+
def upload_test_results_to_rp(client, launch_id, test_path, trajectory_dir, force_stopped=False, video_path=None, is_nightly=False):
164292
"""
165293
Upload test results to ReportPortal with proper status based on test result
166294
"""
@@ -281,6 +409,10 @@ def upload_test_results_to_rp(client, launch_id, test_path, trajectory_dir, forc
281409
item_id=test_item_id
282410
)
283411

412+
# Upload Jan application logs
413+
logger.info("Uploading Jan application logs...")
414+
upload_jan_logs(client, test_item_id, is_nightly=is_nightly, max_log_files=5)
415+
284416
# Upload all turn data with appropriate status
285417
# If test failed, mark all turns as failed
286418
force_fail_turns = (final_status == "FAILED")

autoqa/scripts/macos_install.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ echo "Process name: $PROCESS_NAME"
7676
echo "JAN_APP_PATH=$APP_PATH" >> $GITHUB_ENV
7777
echo "PROCESS_NAME=$PROCESS_NAME" >> $GITHUB_ENV
7878

79+
echo "⏳ Waiting for Jan app first initialization (120 seconds)..."
80+
echo "This allows Jan to complete its initial setup and configuration"
81+
sleep 120
82+
echo "✅ Initialization wait completed"
83+
7984
# Verify installation
8085
if [ -f "$APP_PATH" ]; then
8186
echo "✅ Jan app installed successfully"

autoqa/scripts/ubuntu_install.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ sudo apt-get install -f -y
1515
# Wait for installation to complete
1616
sleep 10
1717

18+
echo "⏳ Waiting for Jan app first initialization (120 seconds)..."
19+
echo "This allows Jan to complete its initial setup and configuration"
20+
sleep 120
21+
echo "✅ Initialization wait completed"
22+
1823
# Verify installation based on nightly flag
1924
if [ "$IS_NIGHTLY" = "true" ]; then
2025
DEFAULT_JAN_PATH="/usr/bin/Jan-nightly"

autoqa/scripts/windows_install.ps1

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ catch {
2424
# Wait a bit for installation to complete
2525
Start-Sleep -Seconds 10
2626

27+
Write-Host "⏳ Waiting for Jan app first initialization (120 seconds)..."
28+
Write-Host "This allows Jan to complete its initial setup and configuration"
29+
Start-Sleep -Seconds 120
30+
Write-Host "✅ Initialization wait completed"
31+
2732
# Verify installation based on nightly flag
2833
if ($isNightly) {
2934
$defaultJanPath = "$env:LOCALAPPDATA\Programs\jan-nightly\Jan-nightly.exe"

autoqa/test_runner.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ async def run_single_test_with_timeout(computer, test_data, rp_client, launch_id
2525
path = test_data['path']
2626
prompt = test_data['prompt']
2727

28+
# Detect if using nightly version based on process name
29+
is_nightly = "nightly" in jan_process_name.lower() if jan_process_name else False
30+
2831
# Default agent config if not provided
2932
if agent_config is None:
3033
agent_config = {
@@ -210,7 +213,7 @@ async def run_agent():
210213
logger.info(f"Video exists: {os.path.exists(video_path)}")
211214
if os.path.exists(video_path):
212215
logger.info(f"Video file size: {os.path.getsize(video_path)} bytes")
213-
upload_test_results_to_rp(rp_client, launch_id, path, trajectory_dir, force_stopped_due_to_turns, video_path)
216+
upload_test_results_to_rp(rp_client, launch_id, path, trajectory_dir, force_stopped_due_to_turns, video_path, is_nightly)
214217
else:
215218
logger.warning(f"Test completed but no trajectory found for: {path}")
216219
# Handle case where test completed but no trajectory found

autoqa/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ def start_jan_app(jan_app_path=None):
280280
# Wait a bit more after maximizing
281281
time.sleep(10)
282282
logger.info("Jan application should be ready, waiting for additional setup...")
283-
time.sleep(120) # Additional wait to ensure everything is ready
283+
time.sleep(10) # Additional wait to ensure everything is ready
284284

285285
except Exception as e:
286286
logger.error(f"Error starting Jan application: {e}")

0 commit comments

Comments
 (0)