* log in pandaStates

* Revert "log in pandaStates"

This reverts commit 87ee283ac45c2eeed94d9a958927e3072ec4460f.

* log to param

* dumps datetime

* cloudlog instead

* add truncation

* fix

* try isotimestamp

* duh

* more fixes

* should be __class__

* add some time to account for log gathering

* use new fast interface

* Revert "add some time to account for log gathering"

This reverts commit 2c08ad48052dfc0546530059a0cda03b04c4939a.

* cleanup

* simple test

* fix wrong serial

---------

Co-authored-by: Comma Device <device@comma.ai>
Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
pull/29042/head
Robbe Derks 2 years ago committed by GitHub
parent 4584e883dc
commit 70bbb94dc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      common/params.cc
  2. 46
      selfdrive/boardd/pandad.py
  3. 9
      selfdrive/boardd/tests/test_pandad.py

@ -177,6 +177,7 @@ std::unordered_map<std::string, uint32_t> keys = {
{"Offroad_UpdateFailed", CLEAR_ON_MANAGER_START}, {"Offroad_UpdateFailed", CLEAR_ON_MANAGER_START},
{"OpenpilotEnabledToggle", PERSISTENT}, {"OpenpilotEnabledToggle", PERSISTENT},
{"PandaHeartbeatLost", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION}, {"PandaHeartbeatLost", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
{"PandaLogState", PERSISTENT},
{"PandaSignatures", CLEAR_ON_MANAGER_START}, {"PandaSignatures", CLEAR_ON_MANAGER_START},
{"Passive", PERSISTENT}, {"Passive", PERSISTENT},
{"PrimeType", PERSISTENT}, {"PrimeType", PERSISTENT},

@ -3,6 +3,7 @@
import os import os
import usb1 import usb1
import time import time
import json
import subprocess import subprocess
from typing import List, NoReturn from typing import List, NoReturn
from functools import cmp_to_key from functools import cmp_to_key
@ -23,6 +24,48 @@ def get_expected_signature(panda: Panda) -> bytes:
cloudlog.exception("Error computing expected signature") cloudlog.exception("Error computing expected signature")
return b"" return b""
def read_panda_logs(panda: Panda) -> None:
"""
Forward panda logs to the cloud
"""
params = Params()
serial = panda.get_usb_serial()
log_state = {}
try:
l = json.loads(params.get("PandaLogState"))
for k, v in l.items():
if isinstance(k, str) and isinstance(v, int):
log_state[k] = v
except (TypeError, json.JSONDecodeError):
cloudlog.exception("failed to parse PandaLogState")
try:
if serial in log_state:
logs = panda.get_logs(last_id=log_state[serial])
else:
logs = panda.get_logs(get_all=True)
# truncate logs to 100 entries if needed
MAX_LOGS = 100
if len(logs) > MAX_LOGS:
cloudlog.warning(f"Panda {serial} has {len(logs)} logs, truncating to {MAX_LOGS}")
logs = logs[-MAX_LOGS:]
# update log state
if len(logs) > 0:
log_state[serial] = logs[-1]["id"]
for log in logs:
if log['timestamp'] is not None:
log['timestamp'] = log['timestamp'].isoformat()
cloudlog.event("panda_log", **log, serial=serial)
params.put("PandaLogState", json.dumps(log_state))
except Exception:
cloudlog.exception(f"Error getting logs for panda {serial}")
def flash_panda(panda_serial: str) -> Panda: def flash_panda(panda_serial: str) -> Panda:
try: try:
@ -47,7 +90,6 @@ def flash_panda(panda_serial: str) -> Panda:
if panda.bootstub: if panda.bootstub:
bootstub_version = panda.get_version() bootstub_version = panda.get_version()
cloudlog.info(f"Flashed firmware not booting, flashing development bootloader. {bootstub_version=}, {internal_panda=}") cloudlog.info(f"Flashed firmware not booting, flashing development bootloader. {bootstub_version=}, {internal_panda=}")
if internal_panda: if internal_panda:
HARDWARE.recover_internal_panda() HARDWARE.recover_internal_panda()
panda.recover(reset=(not internal_panda)) panda.recover(reset=(not internal_panda))
@ -139,6 +181,8 @@ def main() -> NoReturn:
params.put_bool("PandaHeartbeatLost", True) params.put_bool("PandaHeartbeatLost", True)
cloudlog.event("heartbeat lost", deviceState=health, serial=panda.get_usb_serial()) cloudlog.event("heartbeat lost", deviceState=health, serial=panda.get_usb_serial())
read_panda_logs(panda)
if first_run: if first_run:
if panda.is_internal(): if panda.is_internal():
# update time from RTC # update time from RTC

@ -6,6 +6,7 @@ import unittest
import cereal.messaging as messaging import cereal.messaging as messaging
from cereal import log from cereal import log
from common.gpio import gpio_set, gpio_init from common.gpio import gpio_set, gpio_init
from common.params import Params
from panda import Panda, PandaDFU, PandaProtocolMismatch from panda import Panda, PandaDFU, PandaProtocolMismatch
from selfdrive.test.helpers import phone_only from selfdrive.test.helpers import phone_only
from selfdrive.manager.process_config import managed_processes from selfdrive.manager.process_config import managed_processes
@ -17,6 +18,10 @@ HERE = os.path.dirname(os.path.realpath(__file__))
class TestPandad(unittest.TestCase): class TestPandad(unittest.TestCase):
def setUp(self):
self.params = Params()
self.start_log_state = self.params.get("PandaLogState")
def tearDown(self): def tearDown(self):
managed_processes['pandad'].stop() managed_processes['pandad'].stop()
@ -30,6 +35,10 @@ class TestPandad(unittest.TestCase):
if sm['peripheralState'].pandaType == log.PandaState.PandaType.unknown: if sm['peripheralState'].pandaType == log.PandaState.PandaType.unknown:
raise Exception("boardd failed to start") raise Exception("boardd failed to start")
# simple check that we did something with the panda logs
cur_log_state = self.params.get("PandaLogState")
assert cur_log_state != self.start_log_state
def _go_to_dfu(self): def _go_to_dfu(self):
HARDWARE.recover_internal_panda() HARDWARE.recover_internal_panda()
assert Panda.wait_for_dfu(None, 10) assert Panda.wait_for_dfu(None, 10)

Loading…
Cancel
Save