letsbe-hub/app/models/usage_sample.py

73 lines
2.0 KiB
Python

"""Usage sample model - aggregated telemetry data.
PRIVACY GUARANTEE: This model contains NO sensitive data fields.
Only tool names, durations, and counts are stored.
"""
from datetime import datetime
from uuid import UUID
from sqlalchemy import DateTime, ForeignKey, Integer, String
from sqlalchemy.orm import Mapped, mapped_column
from app.models.base import Base, UUIDMixin
class UsageSample(UUIDMixin, Base):
"""
Aggregated usage statistics for an instance.
PRIVACY: This model deliberately has NO fields for:
- Environment values
- File contents
- Request/response payloads
- Screenshots
- Credentials
- Error messages or stack traces
Only metadata fields are allowed.
"""
__tablename__ = "usage_samples"
# Instance reference
instance_id: Mapped[UUID] = mapped_column(
ForeignKey("instances.id", ondelete="CASCADE"),
nullable=False,
index=True,
)
# Time window
window_start: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
)
window_end: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
)
window_type: Mapped[str] = mapped_column(
String(20),
nullable=False,
)
# "minute", "hour", "day"
# Tool (ONLY name, never payloads)
tool_name: Mapped[str] = mapped_column(
String(255),
nullable=False,
index=True,
)
# e.g., "sysadmin.env_update"
# Counts (aggregated)
call_count: Mapped[int] = mapped_column(Integer, default=0)
success_count: Mapped[int] = mapped_column(Integer, default=0)
error_count: Mapped[int] = mapped_column(Integer, default=0)
rate_limited_count: Mapped[int] = mapped_column(Integer, default=0)
# Duration stats (milliseconds)
total_duration_ms: Mapped[int] = mapped_column(Integer, default=0)
min_duration_ms: Mapped[int] = mapped_column(Integer, default=0)
max_duration_ms: Mapped[int] = mapped_column(Integer, default=0)