Files
waydroid/tools/actions/bugreport.py
Alessandro Astone 13a576b4c1 tools: Add bugreport action
`waydroid bugreport` will generate a tarball with all the interesting logs.
This is to facilitate bug reporting.
2025-11-09 19:13:47 +01:00

140 lines
3.9 KiB
Python

# Copyright 2025 Alessandro Astone
# SPDX-License-Identifier: GPL-3.0-or-later
import tools.config
import dbus
import logging
import os
import shutil
import subprocess
import sys
import tarfile
import tempfile
import time
WAYDROID = sys.argv[0]
TARBALL = "waydroid-bugreport.tar.xz"
def logcat(output_path):
with open(output_path, "w+") as fd:
return subprocess.Popen(["sudo", WAYDROID, "logcat"], stdout=fd, stderr=sys.stderr, stdin=None)
def dmesg(params, output_path):
with open(output_path, "w+") as fd:
return subprocess.Popen(["sudo", "dmesg", "-T"] + params, stdout=fd, stderr=fd, stdin=None)
def waydroid_session(output_path):
with open(output_path, "w+") as fd:
return subprocess.Popen([WAYDROID, "session", "start"], stdout=fd, stderr=fd, stdin=None, start_new_session=True)
def clear_line():
sys.stdout.write("\33[2K\r")
def sleep_progress(seconds):
bar_length = 50
time_increment = 0.1
spinner_chars = ['|', '/', '-', '\\']
iteration = 0
time_slept = 0
try:
while time_slept < seconds:
spinner_char = spinner_chars[iteration % len(spinner_chars)]
filled_length = int(bar_length * time_slept // seconds)
sys.stdout.write(f"[{'=' * filled_length}{' ' * (bar_length - filled_length)}] {spinner_char}\r")
sys.stdout.flush()
time.sleep(time_increment)
time_slept += time_increment
iteration += 1
clear_line()
except KeyboardInterrupt:
clear_line()
print("Interrupted.")
def bugreport(args):
tmp = tempfile.mkdtemp()
print("\
The following information will be collected:\n\
- System kernel logs (kmsg)\n\
- Android system and user logs (logcat)\n\
- Waydroid container manager logs (/var/lib/waydroid/waydroid.log)\n\
- Waydroid configuration files (/var/lib/waydroid/*)\n\
\n\
The information will be stored on your machine.\n\
")
print("Please authenticate as administrator in order to read system logs.")
try:
subprocess.run(["sudo", "-v"])
print()
except:
return
procs = []
logfiles = []
def logfile(name):
file = os.path.join(tmp, name)
logfiles.append(file)
return file
session = None
try:
session = tools.helpers.ipc.DBusContainerService().GetSession()
except dbus.DBusException:
pass
if not session:
print("Waydroid session not found. Trying to start one...")
procs.append(waydroid_session(logfile("session.txt")))
sleep_progress(10)
try:
session = tools.helpers.ipc.DBusContainerService().GetSession()
except dbus.DBusException:
pass
if session:
print("\n\
\033[1mPlease try to reproduce the problem now.\033[0m\n\
Waydroid will collect logs for up to 5 minutes. You may interrupt this operation earlier.\n\
")
procs.append(logcat(logfile("logcat.txt")))
procs.append(dmesg(["-w"], logfile("dmesg.txt")))
sleep_progress(5 * 60)
else:
print("Session did not start\n")
dmesg_process = dmesg([], logfile("dmesg.txt"))
for p in procs:
p.terminate()
for p in procs:
p.wait()
print("Creating archive...")
try:
with tarfile.open(TARBALL, "w:xz", preset=9) as tar:
files = [
"/var/lib/waydroid/waydroid.log",
"/var/lib/waydroid/waydroid.cfg",
"/var/lib/waydroid/waydroid_base.prop",
"/var/lib/waydroid/waydroid.prop",
"/var/lib/waydroid/lxc",
] + logfiles
for f in files:
try:
tar.add(f, arcname=os.path.basename(f), recursive=True)
except Exception as e:
logging.debug(f"Failed to archive {f}: {repr(e)}")
except Exception as e:
raise e
finally:
shutil.rmtree(tmp)
print(f"Created \033[1m{TARBALL}\033[0m")