uploader: delay uploading crash and boot logs on metered connections (#31045)

* uploader: delay uploading some files on metered connections

* just crash and boot for now
old-commit-hash: 19630c5af9
pull/32199/head
Adeeb Shihadeh 2 years ago committed by GitHub
parent 46aaf198ef
commit 3d85d3d857
  1. 36
      system/loggerd/uploader.py

@ -8,6 +8,7 @@ import requests
import threading import threading
import time import time
import traceback import traceback
import datetime
from typing import BinaryIO, Iterator, List, Optional, Tuple from typing import BinaryIO, Iterator, List, Optional, Tuple
from cereal import log from cereal import log
@ -45,17 +46,20 @@ def get_directory_sort(d: str) -> List[str]:
return [s.rjust(10, '0') for s in d.rsplit('--', 1)] return [s.rjust(10, '0') for s in d.rsplit('--', 1)]
def listdir_by_creation(d: str) -> List[str]: def listdir_by_creation(d: str) -> List[str]:
if not os.path.isdir(d):
return []
try: try:
paths = [f for f in os.listdir(d) if os.path.isdir(os.path.join(d, f))] paths = [f for f in os.listdir(d) if os.path.isdir(os.path.join(d, f))]
paths = sorted(paths, key=get_directory_sort) paths = sorted(paths, key=get_directory_sort)
return paths return paths
except OSError: except OSError:
cloudlog.exception("listdir_by_creation failed") cloudlog.exception("listdir_by_creation failed")
return list() return []
def clear_locks(root: str) -> None: def clear_locks(root: str) -> None:
for logname in os.listdir(root): for logdir in os.listdir(root):
path = os.path.join(root, logname) path = os.path.join(root, logdir)
try: try:
for fname in os.listdir(path): for fname in os.listdir(path):
if fname.endswith(".lock"): if fname.endswith(".lock"):
@ -76,12 +80,9 @@ class Uploader:
self.immediate_folders = ["crash/", "boot/"] self.immediate_folders = ["crash/", "boot/"]
self.immediate_priority = {"qlog": 0, "qlog.bz2": 0, "qcamera.ts": 1} self.immediate_priority = {"qlog": 0, "qlog.bz2": 0, "qcamera.ts": 1}
def list_upload_files(self) -> Iterator[Tuple[str, str, str]]: def list_upload_files(self, metered: bool) -> Iterator[Tuple[str, str, str]]:
if not os.path.isdir(self.root): for logdir in listdir_by_creation(self.root):
return path = os.path.join(self.root, logdir)
for logname in listdir_by_creation(self.root):
path = os.path.join(self.root, logname)
try: try:
names = os.listdir(path) names = os.listdir(path)
except OSError: except OSError:
@ -91,21 +92,28 @@ class Uploader:
continue continue
for name in sorted(names, key=lambda n: self.immediate_priority.get(n, 1000)): for name in sorted(names, key=lambda n: self.immediate_priority.get(n, 1000)):
key = os.path.join(logname, name) key = os.path.join(logdir, name)
fn = os.path.join(path, name) fn = os.path.join(path, name)
# skip files already uploaded # skip files already uploaded
try: try:
ctime = os.path.getctime(fn)
is_uploaded = getxattr(fn, UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE is_uploaded = getxattr(fn, UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE
except OSError: except OSError:
cloudlog.event("uploader_getxattr_failed", key=key, fn=fn) cloudlog.event("uploader_getxattr_failed", key=key, fn=fn)
is_uploaded = True # deleter could have deleted # deleter could have deleted, so skip
continue
if is_uploaded: if is_uploaded:
continue continue
# delay uploading crash and boot logs on metered connections
dt = datetime.timedelta(hours=12)
if metered and logdir in self.immediate_folders and (datetime.datetime.now() - datetime.datetime.fromtimestamp(ctime)) < dt:
continue
yield name, key, fn yield name, key, fn
def next_file_to_upload(self) -> Optional[Tuple[str, str, str]]: def next_file_to_upload(self, metered: bool) -> Optional[Tuple[str, str, str]]:
upload_files = list(self.list_upload_files()) upload_files = list(self.list_upload_files(metered))
for name, key, fn in upload_files: for name, key, fn in upload_files:
if any(f in fn for f in self.immediate_folders): if any(f in fn for f in self.immediate_folders):
@ -191,7 +199,7 @@ class Uploader:
def step(self, network_type: int, metered: bool) -> bool: def step(self, network_type: int, metered: bool) -> bool:
d = self.next_file_to_upload() d = self.next_file_to_upload(metered)
if d is None: if d is None:
return True return True

Loading…
Cancel
Save