mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-29 19:36:57 +03:00
Add analytics opt-in setting, prompt notice kind, and notice watermarks
This commit is contained in:
@@ -29,6 +29,11 @@ class StatsConfig(FrigateBaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class TelemetryConfig(FrigateBaseModel):
|
class TelemetryConfig(FrigateBaseModel):
|
||||||
|
analytics: bool = Field(
|
||||||
|
default=False,
|
||||||
|
title="Share anonymous analytics",
|
||||||
|
description="Send one anonymous usage report a day to help the Frigate maintainers decide what to support. Nothing is sent until this is on.",
|
||||||
|
)
|
||||||
network_interfaces: list[str] = Field(
|
network_interfaces: list[str] = Field(
|
||||||
default=[],
|
default=[],
|
||||||
title="Network interfaces",
|
title="Network interfaces",
|
||||||
|
|||||||
@@ -319,6 +319,19 @@ class NoticeRegistry:
|
|||||||
if row.kind in NOTICE_KINDS
|
if row.kind in NOTICE_KINDS
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def mark_reported(self, snapshot: list[dict[str, Any]]) -> None:
|
||||||
|
"""Move the analytics watermarks to the counts a sent report was built from.
|
||||||
|
|
||||||
|
Using the snapshot rather than the current counts sends anything raised
|
||||||
|
while the report was in flight with the next one.
|
||||||
|
"""
|
||||||
|
with self._lock:
|
||||||
|
for row in snapshot:
|
||||||
|
NoticeStats.update(
|
||||||
|
reported_occurrences=row["occurrences"],
|
||||||
|
reported_dismissals=row["dismissals"],
|
||||||
|
).where(NoticeStats.kind == row["kind"]).execute()
|
||||||
|
|
||||||
def _write_repeats(
|
def _write_repeats(
|
||||||
self,
|
self,
|
||||||
row: Notice,
|
row: Notice,
|
||||||
|
|||||||
@@ -86,6 +86,16 @@ _KINDS = (
|
|||||||
link="https://github.com/blakeblackshear/frigate/releases/tag/v{version}",
|
link="https://github.com/blakeblackshear/frigate/releases/tag/v{version}",
|
||||||
counts_repeats=False,
|
counts_repeats=False,
|
||||||
keep_latest=1,
|
keep_latest=1,
|
||||||
|
reportable=False,
|
||||||
|
),
|
||||||
|
# raised while analytics is off; the row keeps a dismissal across restarts
|
||||||
|
NoticeKind(
|
||||||
|
"analytics_prompt",
|
||||||
|
NoticeSeverity.info,
|
||||||
|
"system",
|
||||||
|
link="/settings?page=systemTelemetry",
|
||||||
|
counts_repeats=False,
|
||||||
|
reportable=False,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ from frigate.util.builtin import deep_merge
|
|||||||
|
|
||||||
|
|
||||||
class TestConfig(unittest.TestCase):
|
class TestConfig(unittest.TestCase):
|
||||||
|
def test_analytics_is_off_by_default(self):
|
||||||
|
frigate_config = FrigateConfig(**self.minimal)
|
||||||
|
|
||||||
|
self.assertFalse(frigate_config.telemetry.analytics)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.minimal = {
|
self.minimal = {
|
||||||
"mqtt": {"host": "mqtt"},
|
"mqtt": {"host": "mqtt"},
|
||||||
|
|||||||
@@ -48,6 +48,16 @@ class TestNoticeKinds(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertIsNone(kind.link_for({"version": "0.19.1"}))
|
self.assertIsNone(kind.link_for({"version": "0.19.1"}))
|
||||||
|
|
||||||
|
def test_analytics_prompt_links_to_telemetry_settings(self):
|
||||||
|
kind = NOTICE_KINDS["analytics_prompt"]
|
||||||
|
|
||||||
|
self.assertEqual(kind.link_for({}), "/settings?page=systemTelemetry")
|
||||||
|
self.assertFalse(kind.counts_repeats)
|
||||||
|
self.assertFalse(kind.reportable)
|
||||||
|
|
||||||
|
def test_update_available_is_not_reported(self):
|
||||||
|
self.assertFalse(NOTICE_KINDS["update_available"].reportable)
|
||||||
|
|
||||||
|
|
||||||
class RegistryTestCase(unittest.TestCase):
|
class RegistryTestCase(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -278,6 +288,24 @@ class TestNoticeRegistry(RegistryTestCase):
|
|||||||
self.assertEqual(dismissals["detector_stuck"], 1)
|
self.assertEqual(dismissals["detector_stuck"], 1)
|
||||||
|
|
||||||
|
|
||||||
|
class TestMarkReported(RegistryTestCase):
|
||||||
|
def test_moves_watermarks_to_the_snapshot_not_the_current_count(self):
|
||||||
|
self.registry.raise_notice(
|
||||||
|
"detector_stuck", scope="ov", params={"detector": "ov"}
|
||||||
|
)
|
||||||
|
snapshot = self.registry.stats()
|
||||||
|
self.registry.raise_notice(
|
||||||
|
"detector_stuck", scope="ov", params={"detector": "ov"}
|
||||||
|
)
|
||||||
|
|
||||||
|
self.registry.mark_reported(snapshot)
|
||||||
|
|
||||||
|
row = self.registry.stats()[0]
|
||||||
|
self.assertEqual(row["occurrences"], 2)
|
||||||
|
self.assertEqual(row["reported_occurrences"], 1)
|
||||||
|
self.assertEqual(row["reported_dismissals"], 0)
|
||||||
|
|
||||||
|
|
||||||
class TestApply(RegistryTestCase):
|
class TestApply(RegistryTestCase):
|
||||||
def test_each_action_reaches_its_method(self):
|
def test_each_action_reaches_its_method(self):
|
||||||
self.registry.apply(
|
self.registry.apply(
|
||||||
|
|||||||
Reference in New Issue
Block a user