Added telemetry system to get information about issues.

This commit is contained in:
2026-09-07 21:49:37 +02:00
parent bea9d6fda7
commit f06fc2e4e3
16 changed files with 4125 additions and 169 deletions

View File

@@ -15,6 +15,7 @@ import subprocess
import sys
import tarfile
import tempfile
import time
from typing import Mapping
from urllib.error import HTTPError, URLError
from urllib.parse import urlsplit, urlunsplit
@@ -23,6 +24,11 @@ from urllib.request import Request, urlopen
from . import __version__
from .locking import launcher_operation_lock
from .paths import AppPaths
from .telemetry import (
classify_network_failure,
current_telemetry,
network_http_status,
)
DEFAULT_UPDATE_REPOSITORY_URL = (
@@ -681,6 +687,18 @@ def _download_archive(
) -> None:
if destination.is_file() and _archive_matches(destination, manifest):
return
telemetry = current_telemetry()
download_started_at = time.monotonic()
if telemetry is not None:
telemetry.send_event(
"download_started",
metadata={
"resource_type": "launcher_update",
"content_bytes": manifest.archive_size,
"mirror_id": "launcher_update_channel",
},
context={"operation": "launcher_update", "stage": "download"},
)
destination.parent.mkdir(parents=True, exist_ok=True)
temporary = destination.with_name(f".{destination.name}.{os.getpid()}.part")
temporary.unlink(missing_ok=True)
@@ -693,6 +711,7 @@ def _download_archive(
},
method="GET",
)
written = 0
try:
try:
response = urlopen(request, timeout=timeout_seconds)
@@ -715,7 +734,6 @@ def _download_archive(
"launcher archive Content-Length does not match the signed manifest"
)
digest = hashlib.sha256()
written = 0
with temporary.open("xb") as handle:
while True:
chunk = response.read(READ_SIZE)
@@ -736,9 +754,52 @@ def _download_archive(
raise LauncherUpdateError("launcher archive SHA-256 does not match the manifest")
temporary.replace(destination)
_fsync_directory(destination.parent)
except BaseException:
except BaseException as exc:
temporary.unlink(missing_ok=True)
if telemetry is not None:
duration = max(0.0, time.monotonic() - download_started_at)
telemetry.send_event(
"download_failed",
severity="error",
message=str(exc),
metadata={
"resource_type": "launcher_update",
"download_bytes": written,
"content_bytes": manifest.archive_size,
"duration_ms": round(duration * 1000),
"average_mbps": _average_mbps(written, duration),
"retry_count": 0,
"resume_used": False,
"http_status": network_http_status(exc),
"failure_type": classify_network_failure(exc),
"mirror_id": "launcher_update_channel",
},
context={"operation": "launcher_update", "stage": "download"},
)
raise
duration = max(0.0, time.monotonic() - download_started_at)
if telemetry is not None:
telemetry.send_event(
"download_completed",
metadata={
"resource_type": "launcher_update",
"download_bytes": written,
"content_bytes": manifest.archive_size,
"duration_ms": round(duration * 1000),
"average_mbps": _average_mbps(written, duration),
"retry_count": 0,
"resume_used": False,
"http_status": 200,
"mirror_id": "launcher_update_channel",
},
context={"operation": "launcher_update", "stage": "download"},
)
def _average_mbps(download_bytes: int, duration_seconds: float) -> float | None:
if download_bytes <= 0 or duration_seconds <= 0:
return None
return round((download_bytes * 8) / duration_seconds / 1_000_000, 3)
def _stage_and_install_release(