diff --git a/docs/docs/configuration/advanced/analytics.md b/docs/docs/configuration/advanced/analytics.md new file mode 100644 index 0000000000..0171a05810 --- /dev/null +++ b/docs/docs/configuration/advanced/analytics.md @@ -0,0 +1,41 @@ +--- +id: analytics +title: Anonymous Analytics +--- + +import AnalyticsFields from "@site/src/components/AnalyticsFields"; +import NavPath from "@site/src/components/NavPath"; + +Frigate can send one anonymous usage report a day. The reports show the maintainers which hardware to support, which features people use, and how releases perform. Sharing is off until you turn it on. + +## Turning it on + +Enable **Share anonymous analytics** at , or set it in your config: + +```yaml +telemetry: + analytics: true +``` + +The same page has a **Preview the report** button that shows exactly what the next report contains. + +## How it's sent + +- Once a day, as a JSON POST to `https://analytics.frigate.video/report` +- The server looks up your country and region from your IP address and never stores the address +- Raw reports are kept for 60 days; only aggregate totals are published +- A random install ID, stored in `/config/.analytics.json`, keeps your install from being counted twice. Turning sharing off deletes it + +## What's never sent + +- Camera, zone, group, profile, or user names +- Object labels, face names, or license plate text +- IP addresses, hostnames, URLs, or stream paths +- Credentials or API keys +- Events, recordings, or anything from them + +## Every field + +Fields marked public appear in the published totals. The machine-readable schema is [frigate-analytics-schema.json](pathname:///frigate-analytics-schema.json). + + diff --git a/docs/docs/configuration/advanced/reference.md b/docs/docs/configuration/advanced/reference.md index e41eb9cfa2..9d709816da 100644 --- a/docs/docs/configuration/advanced/reference.md +++ b/docs/docs/configuration/advanced/reference.md @@ -1194,6 +1194,9 @@ ui: # Optional: Telemetry configuration telemetry: + # Optional: Share one anonymous usage report a day (default: shown below) + # NOTE: See https://docs.frigate.video/configuration/advanced/analytics for what is sent + analytics: False # Optional: Enabled network interfaces for bandwidth stats monitoring (default: empty list, let nethogs search all) network_interfaces: - eth diff --git a/docs/sidebars.ts b/docs/sidebars.ts index 9a1ec1ffe2..41c4d59ae2 100644 --- a/docs/sidebars.ts +++ b/docs/sidebars.ts @@ -130,6 +130,7 @@ const sidebars: SidebarsConfig = { label: "Advanced Configuration", items: [ "configuration/advanced/system", + "configuration/advanced/analytics", "configuration/advanced/reference", { type: "link", diff --git a/docs/src/components/AnalyticsFields/index.jsx b/docs/src/components/AnalyticsFields/index.jsx new file mode 100644 index 0000000000..b14b088619 --- /dev/null +++ b/docs/src/components/AnalyticsFields/index.jsx @@ -0,0 +1,60 @@ +import React from "react"; +import schema from "@site/static/frigate-analytics-schema.json"; + +function resolve(node) { + if (!node) return node; + if (node.$ref) return schema.$defs[node.$ref.split("/").pop()]; + if (node.anyOf) { + const inner = node.anyOf.find((option) => option.type !== "null"); + return inner ? resolve(inner) : node; + } + return node; +} + +function rows(properties, prefix = "") { + return Object.entries(properties).flatMap(([name, field]) => { + const path = prefix ? `${prefix}.${name}` : name; + const row = { + path, + description: field.description, + isPublic: field["x-public"], + }; + const target = resolve(field); + + if (target?.properties) return [row, ...rows(target.properties, path)]; + + const values = resolve(target?.additionalProperties); + if (values?.properties) + return [row, ...rows(values.properties, `${path}.`)]; + + const items = resolve(target?.items); + if (items?.properties) return [row, ...rows(items.properties, `${path}[]`)]; + + return [row]; + }); +} + +export default function AnalyticsFields() { + return ( + + + + + + + + + + {rows(schema.properties).map((row) => ( + + + + + + ))} + +
FieldDescriptionPublic
+ {row.path} + {row.description}{row.isPublic ? "Yes" : "No"}
+ ); +}