mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-10-30 10:20:30 +03:00
adapt analytics to free-form model scenes, split notice counts, and peewee 4
This commit is contained in:
+35
-25
@@ -373,6 +373,7 @@
|
|||||||
"intel-qsv",
|
"intel-qsv",
|
||||||
"jetson",
|
"jetson",
|
||||||
"rpi",
|
"rpi",
|
||||||
|
"apple-silicon",
|
||||||
"other"
|
"other"
|
||||||
],
|
],
|
||||||
"title": "DecodeFamily",
|
"title": "DecodeFamily",
|
||||||
@@ -381,6 +382,12 @@
|
|||||||
"DetectionModel": {
|
"DetectionModel": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"default": {
|
||||||
|
"description": "Whether the model serves cameras that set no scene",
|
||||||
|
"title": "Default",
|
||||||
|
"type": "boolean",
|
||||||
|
"x-public": true
|
||||||
|
},
|
||||||
"detector": {
|
"detector": {
|
||||||
"$ref": "#/$defs/DetectorTypeEnum",
|
"$ref": "#/$defs/DetectorTypeEnum",
|
||||||
"description": "Detector type the model runs on",
|
"description": "Detector type the model runs on",
|
||||||
@@ -396,7 +403,7 @@
|
|||||||
"inference_ms": {
|
"inference_ms": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"minimum": 0.0,
|
"minimum": 0,
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -426,6 +433,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
"default",
|
||||||
"detector",
|
"detector",
|
||||||
"devices",
|
"devices",
|
||||||
"model_type",
|
"model_type",
|
||||||
@@ -441,26 +449,23 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"detection_fps": {
|
"detection_fps": {
|
||||||
"description": "Detections per second across cameras",
|
"description": "Detections per second across cameras",
|
||||||
"minimum": 0.0,
|
"minimum": 0,
|
||||||
"title": "Detection Fps",
|
"title": "Detection Fps",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"x-public": true
|
"x-public": true
|
||||||
},
|
},
|
||||||
"models": {
|
"models": {
|
||||||
"additionalProperties": {
|
"description": "Detection models",
|
||||||
|
"items": {
|
||||||
"$ref": "#/$defs/DetectionModel"
|
"$ref": "#/$defs/DetectionModel"
|
||||||
},
|
},
|
||||||
"description": "Detection models keyed by scene",
|
|
||||||
"propertyNames": {
|
|
||||||
"$ref": "#/$defs/SceneEnum"
|
|
||||||
},
|
|
||||||
"title": "Models",
|
"title": "Models",
|
||||||
"type": "object",
|
"type": "array",
|
||||||
"x-public": true
|
"x-public": true
|
||||||
},
|
},
|
||||||
"skipped_fps": {
|
"skipped_fps": {
|
||||||
"description": "Frames per second skipped across cameras",
|
"description": "Frames per second skipped across cameras",
|
||||||
"minimum": 0.0,
|
"minimum": 0,
|
||||||
"title": "Skipped Fps",
|
"title": "Skipped Fps",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"x-public": true
|
"x-public": true
|
||||||
@@ -476,6 +481,7 @@
|
|||||||
},
|
},
|
||||||
"DetectorTypeEnum": {
|
"DetectorTypeEnum": {
|
||||||
"enum": [
|
"enum": [
|
||||||
|
"axelera",
|
||||||
"axengine",
|
"axengine",
|
||||||
"cpu",
|
"cpu",
|
||||||
"deepx",
|
"deepx",
|
||||||
@@ -772,6 +778,7 @@
|
|||||||
"nvidia",
|
"nvidia",
|
||||||
"rockchip",
|
"rockchip",
|
||||||
"rpi",
|
"rpi",
|
||||||
|
"apple-silicon",
|
||||||
"other"
|
"other"
|
||||||
],
|
],
|
||||||
"title": "GpuVendor",
|
"title": "GpuVendor",
|
||||||
@@ -785,12 +792,14 @@
|
|||||||
"openvino:NPU",
|
"openvino:NPU",
|
||||||
"onnx:amd",
|
"onnx:amd",
|
||||||
"onnx:nvidia",
|
"onnx:nvidia",
|
||||||
|
"onnx:lighter",
|
||||||
"tensorrt",
|
"tensorrt",
|
||||||
"hailo",
|
"hailo",
|
||||||
"memryx",
|
"memryx",
|
||||||
"deepx",
|
"deepx",
|
||||||
"rknn",
|
"rknn",
|
||||||
"axengine",
|
"axengine",
|
||||||
|
"axelera",
|
||||||
"synaptics",
|
"synaptics",
|
||||||
"cpu",
|
"cpu",
|
||||||
"other"
|
"other"
|
||||||
@@ -945,6 +954,8 @@
|
|||||||
"enum": [
|
"enum": [
|
||||||
"rpi-64-h264",
|
"rpi-64-h264",
|
||||||
"rpi-64-h265",
|
"rpi-64-h265",
|
||||||
|
"apple-silicon-h264",
|
||||||
|
"apple-silicon-h265",
|
||||||
"vaapi",
|
"vaapi",
|
||||||
"intel-qsv-h264",
|
"intel-qsv-h264",
|
||||||
"intel-qsv-h265",
|
"intel-qsv-h265",
|
||||||
@@ -1091,10 +1102,17 @@
|
|||||||
"NoticeCounts": {
|
"NoticeCounts": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
"dismissals": {
|
"acknowledgements": {
|
||||||
"description": "Dismissals since the last accepted report",
|
"description": "Acknowledgements since the last accepted report",
|
||||||
"minimum": 0,
|
"minimum": 0,
|
||||||
"title": "Dismissals",
|
"title": "Acknowledgements",
|
||||||
|
"type": "integer",
|
||||||
|
"x-public": true
|
||||||
|
},
|
||||||
|
"mutes": {
|
||||||
|
"description": "Mutes since the last accepted report",
|
||||||
|
"minimum": 0,
|
||||||
|
"title": "Mutes",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"x-public": true
|
"x-public": true
|
||||||
},
|
},
|
||||||
@@ -1108,7 +1126,8 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"occurrences",
|
"occurrences",
|
||||||
"dismissals"
|
"acknowledgements",
|
||||||
|
"mutes"
|
||||||
],
|
],
|
||||||
"title": "NoticeCounts",
|
"title": "NoticeCounts",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
@@ -1118,7 +1137,10 @@
|
|||||||
"detector_stuck",
|
"detector_stuck",
|
||||||
"model_download_failed",
|
"model_download_failed",
|
||||||
"skipped_detections",
|
"skipped_detections",
|
||||||
|
"ffmpeg_high_cpu",
|
||||||
|
"detect_high_cpu",
|
||||||
"shm_too_low",
|
"shm_too_low",
|
||||||
|
"object_processing_behind",
|
||||||
"failed_login"
|
"failed_login"
|
||||||
],
|
],
|
||||||
"title": "NoticeKindKey",
|
"title": "NoticeKindKey",
|
||||||
@@ -1195,18 +1217,6 @@
|
|||||||
"title": "RetainDays",
|
"title": "RetainDays",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"SceneEnum": {
|
|
||||||
"description": "The camera environment a detection model is intended for.",
|
|
||||||
"enum": [
|
|
||||||
"all",
|
|
||||||
"indoor",
|
|
||||||
"outdoor",
|
|
||||||
"indoor_thermal",
|
|
||||||
"outdoor_thermal"
|
|
||||||
],
|
|
||||||
"title": "SceneEnum",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"SemanticSearchModel": {
|
"SemanticSearchModel": {
|
||||||
"enum": [
|
"enum": [
|
||||||
"jinav1",
|
"jinav1",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from frigate.analytics.context import ReportContext
|
|||||||
from frigate.analytics.schema import DetectionModel, DetectionSection, ModelSource
|
from frigate.analytics.schema import DetectionModel, DetectionSection, ModelSource
|
||||||
from frigate.config.config import DEFAULT_MODEL
|
from frigate.config.config import DEFAULT_MODEL
|
||||||
from frigate.const import MODEL_CACHE_DIR
|
from frigate.const import MODEL_CACHE_DIR
|
||||||
from frigate.detectors.detector_config import SceneEnum
|
from frigate.detectors.detector_config import DEFAULT_SCENE
|
||||||
from frigate.detectors.detector_types import DetectorTypeEnum
|
from frigate.detectors.detector_types import DetectorTypeEnum
|
||||||
from frigate.detectors.device import runner_names
|
from frigate.detectors.device import runner_names
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ def collect(ctx: ReportContext) -> DetectionSection:
|
|||||||
|
|
||||||
# FrigateApp.start_detectors names the processes in this same order
|
# FrigateApp.start_detectors names the processes in this same order
|
||||||
names = iter(runner_names([spec for _, specs in model_specs for spec in specs]))
|
names = iter(runner_names([spec for _, specs in model_specs for spec in specs]))
|
||||||
models: dict[SceneEnum, DetectionModel] = {}
|
models: list[DetectionModel] = []
|
||||||
|
|
||||||
for model, specs in model_specs:
|
for model, specs in model_specs:
|
||||||
speeds: list[float] = []
|
speeds: list[float] = []
|
||||||
@@ -49,13 +49,16 @@ def collect(ctx: ReportContext) -> DetectionSection:
|
|||||||
if isinstance(speed, int | float) and speed > 0:
|
if isinstance(speed, int | float) and speed > 0:
|
||||||
speeds.append(float(speed))
|
speeds.append(float(speed))
|
||||||
|
|
||||||
models[model.scene] = DetectionModel(
|
models.append(
|
||||||
detector=DetectorTypeEnum(specs[0].detector),
|
DetectionModel(
|
||||||
devices=len(specs),
|
default=model.scene == DEFAULT_SCENE,
|
||||||
model_type=model.model_type,
|
detector=DetectorTypeEnum(specs[0].detector),
|
||||||
input=f"{model.width}x{model.height}",
|
devices=len(specs),
|
||||||
source=model_source(model.path),
|
model_type=model.model_type,
|
||||||
inference_ms=rate(sum(speeds) / len(speeds)) if speeds else None,
|
input=f"{model.width}x{model.height}",
|
||||||
|
source=model_source(model.path),
|
||||||
|
inference_ms=rate(sum(speeds) / len(speeds)) if speeds else None,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
return DetectionSection(
|
return DetectionSection(
|
||||||
|
|||||||
@@ -32,11 +32,14 @@ def notice_deltas(notice_stats: list[dict[str, Any]]) -> dict[Any, NoticeCounts]
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
occurrences = max(row["occurrences"] - row["reported_occurrences"], 0)
|
occurrences = max(row["occurrences"] - row["reported_occurrences"], 0)
|
||||||
dismissals = max(row["dismissals"] - row["reported_dismissals"], 0)
|
acknowledgements = max(
|
||||||
|
row["acknowledgements"] - row["reported_acknowledgements"], 0
|
||||||
|
)
|
||||||
|
mutes = max(row["mutes"] - row["reported_mutes"], 0)
|
||||||
|
|
||||||
if occurrences or dismissals:
|
if occurrences or acknowledgements or mutes:
|
||||||
deltas[NoticeKindKey(row["kind"])] = NoticeCounts(
|
deltas[NoticeKindKey(row["kind"])] = NoticeCounts(
|
||||||
occurrences=occurrences, dismissals=dismissals
|
occurrences=occurrences, acknowledgements=acknowledgements, mutes=mutes
|
||||||
)
|
)
|
||||||
|
|
||||||
return deltas
|
return deltas
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from frigate.config.camera.birdseye import BirdseyeModeEnum
|
|||||||
from frigate.config.camera.camera import CameraTypeEnum
|
from frigate.config.camera.camera import CameraTypeEnum
|
||||||
from frigate.config.camera.genai import GenAIProviderEnum, GenAIRoleEnum
|
from frigate.config.camera.genai import GenAIProviderEnum, GenAIRoleEnum
|
||||||
from frigate.config.classification import ModelSizeEnum
|
from frigate.config.classification import ModelSizeEnum
|
||||||
from frigate.detectors.detector_config import ModelTypeEnum, SceneEnum
|
from frigate.detectors.detector_config import ModelTypeEnum
|
||||||
from frigate.detectors.detector_types import DetectorTypeEnum
|
from frigate.detectors.detector_types import DetectorTypeEnum
|
||||||
from frigate.ffmpeg_presets import PRESETS_HW_ACCEL_DECODE, PRESETS_INPUT
|
from frigate.ffmpeg_presets import PRESETS_HW_ACCEL_DECODE, PRESETS_INPUT
|
||||||
from frigate.notices.types import NOTICE_KINDS
|
from frigate.notices.types import NOTICE_KINDS
|
||||||
@@ -53,6 +53,7 @@ class GpuVendor(StrEnum):
|
|||||||
nvidia = "nvidia"
|
nvidia = "nvidia"
|
||||||
rockchip = "rockchip"
|
rockchip = "rockchip"
|
||||||
rpi = "rpi"
|
rpi = "rpi"
|
||||||
|
apple_silicon = "apple-silicon"
|
||||||
other = "other"
|
other = "other"
|
||||||
|
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ class DecodeFamily(StrEnum):
|
|||||||
intel_qsv = "intel-qsv"
|
intel_qsv = "intel-qsv"
|
||||||
jetson = "jetson"
|
jetson = "jetson"
|
||||||
rpi = "rpi"
|
rpi = "rpi"
|
||||||
|
apple_silicon = "apple-silicon"
|
||||||
other = "other"
|
other = "other"
|
||||||
|
|
||||||
|
|
||||||
@@ -73,12 +75,14 @@ class HardwareKey(StrEnum):
|
|||||||
openvino_npu = "openvino:NPU"
|
openvino_npu = "openvino:NPU"
|
||||||
onnx_amd = "onnx:amd"
|
onnx_amd = "onnx:amd"
|
||||||
onnx_nvidia = "onnx:nvidia"
|
onnx_nvidia = "onnx:nvidia"
|
||||||
|
onnx_lighter = "onnx:lighter"
|
||||||
tensorrt = "tensorrt"
|
tensorrt = "tensorrt"
|
||||||
hailo = "hailo"
|
hailo = "hailo"
|
||||||
memryx = "memryx"
|
memryx = "memryx"
|
||||||
deepx = "deepx"
|
deepx = "deepx"
|
||||||
rknn = "rknn"
|
rknn = "rknn"
|
||||||
axengine = "axengine"
|
axengine = "axengine"
|
||||||
|
axelera = "axelera"
|
||||||
synaptics = "synaptics"
|
synaptics = "synaptics"
|
||||||
cpu = "cpu"
|
cpu = "cpu"
|
||||||
other = "other"
|
other = "other"
|
||||||
@@ -228,6 +232,7 @@ class HardwareSection(AnalyticsModel):
|
|||||||
|
|
||||||
|
|
||||||
class DetectionModel(AnalyticsModel):
|
class DetectionModel(AnalyticsModel):
|
||||||
|
default: bool = metric("Whether the model serves cameras that set no scene")
|
||||||
detector: DetectorTypeEnum = metric("Detector type the model runs on")
|
detector: DetectorTypeEnum = metric("Detector type the model runs on")
|
||||||
devices: int = count("Devices the model runs on")
|
devices: int = count("Devices the model runs on")
|
||||||
model_type: ModelTypeEnum = metric("Model architecture")
|
model_type: ModelTypeEnum = metric("Model architecture")
|
||||||
@@ -240,7 +245,7 @@ class DetectionModel(AnalyticsModel):
|
|||||||
|
|
||||||
|
|
||||||
class DetectionSection(AnalyticsModel):
|
class DetectionSection(AnalyticsModel):
|
||||||
models: dict[SceneEnum, DetectionModel] = metric("Detection models keyed by scene")
|
models: list[DetectionModel] = metric("Detection models")
|
||||||
detection_fps: float = metric("Detections per second across cameras", ge=0)
|
detection_fps: float = metric("Detections per second across cameras", ge=0)
|
||||||
skipped_fps: float = metric("Frames per second skipped across cameras", ge=0)
|
skipped_fps: float = metric("Frames per second skipped across cameras", ge=0)
|
||||||
|
|
||||||
@@ -369,7 +374,8 @@ class FeaturesSection(AnalyticsModel):
|
|||||||
|
|
||||||
class NoticeCounts(AnalyticsModel):
|
class NoticeCounts(AnalyticsModel):
|
||||||
occurrences: int = count("Occurrences since the last accepted report")
|
occurrences: int = count("Occurrences since the last accepted report")
|
||||||
dismissals: int = count("Dismissals since the last accepted report")
|
acknowledgements: int = count("Acknowledgements since the last accepted report")
|
||||||
|
mutes: int = count("Mutes since the last accepted report")
|
||||||
|
|
||||||
|
|
||||||
class HealthSection(AnalyticsModel):
|
class HealthSection(AnalyticsModel):
|
||||||
|
|||||||
+1
-1
@@ -209,7 +209,7 @@ class NoticeStats(Model):
|
|||||||
mutes = IntegerField(default=0)
|
mutes = IntegerField(default=0)
|
||||||
first_seen = DateTimeField()
|
first_seen = DateTimeField()
|
||||||
last_seen = DateTimeField()
|
last_seen = DateTimeField()
|
||||||
# watermarks for a future analytics reporter; unused until then
|
# counts the last accepted analytics report covered
|
||||||
reported_occurrences = IntegerField(default=0)
|
reported_occurrences = IntegerField(default=0)
|
||||||
reported_acknowledgements = IntegerField(default=0)
|
reported_acknowledgements = IntegerField(default=0)
|
||||||
reported_mutes = IntegerField(default=0)
|
reported_mutes = IntegerField(default=0)
|
||||||
|
|||||||
@@ -395,7 +395,8 @@ class NoticeRegistry:
|
|||||||
for row in snapshot:
|
for row in snapshot:
|
||||||
NoticeStats.update(
|
NoticeStats.update(
|
||||||
reported_occurrences=row["occurrences"],
|
reported_occurrences=row["occurrences"],
|
||||||
reported_dismissals=row["dismissals"],
|
reported_acknowledgements=row["acknowledgements"],
|
||||||
|
reported_mutes=row["mutes"],
|
||||||
).where(NoticeStats.kind == row["kind"]).execute()
|
).where(NoticeStats.kind == row["kind"]).execute()
|
||||||
|
|
||||||
def _write_repeats(
|
def _write_repeats(
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ from unittest.mock import patch
|
|||||||
|
|
||||||
from frigate.analytics.collectors import detection
|
from frigate.analytics.collectors import detection
|
||||||
from frigate.analytics.schema import ModelSource
|
from frigate.analytics.schema import ModelSource
|
||||||
from frigate.detectors.detector_config import SceneEnum
|
|
||||||
from frigate.test.analytics_helpers import make_config, make_context
|
from frigate.test.analytics_helpers import make_config, make_context
|
||||||
|
|
||||||
|
|
||||||
@@ -25,7 +24,8 @@ class TestDetectionCollector(unittest.TestCase):
|
|||||||
|
|
||||||
section = detection.collect(make_context(config, stats))
|
section = detection.collect(make_context(config, stats))
|
||||||
|
|
||||||
model = section.models[SceneEnum.all]
|
[model] = section.models
|
||||||
|
self.assertTrue(model.default)
|
||||||
self.assertEqual(model.detector, "cpu")
|
self.assertEqual(model.detector, "cpu")
|
||||||
self.assertEqual(model.devices, 2)
|
self.assertEqual(model.devices, 2)
|
||||||
self.assertEqual(model.model_type, "ssd")
|
self.assertEqual(model.model_type, "ssd")
|
||||||
@@ -35,10 +35,29 @@ class TestDetectionCollector(unittest.TestCase):
|
|||||||
self.assertEqual(section.detection_fps, 12.35)
|
self.assertEqual(section.detection_fps, 12.35)
|
||||||
self.assertEqual(section.skipped_fps, 0.0)
|
self.assertEqual(section.skipped_fps, 0.0)
|
||||||
|
|
||||||
|
def test_named_scene_reports_no_name(self):
|
||||||
|
config = make_config(
|
||||||
|
{
|
||||||
|
"models": [
|
||||||
|
{"devices": ["cpu"]},
|
||||||
|
{
|
||||||
|
"scene": "backyard_thermal",
|
||||||
|
"devices": ["cpu"],
|
||||||
|
"path": "/thermal.tflite",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
section = detection.collect(make_context(config))
|
||||||
|
|
||||||
|
self.assertEqual([m.default for m in section.models], [True, False])
|
||||||
|
self.assertNotIn("backyard_thermal", section.model_dump_json())
|
||||||
|
|
||||||
def test_inference_is_null_before_the_first_stats(self):
|
def test_inference_is_null_before_the_first_stats(self):
|
||||||
section = detection.collect(make_context())
|
section = detection.collect(make_context())
|
||||||
|
|
||||||
self.assertIsNone(section.models[SceneEnum.all].inference_ms)
|
self.assertIsNone(section.models[0].inference_ms)
|
||||||
|
|
||||||
def test_model_source(self):
|
def test_model_source(self):
|
||||||
with tempfile.TemporaryDirectory() as cache:
|
with tempfile.TemporaryDirectory() as cache:
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
from peewee import SqliteDatabase
|
||||||
from peewee_migrate import Router
|
from peewee_migrate import Router
|
||||||
from playhouse.sqlite_ext import SqliteExtDatabase
|
|
||||||
from playhouse.sqliteq import SqliteQueueDatabase
|
from playhouse.sqliteq import SqliteQueueDatabase
|
||||||
|
|
||||||
from frigate.analytics.collectors import features
|
from frigate.analytics.collectors import features
|
||||||
@@ -49,7 +49,7 @@ CONFIG = {
|
|||||||
|
|
||||||
class TestFeaturesCollector(unittest.TestCase):
|
class TestFeaturesCollector(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
migrate_db = SqliteExtDatabase(TEST_DB)
|
migrate_db = SqliteDatabase(TEST_DB)
|
||||||
del logging.getLogger("peewee_migrate").handlers[:]
|
del logging.getLogger("peewee_migrate").handlers[:]
|
||||||
Router(migrate_db).run()
|
Router(migrate_db).run()
|
||||||
migrate_db.close()
|
migrate_db.close()
|
||||||
|
|||||||
@@ -21,23 +21,29 @@ class TestHealthCollector(unittest.TestCase):
|
|||||||
{
|
{
|
||||||
"kind": "detector_stuck",
|
"kind": "detector_stuck",
|
||||||
"occurrences": 5,
|
"occurrences": 5,
|
||||||
"dismissals": 1,
|
"acknowledgements": 1,
|
||||||
|
"mutes": 0,
|
||||||
"reported_occurrences": 3,
|
"reported_occurrences": 3,
|
||||||
"reported_dismissals": 1,
|
"reported_acknowledgements": 1,
|
||||||
|
"reported_mutes": 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "shm_too_low",
|
"kind": "shm_too_low",
|
||||||
"occurrences": 2,
|
"occurrences": 2,
|
||||||
"dismissals": 0,
|
"acknowledgements": 0,
|
||||||
|
"mutes": 0,
|
||||||
"reported_occurrences": 2,
|
"reported_occurrences": 2,
|
||||||
"reported_dismissals": 0,
|
"reported_acknowledgements": 0,
|
||||||
|
"reported_mutes": 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "update_available",
|
"kind": "update_available",
|
||||||
"occurrences": 4,
|
"occurrences": 4,
|
||||||
"dismissals": 0,
|
"acknowledgements": 0,
|
||||||
|
"mutes": 0,
|
||||||
"reported_occurrences": 0,
|
"reported_occurrences": 0,
|
||||||
"reported_dismissals": 0,
|
"reported_acknowledgements": 0,
|
||||||
|
"reported_mutes": 0,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -49,10 +55,10 @@ class TestHealthCollector(unittest.TestCase):
|
|||||||
self.assertTrue(section.retention_unmet)
|
self.assertTrue(section.retention_unmet)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
{
|
{
|
||||||
kind: (c.occurrences, c.dismissals)
|
kind: (c.occurrences, c.acknowledgements, c.mutes)
|
||||||
for kind, c in section.notices.items()
|
for kind, c in section.notices.items()
|
||||||
},
|
},
|
||||||
{"detector_stuck": (2, 0)},
|
{"detector_stuck": (2, 0, 0)},
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_missing_stats_give_zeros(self):
|
def test_missing_stats_give_zeros(self):
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import os
|
|||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import Mock, patch
|
from unittest.mock import Mock, patch
|
||||||
|
|
||||||
|
from peewee import SqliteDatabase
|
||||||
from peewee_migrate import Router
|
from peewee_migrate import Router
|
||||||
from playhouse.sqlite_ext import SqliteExtDatabase
|
|
||||||
from playhouse.sqliteq import SqliteQueueDatabase
|
from playhouse.sqliteq import SqliteQueueDatabase
|
||||||
|
|
||||||
from frigate.analytics import report
|
from frigate.analytics import report
|
||||||
@@ -50,7 +50,7 @@ class TestBuildReport(unittest.TestCase):
|
|||||||
|
|
||||||
class TestRealCollectors(unittest.TestCase):
|
class TestRealCollectors(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
migrate_db = SqliteExtDatabase(TEST_DB)
|
migrate_db = SqliteDatabase(TEST_DB)
|
||||||
del logging.getLogger("peewee_migrate").handlers[:]
|
del logging.getLogger("peewee_migrate").handlers[:]
|
||||||
Router(migrate_db).run()
|
Router(migrate_db).run()
|
||||||
migrate_db.close()
|
migrate_db.close()
|
||||||
|
|||||||
@@ -24,9 +24,11 @@ SNAPSHOT = [
|
|||||||
{
|
{
|
||||||
"kind": "detector_stuck",
|
"kind": "detector_stuck",
|
||||||
"occurrences": 3,
|
"occurrences": 3,
|
||||||
"dismissals": 0,
|
"acknowledgements": 0,
|
||||||
|
"mutes": 0,
|
||||||
"reported_occurrences": 1,
|
"reported_occurrences": 1,
|
||||||
"reported_dismissals": 0,
|
"reported_acknowledgements": 0,
|
||||||
|
"reported_mutes": 0,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -372,7 +372,8 @@ class TestMarkReported(RegistryTestCase):
|
|||||||
row = self.registry.stats()[0]
|
row = self.registry.stats()[0]
|
||||||
self.assertEqual(row["occurrences"], 2)
|
self.assertEqual(row["occurrences"], 2)
|
||||||
self.assertEqual(row["reported_occurrences"], 1)
|
self.assertEqual(row["reported_occurrences"], 1)
|
||||||
self.assertEqual(row["reported_dismissals"], 0)
|
self.assertEqual(row["reported_acknowledgements"], 0)
|
||||||
|
self.assertEqual(row["reported_mutes"], 0)
|
||||||
|
|
||||||
|
|
||||||
class TestApply(RegistryTestCase):
|
class TestApply(RegistryTestCase):
|
||||||
|
|||||||
Reference in New Issue
Block a user