stats.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import json
  2. import logging
  3. import threading
  4. import time
  5. import psutil
  6. import shutil
  7. from frigate.config import FrigateConfig
  8. from frigate.const import RECORD_DIR, CLIPS_DIR, CACHE_DIR
  9. from frigate.version import VERSION
  10. logger = logging.getLogger(__name__)
  11. def stats_init(camera_metrics, detectors):
  12. stats_tracking = {
  13. "camera_metrics": camera_metrics,
  14. "detectors": detectors,
  15. "started": int(time.time()),
  16. }
  17. return stats_tracking
  18. def get_fs_type(path):
  19. bestMatch = ""
  20. fsType = ""
  21. for part in psutil.disk_partitions(all=True):
  22. if path.startswith(part.mountpoint) and len(bestMatch) < len(part.mountpoint):
  23. fsType = part.fstype
  24. bestMatch = part.mountpoint
  25. return fsType
  26. def stats_snapshot(stats_tracking):
  27. camera_metrics = stats_tracking["camera_metrics"]
  28. stats = {}
  29. total_detection_fps = 0
  30. for name, camera_stats in camera_metrics.items():
  31. total_detection_fps += camera_stats["detection_fps"].value
  32. stats[name] = {
  33. "camera_fps": round(camera_stats["camera_fps"].value, 2),
  34. "process_fps": round(camera_stats["process_fps"].value, 2),
  35. "skipped_fps": round(camera_stats["skipped_fps"].value, 2),
  36. "detection_fps": round(camera_stats["detection_fps"].value, 2),
  37. "pid": camera_stats["process"].pid,
  38. "capture_pid": camera_stats["capture_process"].pid,
  39. }
  40. stats["detectors"] = {}
  41. for name, detector in stats_tracking["detectors"].items():
  42. stats["detectors"][name] = {
  43. "inference_speed": round(detector.avg_inference_speed.value * 1000, 2),
  44. "detection_start": detector.detection_start.value,
  45. "pid": detector.detect_process.pid,
  46. }
  47. stats["detection_fps"] = round(total_detection_fps, 2)
  48. stats["service"] = {
  49. "uptime": (int(time.time()) - stats_tracking["started"]),
  50. "version": VERSION,
  51. "storage": {},
  52. }
  53. for path in [RECORD_DIR, CLIPS_DIR, CACHE_DIR, "/dev/shm"]:
  54. storage_stats = shutil.disk_usage(path)
  55. stats["service"]["storage"][path] = {
  56. "total": round(storage_stats.total / 1000000, 1),
  57. "used": round(storage_stats.used / 1000000, 1),
  58. "free": round(storage_stats.free / 1000000, 1),
  59. "mount_type": get_fs_type(path),
  60. }
  61. return stats
  62. class StatsEmitter(threading.Thread):
  63. def __init__(
  64. self,
  65. config: FrigateConfig,
  66. stats_tracking,
  67. mqtt_client,
  68. topic_prefix,
  69. stop_event,
  70. ):
  71. threading.Thread.__init__(self)
  72. self.name = "frigate_stats_emitter"
  73. self.config = config
  74. self.stats_tracking = stats_tracking
  75. self.mqtt_client = mqtt_client
  76. self.topic_prefix = topic_prefix
  77. self.stop_event = stop_event
  78. def run(self):
  79. time.sleep(10)
  80. while not self.stop_event.wait(self.config.mqtt.stats_interval):
  81. stats = stats_snapshot(self.stats_tracking)
  82. self.mqtt_client.publish(
  83. f"{self.topic_prefix}/stats", json.dumps(stats), retain=False
  84. )
  85. logger.info(f"Exiting watchdog...")