60 lines
3.0 KiB
Python
60 lines
3.0 KiB
Python
"""埋点/上报成功率自报计数快照表(append-only)。
|
|
|
|
客户端周期上报「自 epoch 起算的累计计数」;服务端只存原始快照,查询时在 Python 侧差分聚合
|
|
(见 app/admin/repositories/analytics_health.py)。与既有 analytics_event 表完全独立。
|
|
|
|
- analytics_selfstat :一快照一行(快照头 + 设备维度 + 设备级诊断量)
|
|
- analytics_selfstat_event :一 event 一行(四类累计计数),外键指向快照头
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import BigInteger, DateTime, ForeignKey, Integer, String, func
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from app.db.base import Base
|
|
|
|
|
|
class AnalyticsSelfStat(Base):
|
|
__tablename__ = "analytics_selfstat"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
device_id: Mapped[str] = mapped_column(String(64), index=True, nullable=False)
|
|
epoch_id: Mapped[str] = mapped_column(String(64), index=True, nullable=False)
|
|
# 设备维度(每设备固定,下钻用)
|
|
app_ver: Mapped[str | None] = mapped_column(String(32), nullable=True)
|
|
oem: Mapped[str | None] = mapped_column(String(32), nullable=True)
|
|
os: Mapped[str | None] = mapped_column(String(32), nullable=True)
|
|
# 设备级诊断量(累计;queue_depth 是瞬时 gauge)
|
|
batches_attempted: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0)
|
|
batches_ok: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0)
|
|
batches_fail: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0)
|
|
retries: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0)
|
|
queue_depth: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
|
sent_at: Mapped[int | None] = mapped_column(BigInteger, nullable=True) # 端上报时刻 epoch ms
|
|
# 服务端接收时间(权威,用于时间分桶与分区排序)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), index=True, nullable=False
|
|
)
|
|
|
|
def __repr__(self) -> str: # pragma: no cover
|
|
return f"<AnalyticsSelfStat id={self.id} device={self.device_id} epoch={self.epoch_id}>"
|
|
|
|
|
|
class AnalyticsSelfStatEvent(Base):
|
|
__tablename__ = "analytics_selfstat_event"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
snapshot_id: Mapped[int] = mapped_column(
|
|
ForeignKey("analytics_selfstat.id"), index=True, nullable=False
|
|
)
|
|
event: Mapped[str] = mapped_column(String(64), index=True, nullable=False)
|
|
attempted: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0)
|
|
drop_capture: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0)
|
|
delivered: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0)
|
|
drop_undelivered: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0)
|
|
|
|
def __repr__(self) -> str: # pragma: no cover
|
|
return f"<AnalyticsSelfStatEvent snap={self.snapshot_id} event={self.event}>"
|