feat: 增加日志模块
This commit is contained in:
@@ -16,8 +16,8 @@ from .common import (
|
||||
load_omnisocket_config,
|
||||
utc_iso_now,
|
||||
)
|
||||
from .control import ControlArbiter, NativeUdpControlIngress, OmniSocketControlSender
|
||||
from .video import FrameTrailerMetadata, OmniSocketVideoReceiver
|
||||
from .control import ControlAckTracker, ControlArbiter, NativeUdpControlIngress, OmniSocketControlAckReceiver, OmniSocketControlSender
|
||||
from .video import FrameTrailerMetadata, OmniSocketVideoReceiver, VideoDisplayProbeStore
|
||||
|
||||
|
||||
LOCAL_SAMPLE_INTERVAL_MS = 500
|
||||
@@ -140,7 +140,9 @@ class KcpTrendTracker:
|
||||
"conv": _coerce_int(raw.get("conv")),
|
||||
"rto_ms": _coerce_int(raw.get("rto_ms")),
|
||||
"srtt_ms": _coerce_int(raw.get("srtt_ms")),
|
||||
"min_srtt_ms": _coerce_int(raw.get("min_srtt_ms")),
|
||||
"srttvar_ms": _coerce_int(raw.get("srttvar_ms")),
|
||||
"last_feedback_age_ms": _coerce_int(raw.get("last_feedback_age_ms")),
|
||||
"snd_wnd": snd_wnd,
|
||||
"rmt_wnd": rmt_wnd,
|
||||
"inflight": inflight,
|
||||
@@ -419,15 +421,21 @@ class NetworkTelemetryService:
|
||||
self,
|
||||
video_receiver: OmniSocketVideoReceiver,
|
||||
control_sender: OmniSocketControlSender,
|
||||
control_ack_tracker: ControlAckTracker,
|
||||
control_ack_receiver: OmniSocketControlAckReceiver,
|
||||
control_arbiter: ControlArbiter,
|
||||
native_ingress: NativeUdpControlIngress,
|
||||
hub_receiver: HubTelemetryReceiver,
|
||||
video_display_probe_store: VideoDisplayProbeStore,
|
||||
) -> None:
|
||||
self._video_receiver = video_receiver
|
||||
self._control_sender = control_sender
|
||||
self._control_ack_tracker = control_ack_tracker
|
||||
self._control_ack_receiver = control_ack_receiver
|
||||
self._control_arbiter = control_arbiter
|
||||
self._native_ingress = native_ingress
|
||||
self._hub_receiver = hub_receiver
|
||||
self._video_display_probe_store = video_display_probe_store
|
||||
self._trend_tracker = KcpTrendTracker()
|
||||
self._rate_lock = threading.Lock()
|
||||
self._last_rate_sample: tuple[float, int, int] | None = None
|
||||
@@ -439,6 +447,7 @@ class NetworkTelemetryService:
|
||||
def _ensure_started(self) -> None:
|
||||
self._video_receiver.ensure_started()
|
||||
self._control_arbiter.ensure_started()
|
||||
self._control_ack_receiver.ensure_started()
|
||||
self._native_ingress.ensure_started()
|
||||
self._hub_receiver.ensure_started()
|
||||
with self._rate_lock:
|
||||
@@ -629,6 +638,74 @@ class NetworkTelemetryService:
|
||||
"updated_at": _utc_from_epoch(updated_at_epoch_ms / 1000.0) or utc_iso_now(),
|
||||
}
|
||||
|
||||
def _derive_latency_estimate(
|
||||
self,
|
||||
*,
|
||||
links: dict[str, dict[str, Any]],
|
||||
video_receiver_status: dict[str, Any],
|
||||
display_probe_status: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
a_to_d_control_raw = links["a_to_d"]["sessions"]["control"]["kcp"].get("srtt_ms")
|
||||
d_to_b_control_raw = links["d_to_b"]["sessions"]["control"]["kcp"].get("srtt_ms")
|
||||
a_to_d_control_min_raw = links["a_to_d"]["sessions"]["control"]["kcp"].get("min_srtt_ms")
|
||||
d_to_b_control_min_raw = links["d_to_b"]["sessions"]["control"]["kcp"].get("min_srtt_ms")
|
||||
a_to_d_video_raw = links["a_to_d"]["sessions"]["video"]["kcp"].get("srtt_ms")
|
||||
d_to_b_video_raw = links["d_to_b"]["sessions"]["video"]["kcp"].get("srtt_ms")
|
||||
|
||||
a_to_d_control = _coerce_float(a_to_d_control_raw) if a_to_d_control_raw is not None else None
|
||||
d_to_b_control = _coerce_float(d_to_b_control_raw) if d_to_b_control_raw is not None else None
|
||||
a_to_d_control_min = _coerce_float(a_to_d_control_min_raw) if a_to_d_control_min_raw is not None else None
|
||||
d_to_b_control_min = _coerce_float(d_to_b_control_min_raw) if d_to_b_control_min_raw is not None else None
|
||||
a_to_d_video = _coerce_float(a_to_d_video_raw) if a_to_d_video_raw is not None else None
|
||||
d_to_b_video = _coerce_float(d_to_b_video_raw) if d_to_b_video_raw is not None else None
|
||||
ack_estimate = self._control_ack_tracker.get_latest_estimate()
|
||||
capture_to_send_raw = video_receiver_status.get("latest_capture_to_send_ms")
|
||||
a_recv_to_paint_raw = display_probe_status.get("a_recv_to_paint_ms")
|
||||
capture_to_send_ms = _coerce_float(capture_to_send_raw) if capture_to_send_raw is not None else None
|
||||
a_recv_to_paint_ms = _coerce_float(a_recv_to_paint_raw) if a_recv_to_paint_raw is not None else None
|
||||
video_network_oneway_est_ms = (
|
||||
round((a_to_d_video + d_to_b_video) / 2.0, 3)
|
||||
if a_to_d_video is not None and d_to_b_video is not None
|
||||
else None
|
||||
)
|
||||
video_partial_est_ms = None
|
||||
if capture_to_send_ms is not None and video_network_oneway_est_ms is not None:
|
||||
video_partial_est_ms = round(capture_to_send_ms + video_network_oneway_est_ms, 3)
|
||||
video_e2e_est_ms = None
|
||||
if video_partial_est_ms is not None and a_recv_to_paint_ms is not None:
|
||||
video_e2e_est_ms = round(video_partial_est_ms + a_recv_to_paint_ms, 3)
|
||||
|
||||
return {
|
||||
"control_loop_rtt_ms": ack_estimate.get("control_loop_rtt_ms"),
|
||||
"control_to_persist_est_ms": ack_estimate.get("control_to_persist_est_ms"),
|
||||
"control_oneway_srtt_est_ms": (
|
||||
round((a_to_d_control + d_to_b_control) / 2.0, 3)
|
||||
if a_to_d_control is not None and d_to_b_control is not None
|
||||
else None
|
||||
),
|
||||
"control_oneway_bestcase_est_ms": (
|
||||
round((a_to_d_control_min + d_to_b_control_min) / 2.0, 3)
|
||||
if a_to_d_control_min is not None and d_to_b_control_min is not None
|
||||
else None
|
||||
),
|
||||
"video_network_oneway_est_ms": video_network_oneway_est_ms,
|
||||
"video_partial_est_ms": video_partial_est_ms,
|
||||
"video_e2e_est_ms": video_e2e_est_ms,
|
||||
"estimate_method": {
|
||||
"control": "ack_loop" if ack_estimate.get("ack_available") else "srtt_fallback",
|
||||
"video": "capture_to_send+srtt/2+recv_to_paint" if video_e2e_est_ms is not None else "capture_to_send+srtt/2",
|
||||
},
|
||||
"clock_sync_required": False,
|
||||
"assumptions": [
|
||||
"control one-way estimate uses ACK loop when available",
|
||||
"video one-way estimate uses per-leg SRTT and local paint timing",
|
||||
],
|
||||
"confidence": {
|
||||
"control": "derived_ack" if ack_estimate.get("ack_available") else "fallback_srtt",
|
||||
"video": "derived_local_probe" if video_e2e_est_ms is not None else "partial_without_probe",
|
||||
},
|
||||
}
|
||||
|
||||
def get_latest(self) -> dict[str, Any]:
|
||||
self._ensure_started()
|
||||
|
||||
@@ -645,7 +722,10 @@ class NetworkTelemetryService:
|
||||
arbiter_status = self._control_arbiter.get_status()
|
||||
ingress_status = self._native_ingress.get_status()
|
||||
sender_status = self._control_sender.get_status()
|
||||
ack_receiver_status = self._control_ack_receiver.get_status()
|
||||
ack_status = self._control_ack_tracker.get_latest_estimate()
|
||||
telemetry_state = self._hub_receiver.get_snapshot()
|
||||
display_probe_status = self._video_display_probe_store.get_status()
|
||||
|
||||
total_send_bytes = int(video_app.get("send_bytes", 0)) + int(control_app.get("send_bytes", 0))
|
||||
total_recv_bytes = int(video_app.get("recv_bytes", 0)) + int(control_app.get("recv_bytes", 0))
|
||||
@@ -697,6 +777,9 @@ class NetworkTelemetryService:
|
||||
remote_stale,
|
||||
),
|
||||
}
|
||||
self._video_receiver.update_remote_video_srtt(
|
||||
_coerce_int(remote_sessions["video"]["kcp"].get("srtt_ms")) if remote_sessions["video"]["kcp"].get("srtt_ms") is not None else None
|
||||
)
|
||||
|
||||
links = {
|
||||
"a_to_d": self._build_link("local-a-side", local_updated_at, False, local_sessions),
|
||||
@@ -724,6 +807,11 @@ class NetworkTelemetryService:
|
||||
telemetry_state=telemetry_state,
|
||||
watchdog_status=watchdog_status,
|
||||
)
|
||||
latency_estimate = self._derive_latency_estimate(
|
||||
links=links,
|
||||
video_receiver_status=video_receiver_status,
|
||||
display_probe_status=display_probe_status,
|
||||
)
|
||||
|
||||
if local_control_registered and remote_control_fresh:
|
||||
peer_status = "online"
|
||||
@@ -764,6 +852,12 @@ class NetworkTelemetryService:
|
||||
},
|
||||
},
|
||||
"links": links,
|
||||
"latency_estimate": latency_estimate,
|
||||
"video_freshness": video_receiver_status.get("freshness", {}),
|
||||
"control_ack_status": {
|
||||
**ack_status,
|
||||
"receiver": ack_receiver_status,
|
||||
},
|
||||
"telemetry_receiver": {
|
||||
"hub_connected": bool(telemetry_state.get("connected")),
|
||||
"hub_updated_at": telemetry_state.get("updated_at"),
|
||||
@@ -781,6 +875,7 @@ class NetworkTelemetryService:
|
||||
"control": {
|
||||
"arbiter": arbiter_status,
|
||||
"sender": sender_status,
|
||||
"ack_receiver": ack_receiver_status,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user