print_log.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. """Service for writing independent print log entries.
  2. Log entries are written to a separate table and never touch archives or queue items.
  3. """
  4. import logging
  5. from datetime import datetime
  6. from sqlalchemy.ext.asyncio import AsyncSession
  7. from backend.app.models.print_log import PrintLogEntry
  8. logger = logging.getLogger(__name__)
  9. async def write_log_entry(
  10. db: AsyncSession,
  11. *,
  12. status: str,
  13. archive_id: int | None = None,
  14. queue_item_id: int | None = None,
  15. print_name: str | None = None,
  16. printer_name: str | None = None,
  17. printer_id: int | None = None,
  18. started_at: datetime | None = None,
  19. completed_at: datetime | None = None,
  20. filament_type: str | None = None,
  21. filament_color: str | None = None,
  22. filament_used_grams: float | None = None,
  23. cost: float | None = None,
  24. energy_kwh: float | None = None,
  25. energy_cost: float | None = None,
  26. failure_reason: str | None = None,
  27. thumbnail_path: str | None = None,
  28. created_by_id: int | None = None,
  29. created_by_username: str | None = None,
  30. reconciled: bool = False,
  31. ) -> PrintLogEntry:
  32. """Write a print log entry.
  33. ``reconciled`` marks a synthetic completion written when a stale
  34. ``status="printing"`` archive is closed out at reconnect. Its real end time
  35. is unknown — the print stopped somewhere during the disconnect and
  36. ``completed_at`` is only the reconnect moment — so ``completed_at -
  37. started_at`` would bank the entire disconnect gap as print time, adding
  38. hundreds of fictitious hours across a farm of stale rows (#2592). For those
  39. entries we store an explicit ``0`` ("no measured runtime") rather than a
  40. fabricated duration; the stats total trusts a stored 0 instead of
  41. recomputing from the stale timestamps.
  42. """
  43. if reconciled:
  44. duration: int | None = 0
  45. elif started_at and completed_at:
  46. duration = int((completed_at - started_at).total_seconds())
  47. else:
  48. duration = None
  49. entry = PrintLogEntry(
  50. archive_id=archive_id,
  51. queue_item_id=queue_item_id,
  52. print_name=print_name,
  53. printer_name=printer_name,
  54. printer_id=printer_id,
  55. status=status,
  56. started_at=started_at,
  57. completed_at=completed_at,
  58. duration_seconds=duration,
  59. filament_type=filament_type,
  60. filament_color=filament_color,
  61. filament_used_grams=filament_used_grams,
  62. cost=cost,
  63. energy_kwh=energy_kwh,
  64. energy_cost=energy_cost,
  65. failure_reason=failure_reason,
  66. thumbnail_path=thumbnail_path,
  67. created_by_id=created_by_id,
  68. created_by_username=created_by_username,
  69. )
  70. db.add(entry)
  71. await db.flush()
  72. return entry