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
pull/30996/merge
Adeeb Shihadeh 2 years ago committed by GitHub
parent 4c2bb9f380
commit 19630c5af9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  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