mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
feat(observability): add Sentry error reporting to Rust core (#131)
* chore(workflows): comment out Windows smoke tests in installer and release workflows * feat(observability): integrate Sentry for error reporting and add configuration support - Added Sentry integration for error reporting in the application, initializing it in the main function. - Introduced a new environment variable `OPENHUMAN_SENTRY_DSN` to configure Sentry DSN. - Updated the observability configuration schema to include a field for Sentry DSN. - Enhanced logging to include Sentry event filtering based on log levels. - Implemented secret scrubbing to protect sensitive information in error reports. * feat(analytics): add support for anonymized analytics settings - Introduced new environment variable `OPENHUMAN_ANALYTICS_ENABLED` to enable or disable anonymized analytics and crash reports. - Updated the PrivacyPanel component to sync analytics consent with the core configuration. - Added new functions to handle analytics settings updates and retrieval in the Tauri backend. - Enhanced observability configuration to include analytics settings, defaulting to enabled. - Updated relevant schemas and handlers for analytics settings in the backend. * refactor(tauriCommands): improve formatting and structure of analytics settings function - Reformatted the `openhumanUpdateAnalyticsSettings` function for better readability by adjusting the parameter structure. - Enhanced the output formatting in the `handle_get_analytics_settings` function for improved clarity in the JSON response. * feat(analytics): sync analytics consent to core RPC and improve anonymization copy Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
52b59f62d7
commit
906b55b63e
@@ -111,6 +111,14 @@ OLLAMA_BIN=
|
||||
# [optional] Override skills registry URL
|
||||
SKILLS_REGISTRY_URL=
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Error Reporting (Sentry)
|
||||
# ---------------------------------------------------------------------------
|
||||
# [optional] Sentry DSN for Rust core error reporting (no PII is sent)
|
||||
OPENHUMAN_SENTRY_DSN=
|
||||
# [optional] Default: true — set to false to disable anonymized analytics & crash reports
|
||||
OPENHUMAN_ANALYTICS_ENABLED=true
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Logging
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -23,13 +23,13 @@ jobs:
|
||||
- name: Run installer dry-run
|
||||
run: bash scripts/install.sh --dry-run --verbose
|
||||
|
||||
smoke-windows:
|
||||
name: Smoke install.ps1 (windows-latest)
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
# smoke-windows:
|
||||
# name: Smoke install.ps1 (windows-latest)
|
||||
# runs-on: windows-latest
|
||||
# steps:
|
||||
# - name: Checkout
|
||||
# uses: actions/checkout@v4
|
||||
|
||||
- name: Run installer dry-run
|
||||
shell: pwsh
|
||||
run: ./scripts/install.ps1 -DryRun
|
||||
# - name: Run installer dry-run
|
||||
# shell: pwsh
|
||||
# run: ./scripts/install.ps1 -DryRun
|
||||
|
||||
@@ -221,10 +221,10 @@ jobs:
|
||||
args: --target x86_64-unknown-linux-gnu
|
||||
target: x86_64-unknown-linux-gnu
|
||||
artifact_suffix: ubuntu
|
||||
- platform: windows-latest
|
||||
args: --target x86_64-pc-windows-msvc
|
||||
target: x86_64-pc-windows-msvc
|
||||
artifact_suffix: windows
|
||||
# - platform: windows-latest
|
||||
# args: --target x86_64-pc-windows-msvc
|
||||
# target: x86_64-pc-windows-msvc
|
||||
# artifact_suffix: windows
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
|
||||
Generated
+569
-6
@@ -14,6 +14,15 @@ dependencies = [
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
@@ -453,6 +462,21 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object 0.37.3",
|
||||
"rustc-demangle",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
@@ -594,6 +618,15 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block2"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bs58"
|
||||
version = "0.5.1"
|
||||
@@ -686,6 +719,12 @@ dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cesu8"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
|
||||
|
||||
[[package]]
|
||||
name = "cff-parser"
|
||||
version = "0.1.0"
|
||||
@@ -863,6 +902,16 @@ version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
|
||||
|
||||
[[package]]
|
||||
name = "combine"
|
||||
version = "4.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compact_str"
|
||||
version = "0.9.0"
|
||||
@@ -1289,6 +1338,16 @@ dependencies = [
|
||||
"deadpool-runtime",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "debugid"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "decancer"
|
||||
version = "3.3.3"
|
||||
@@ -1528,6 +1587,16 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch2"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "displaydoc"
|
||||
version = "0.2.5"
|
||||
@@ -2410,7 +2479,7 @@ dependencies = [
|
||||
"log",
|
||||
"native-tls",
|
||||
"rand 0.9.2",
|
||||
"reqwest",
|
||||
"reqwest 0.12.28",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.18",
|
||||
@@ -3074,6 +3143,50 @@ dependencies = [
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jni"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
|
||||
dependencies = [
|
||||
"cesu8",
|
||||
"cfg-if",
|
||||
"combine",
|
||||
"jni-sys 0.3.1",
|
||||
"log",
|
||||
"thiserror 1.0.69",
|
||||
"walkdir",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jni-sys"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258"
|
||||
dependencies = [
|
||||
"jni-sys 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jni-sys"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2"
|
||||
dependencies = [
|
||||
"jni-sys-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jni-sys-macros"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.34"
|
||||
@@ -3518,7 +3631,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"reqwest",
|
||||
"reqwest 0.12.28",
|
||||
"ruma",
|
||||
"serde",
|
||||
"serde_html_form",
|
||||
@@ -4170,7 +4283,7 @@ dependencies = [
|
||||
"getrandom 0.2.17",
|
||||
"http 1.4.0",
|
||||
"rand 0.8.5",
|
||||
"reqwest",
|
||||
"reqwest 0.12.28",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
@@ -4179,6 +4292,36 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f"
|
||||
dependencies = [
|
||||
"objc2-encode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-cloud-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-data"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.2"
|
||||
@@ -4186,6 +4329,95 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-graphics"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-io-surface",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-image"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-location"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-text"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"block2",
|
||||
"libc",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-io-surface"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-quartz-core"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4197,6 +4429,37 @@ dependencies = [
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-ui-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-cloud-kit",
|
||||
"objc2-core-data",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
"objc2-core-image",
|
||||
"objc2-core-location",
|
||||
"objc2-core-text",
|
||||
"objc2-foundation",
|
||||
"objc2-quartz-core",
|
||||
"objc2-user-notifications",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-user-notifications"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.37.3"
|
||||
@@ -4308,7 +4571,7 @@ dependencies = [
|
||||
"prost 0.14.3",
|
||||
"rand 0.9.2",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"reqwest 0.12.28",
|
||||
"ring",
|
||||
"rppal",
|
||||
"rquickjs",
|
||||
@@ -4317,6 +4580,7 @@ dependencies = [
|
||||
"rustls-pki-types",
|
||||
"rustyline",
|
||||
"schemars",
|
||||
"sentry",
|
||||
"serde",
|
||||
"serde-big-array",
|
||||
"serde_json",
|
||||
@@ -4417,7 +4681,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"http 1.4.0",
|
||||
"opentelemetry",
|
||||
"reqwest",
|
||||
"reqwest 0.12.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4432,7 +4696,7 @@ dependencies = [
|
||||
"opentelemetry-proto",
|
||||
"opentelemetry_sdk",
|
||||
"prost 0.14.3",
|
||||
"reqwest",
|
||||
"reqwest 0.12.28",
|
||||
"thiserror 2.0.18",
|
||||
]
|
||||
|
||||
@@ -4489,6 +4753,22 @@ version = "2.0.0-rc.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06503bb33f294c5f1ba484011e053bfa6ae227074bdb841e9863492dc5960d4b"
|
||||
|
||||
[[package]]
|
||||
name = "os_info"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"log",
|
||||
"nix 0.30.1",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
"objc2-ui-kit",
|
||||
"serde",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
@@ -5124,6 +5404,7 @@ version = "0.11.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"bytes",
|
||||
"getrandom 0.3.4",
|
||||
"lru-slab",
|
||||
@@ -5468,6 +5749,46 @@ dependencies = [
|
||||
"webpki-roots 1.0.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http 1.4.0",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"hyper",
|
||||
"hyper-rustls",
|
||||
"hyper-util",
|
||||
"js-sys",
|
||||
"log",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"quinn",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"rustls-platform-verifier",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sync_wrapper",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
"tower",
|
||||
"tower-http",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
@@ -5728,6 +6049,12 @@ dependencies = [
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.2"
|
||||
@@ -5807,6 +6134,33 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-platform-verifier"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784"
|
||||
dependencies = [
|
||||
"core-foundation 0.10.1",
|
||||
"core-foundation-sys",
|
||||
"jni",
|
||||
"log",
|
||||
"once_cell",
|
||||
"rustls",
|
||||
"rustls-native-certs",
|
||||
"rustls-platform-verifier-android",
|
||||
"rustls-webpki",
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"webpki-root-certs",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-platform-verifier-android"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.103.10"
|
||||
@@ -5873,6 +6227,15 @@ dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.29"
|
||||
@@ -5965,6 +6328,103 @@ version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||
|
||||
[[package]]
|
||||
name = "sentry"
|
||||
version = "0.47.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb25f439f97d26fea01d717fa626167ceffcd981addaa670001e70505b72acbb"
|
||||
dependencies = [
|
||||
"cfg_aliases",
|
||||
"httpdate",
|
||||
"reqwest 0.13.2",
|
||||
"rustls",
|
||||
"sentry-backtrace",
|
||||
"sentry-contexts",
|
||||
"sentry-core",
|
||||
"sentry-panic",
|
||||
"sentry-tracing",
|
||||
"tokio",
|
||||
"ureq 3.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-backtrace"
|
||||
version = "0.47.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46a8c2c1bd5c1f735e84f28b48e7d72efcaafc362b7541bc8253e60e8fcdffc6"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"regex",
|
||||
"sentry-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-contexts"
|
||||
version = "0.47.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b88a90baa654d7f0e1f4b667f6b434293d9f72c71bef16b197c76af5b7d5803"
|
||||
dependencies = [
|
||||
"hostname",
|
||||
"libc",
|
||||
"os_info",
|
||||
"rustc_version",
|
||||
"sentry-core",
|
||||
"uname",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-core"
|
||||
version = "0.47.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ac170a5bba8bec6e3339c90432569d89641fa7a3d3e4f44987d24f0762e6adf"
|
||||
dependencies = [
|
||||
"rand 0.9.2",
|
||||
"sentry-types",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-panic"
|
||||
version = "0.47.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6127d3d304ba5ce0409401e85aae538e303a569f8dbb031bf64f9ba0f7174346"
|
||||
dependencies = [
|
||||
"sentry-backtrace",
|
||||
"sentry-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-tracing"
|
||||
version = "0.47.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27701acc51e68db5281802b709010395bfcbcb128b1d0a4e5873680d3b47ff0c"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"sentry-backtrace",
|
||||
"sentry-core",
|
||||
"tracing-core",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-types"
|
||||
version = "0.47.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56780cb5597d676bf22e6c11d1f062eb4def46390ea3bfb047bcbcf7dfd19bdb"
|
||||
dependencies = [
|
||||
"debugid",
|
||||
"hex",
|
||||
"rand 0.9.2",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.18",
|
||||
"time",
|
||||
"url",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
@@ -7255,6 +7715,15 @@ dependencies = [
|
||||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uname"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unescaper"
|
||||
version = "0.1.8"
|
||||
@@ -7741,6 +8210,16 @@ dependencies = [
|
||||
"wa-rs-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.1"
|
||||
@@ -7965,6 +8444,15 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-root-certs"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.26.11"
|
||||
@@ -8024,6 +8512,15 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
@@ -8153,6 +8650,15 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
@@ -8198,6 +8704,21 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.42.2",
|
||||
"windows_aarch64_msvc 0.42.2",
|
||||
"windows_i686_gnu 0.42.2",
|
||||
"windows_i686_msvc 0.42.2",
|
||||
"windows_x86_64_gnu 0.42.2",
|
||||
"windows_x86_64_gnullvm 0.42.2",
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
@@ -8246,6 +8767,12 @@ dependencies = [
|
||||
"windows_x86_64_msvc 0.53.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
@@ -8264,6 +8791,12 @@ version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
@@ -8282,6 +8815,12 @@ version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
@@ -8312,6 +8851,12 @@ version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
@@ -8330,6 +8875,12 @@ version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
@@ -8348,6 +8899,12 @@ version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
@@ -8366,6 +8923,12 @@ version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
|
||||
@@ -82,6 +82,7 @@ tower = { version = "0.5", default-features = false }
|
||||
opentelemetry = { version = "0.31", default-features = false, features = ["trace", "metrics"] }
|
||||
opentelemetry_sdk = { version = "0.31", default-features = false, features = ["trace", "metrics"] }
|
||||
opentelemetry-otlp = { version = "0.31", default-features = false, features = ["trace", "metrics", "http-proto", "reqwest-client", "reqwest-rustls-webpki-roots"] }
|
||||
sentry = { version = "0.47.0", default-features = false, features = ["backtrace", "contexts", "panic", "tracing", "reqwest", "rustls"] }
|
||||
tokio-stream = { version = "0.1.18", features = ["full"] }
|
||||
url = "2"
|
||||
socketioxide = { version = "0.15", features = ["extensions"] }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { syncAnalyticsConsent } from '../../../services/analytics';
|
||||
import { setAnalyticsForUser } from '../../../store/authSlice';
|
||||
import { useAppDispatch, useAppSelector } from '../../../store/hooks';
|
||||
import { isTauri, openhumanUpdateAnalyticsSettings } from '../../../utils/tauriCommands';
|
||||
import SettingsHeader from '../components/SettingsHeader';
|
||||
import { useSettingsNavigation } from '../hooks/useSettingsNavigation';
|
||||
|
||||
@@ -19,6 +20,13 @@ const PrivacyPanel = () => {
|
||||
const newValue = !analyticsEnabled;
|
||||
dispatch(setAnalyticsForUser({ userId: user._id, enabled: newValue }));
|
||||
syncAnalyticsConsent(newValue);
|
||||
|
||||
// Sync to core config so the Rust process also respects the setting
|
||||
if (isTauri()) {
|
||||
openhumanUpdateAnalyticsSettings({ enabled: newValue }).catch(() => {
|
||||
/* best-effort */
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -30,7 +38,7 @@ const PrivacyPanel = () => {
|
||||
{/* Analytics Section */}
|
||||
<div>
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wider text-stone-400 mb-3 px-1">
|
||||
Analytics
|
||||
Anonymized Analytics
|
||||
</h3>
|
||||
<div className="bg-stone-800/50 rounded-xl border border-stone-700/50 overflow-hidden">
|
||||
<div className="flex items-center justify-between p-4">
|
||||
@@ -38,7 +46,8 @@ const PrivacyPanel = () => {
|
||||
<p className="text-sm font-medium text-white">Share Anonymized Usage Data</p>
|
||||
<p className="text-xs text-stone-400 mt-1 leading-relaxed">
|
||||
Help improve OpenHuman by sharing anonymous crash reports and usage analytics.
|
||||
No personal data, messages, or wallet information is ever collected.
|
||||
All data is fully anonymized — no personal data, messages, wallet keys, or
|
||||
session information is ever collected.
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
@@ -73,9 +82,10 @@ const PrivacyPanel = () => {
|
||||
</svg>
|
||||
<div>
|
||||
<p className="text-xs text-stone-400 leading-relaxed">
|
||||
When enabled, we collect only crash information, device type, and the file
|
||||
location of errors. We never access your messages, session data, wallet keys, or
|
||||
any personally identifiable information.
|
||||
All analytics and bug reports are fully anonymized. When enabled, we collect only
|
||||
crash information, device type, and the file location of errors. We never access
|
||||
your messages, session data, wallet keys, API keys, or any personally identifiable
|
||||
information. You can change this setting at any time.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import { isTauri, openhumanUpdateAnalyticsSettings } from '../../../utils/tauriCommands';
|
||||
|
||||
interface AnalyticsStepProps {
|
||||
onNext: (analyticsEnabled: boolean) => void;
|
||||
}
|
||||
@@ -7,13 +9,26 @@ interface AnalyticsStepProps {
|
||||
const AnalyticsStep = ({ onNext }: AnalyticsStepProps) => {
|
||||
const [selectedOption, setSelectedOption] = useState('shareAnalytics');
|
||||
|
||||
const handleContinue = () => {
|
||||
const enabled = selectedOption === 'shareAnalytics';
|
||||
|
||||
// Sync to core config so the Rust process also respects the setting
|
||||
if (isTauri()) {
|
||||
openhumanUpdateAnalyticsSettings({ enabled }).catch(() => {
|
||||
/* best-effort */
|
||||
});
|
||||
}
|
||||
|
||||
onNext(enabled);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="glass rounded-3xl p-8 shadow-large animate-fade-up">
|
||||
<div className="text-center mb-4">
|
||||
<h1 className="text-xl font-bold mb-2">Analytics</h1>
|
||||
<h1 className="text-xl font-bold mb-2">Anonymized Analytics</h1>
|
||||
<p className="opacity-70 text-sm">
|
||||
We collect anonymized usage data to help us improve the app for you and for others. You
|
||||
can choose to skip this.
|
||||
We collect fully anonymized usage data to help improve the app. No personal data,
|
||||
messages, or wallet keys are ever collected. You can change this anytime in Settings.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -41,8 +56,8 @@ const AnalyticsStep = ({ onNext }: AnalyticsStepProps) => {
|
||||
<div>
|
||||
<h3 className="font-semibold mb-1 text-sm">Share Anonymized Usage Data</h3>
|
||||
<p className="opacity-70 text-xs leading-relaxed">
|
||||
Share anonymized usage data to help us improve features and performance of the app.
|
||||
This helps us improve the app for you and for others.
|
||||
Share anonymized crash reports and usage analytics to help us improve features and
|
||||
performance. All data is fully anonymized.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -71,8 +86,8 @@ const AnalyticsStep = ({ onNext }: AnalyticsStepProps) => {
|
||||
<div>
|
||||
<h3 className="font-semibold mb-1 text-sm">Don't Collect Anything</h3>
|
||||
<p className="opacity-70 text-xs leading-relaxed">
|
||||
We won't collect any usage analytics, ensuring total anonymity. Keep all your data
|
||||
completely private.
|
||||
We won't collect any usage analytics or crash reports. Keep all your data completely
|
||||
private.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -91,14 +106,14 @@ const AnalyticsStep = ({ onNext }: AnalyticsStepProps) => {
|
||||
<div>
|
||||
<p className="font-medium text-sm">You can change this setting anytime</p>
|
||||
<p className="opacity-70 text-xs mt-1">
|
||||
Your privacy preferences can be updated in your account settings
|
||||
Your privacy preferences can be updated in Settings > Privacy & Security
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => onNext(selectedOption === 'shareAnalytics')}
|
||||
onClick={handleContinue}
|
||||
className="btn-primary w-full py-2.5 text-sm font-medium rounded-xl">
|
||||
Continue
|
||||
</button>
|
||||
|
||||
@@ -1065,6 +1065,29 @@ export async function openhumanUpdateScreenIntelligenceSettings(
|
||||
});
|
||||
}
|
||||
|
||||
export async function openhumanUpdateAnalyticsSettings(update: {
|
||||
enabled?: boolean;
|
||||
}): Promise<CommandResponse<ConfigSnapshot>> {
|
||||
if (!isTauri()) {
|
||||
throw new Error('Not running in Tauri');
|
||||
}
|
||||
return await callCoreRpc<CommandResponse<ConfigSnapshot>>({
|
||||
method: 'openhuman.update_analytics_settings',
|
||||
params: update,
|
||||
});
|
||||
}
|
||||
|
||||
export async function openhumanGetAnalyticsSettings(): Promise<
|
||||
CommandResponse<{ enabled: boolean }>
|
||||
> {
|
||||
if (!isTauri()) {
|
||||
throw new Error('Not running in Tauri');
|
||||
}
|
||||
return await callCoreRpc<CommandResponse<{ enabled: boolean }>>({
|
||||
method: 'openhuman.get_analytics_settings',
|
||||
});
|
||||
}
|
||||
|
||||
export async function openhumanGetRuntimeFlags(): Promise<CommandResponse<RuntimeFlags>> {
|
||||
if (!isTauri()) {
|
||||
throw new Error('Not running in Tauri');
|
||||
|
||||
+20
-3
@@ -10,7 +10,9 @@ use nu_ansi_term::{Color, Style};
|
||||
use tracing::{Event, Level};
|
||||
use tracing_subscriber::fmt::format::{FormatEvent, FormatFields, Writer};
|
||||
use tracing_subscriber::fmt::FmtContext;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::registry::LookupSpan;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
|
||||
static INIT: Once = Once::new();
|
||||
|
||||
@@ -89,10 +91,25 @@ pub fn init_for_cli_run(verbose: bool) {
|
||||
|
||||
let use_color = io::stderr().is_terminal();
|
||||
|
||||
let _ = tracing_subscriber::fmt()
|
||||
let fmt_layer = tracing_subscriber::fmt::layer()
|
||||
.with_ansi(use_color)
|
||||
.with_env_filter(filter)
|
||||
.event_format(CleanCliFormat)
|
||||
.event_format(CleanCliFormat);
|
||||
|
||||
let sentry_layer =
|
||||
sentry::integrations::tracing::layer().event_filter(|md: &tracing::Metadata<'_>| {
|
||||
match *md.level() {
|
||||
Level::ERROR => sentry::integrations::tracing::EventFilter::Event,
|
||||
Level::WARN | Level::INFO => {
|
||||
sentry::integrations::tracing::EventFilter::Breadcrumb
|
||||
}
|
||||
_ => sentry::integrations::tracing::EventFilter::Ignore,
|
||||
}
|
||||
});
|
||||
|
||||
let _ = tracing_subscriber::registry()
|
||||
.with(filter)
|
||||
.with(fmt_layer)
|
||||
.with(sentry_layer)
|
||||
.try_init();
|
||||
|
||||
let _ = tracing_log::LogTracer::init();
|
||||
|
||||
+62
@@ -1,7 +1,69 @@
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
|
||||
fn main() {
|
||||
// Initialize Sentry as the very first operation so the guard outlives everything.
|
||||
// If OPENHUMAN_SENTRY_DSN is unset or empty, sentry::init returns a no-op guard.
|
||||
let _sentry_guard = sentry::init(sentry::ClientOptions {
|
||||
dsn: std::env::var("OPENHUMAN_SENTRY_DSN")
|
||||
.ok()
|
||||
.filter(|s| !s.is_empty())
|
||||
.and_then(|s| s.parse().ok()),
|
||||
release: Some(std::borrow::Cow::Borrowed(env!("CARGO_PKG_VERSION"))),
|
||||
environment: Some(if cfg!(debug_assertions) {
|
||||
"development".into()
|
||||
} else {
|
||||
"production".into()
|
||||
}),
|
||||
send_default_pii: false,
|
||||
before_send: Some(std::sync::Arc::new(|mut event| {
|
||||
// Strip server_name (hostname) to avoid leaking machine identity
|
||||
event.server_name = None;
|
||||
// Strip user context entirely
|
||||
event.user = None;
|
||||
// Scrub exception messages for secrets
|
||||
for exc in &mut event.exception.values {
|
||||
if let Some(ref value) = exc.value {
|
||||
exc.value = Some(scrub_secrets(value));
|
||||
}
|
||||
}
|
||||
Some(event)
|
||||
})),
|
||||
sample_rate: 1.0,
|
||||
..sentry::ClientOptions::default()
|
||||
});
|
||||
|
||||
let args: Vec<String> = std::env::args().skip(1).collect();
|
||||
if let Err(err) = openhuman_core::run_core_from_args(&args) {
|
||||
eprintln!("{err}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Secret scrubbing
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static SECRET_PATTERNS: Lazy<Vec<(Regex, &'static str)>> = Lazy::new(|| {
|
||||
vec![
|
||||
(Regex::new(r"(?i)(bearer\s+)\S+").unwrap(), "${1}[REDACTED]"),
|
||||
(
|
||||
Regex::new(r"(?i)(api[_-]?key[=:\s]+)\S+").unwrap(),
|
||||
"${1}[REDACTED]",
|
||||
),
|
||||
(
|
||||
Regex::new(r"(?i)(token[=:\s]+)\S+").unwrap(),
|
||||
"${1}[REDACTED]",
|
||||
),
|
||||
(Regex::new(r"sk-[a-zA-Z0-9]{20,}").unwrap(), "[REDACTED]"),
|
||||
]
|
||||
});
|
||||
|
||||
/// Replace patterns that look like secrets with `[REDACTED]`.
|
||||
fn scrub_secrets(input: &str) -> String {
|
||||
let mut result = input.to_string();
|
||||
for (re, replacement) in SECRET_PATTERNS.iter() {
|
||||
result = re.replace_all(&result, *replacement).into_owned();
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
@@ -88,6 +88,11 @@ pub struct ScreenIntelligenceSettingsPatch {
|
||||
pub denylist: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct AnalyticsSettingsPatch {
|
||||
pub enabled: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct RuntimeFlagsOut {
|
||||
pub browser_allow_all: bool,
|
||||
@@ -313,6 +318,31 @@ pub async fn load_and_apply_runtime_settings(
|
||||
apply_runtime_settings(&mut config, update).await
|
||||
}
|
||||
|
||||
pub async fn apply_analytics_settings(
|
||||
config: &mut Config,
|
||||
update: AnalyticsSettingsPatch,
|
||||
) -> Result<RpcOutcome<serde_json::Value>, String> {
|
||||
if let Some(enabled) = update.enabled {
|
||||
config.observability.analytics_enabled = enabled;
|
||||
}
|
||||
config.save().await.map_err(|e| e.to_string())?;
|
||||
let snapshot = snapshot_config_json(config)?;
|
||||
Ok(RpcOutcome::new(
|
||||
snapshot,
|
||||
vec![format!(
|
||||
"analytics settings saved to {}",
|
||||
config.config_path.display()
|
||||
)],
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn load_and_apply_analytics_settings(
|
||||
update: AnalyticsSettingsPatch,
|
||||
) -> Result<RpcOutcome<serde_json::Value>, String> {
|
||||
let mut config = load_config_with_timeout().await?;
|
||||
apply_analytics_settings(&mut config, update).await
|
||||
}
|
||||
|
||||
pub async fn load_and_apply_browser_settings(
|
||||
update: BrowserSettingsPatch,
|
||||
) -> Result<RpcOutcome<serde_json::Value>, String> {
|
||||
|
||||
@@ -592,6 +592,22 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(dsn) = std::env::var("OPENHUMAN_SENTRY_DSN") {
|
||||
let dsn = dsn.trim();
|
||||
if !dsn.is_empty() {
|
||||
self.observability.sentry_dsn = Some(dsn.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(flag) = std::env::var("OPENHUMAN_ANALYTICS_ENABLED") {
|
||||
let normalized = flag.trim().to_ascii_lowercase();
|
||||
match normalized.as_str() {
|
||||
"1" | "true" | "yes" | "on" => self.observability.analytics_enabled = true,
|
||||
"0" | "false" | "no" | "off" => self.observability.analytics_enabled = false,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if self.proxy.enabled && self.proxy.scope == ProxyScope::Environment {
|
||||
self.proxy.apply_to_process_env();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,19 @@ pub struct ObservabilityConfig {
|
||||
/// Service name reported to the OTel collector. Defaults to "openhuman".
|
||||
#[serde(default)]
|
||||
pub otel_service_name: Option<String>,
|
||||
|
||||
/// Sentry DSN for error reporting. Overridden by `OPENHUMAN_SENTRY_DSN` env var.
|
||||
#[serde(default)]
|
||||
pub sentry_dsn: Option<String>,
|
||||
|
||||
/// Whether anonymized analytics and error reporting is enabled.
|
||||
/// Defaults to `true`. Users can disable via settings or CLI.
|
||||
#[serde(default = "default_analytics_enabled")]
|
||||
pub analytics_enabled: bool,
|
||||
}
|
||||
|
||||
fn default_analytics_enabled() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
impl Default for ObservabilityConfig {
|
||||
@@ -23,6 +36,8 @@ impl Default for ObservabilityConfig {
|
||||
backend: "none".into(),
|
||||
otel_endpoint: None,
|
||||
otel_service_name: None,
|
||||
sentry_dsn: None,
|
||||
analytics_enabled: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,11 @@ struct ScreenIntelligenceSettingsUpdate {
|
||||
denylist: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct AnalyticsSettingsUpdate {
|
||||
enabled: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct SetBrowserAllowAllParams {
|
||||
enabled: bool,
|
||||
@@ -80,6 +85,8 @@ pub fn all_controller_schemas() -> Vec<ControllerSchema> {
|
||||
schemas("set_browser_allow_all"),
|
||||
schemas("workspace_onboarding_flag_exists"),
|
||||
schemas("workspace_onboarding_flag_set"),
|
||||
schemas("update_analytics_settings"),
|
||||
schemas("get_analytics_settings"),
|
||||
schemas("agent_server_status"),
|
||||
]
|
||||
}
|
||||
@@ -134,6 +141,14 @@ pub fn all_registered_controllers() -> Vec<RegisteredController> {
|
||||
schema: schemas("workspace_onboarding_flag_set"),
|
||||
handler: handle_workspace_onboarding_flag_set,
|
||||
},
|
||||
RegisteredController {
|
||||
schema: schemas("update_analytics_settings"),
|
||||
handler: handle_update_analytics_settings,
|
||||
},
|
||||
RegisteredController {
|
||||
schema: schemas("get_analytics_settings"),
|
||||
handler: handle_get_analytics_settings,
|
||||
},
|
||||
RegisteredController {
|
||||
schema: schemas("agent_server_status"),
|
||||
handler: handle_agent_server_status,
|
||||
@@ -363,6 +378,28 @@ pub fn schemas(function: &str) -> ControllerSchema {
|
||||
required: true,
|
||||
}],
|
||||
},
|
||||
"update_analytics_settings" => ControllerSchema {
|
||||
namespace: "config",
|
||||
function: "update_analytics_settings",
|
||||
description: "Enable or disable anonymized analytics and error reporting.",
|
||||
inputs: vec![optional_bool(
|
||||
"enabled",
|
||||
"Enable anonymized analytics and crash reports.",
|
||||
)],
|
||||
outputs: vec![json_output("snapshot", "Updated config snapshot.")],
|
||||
},
|
||||
"get_analytics_settings" => ControllerSchema {
|
||||
namespace: "config",
|
||||
function: "get_analytics_settings",
|
||||
description: "Read current analytics settings.",
|
||||
inputs: vec![],
|
||||
outputs: vec![FieldSchema {
|
||||
name: "enabled",
|
||||
ty: TypeSchema::Bool,
|
||||
comment: "Whether anonymized analytics is enabled.",
|
||||
required: true,
|
||||
}],
|
||||
},
|
||||
"agent_server_status" => ControllerSchema {
|
||||
namespace: "config",
|
||||
function: "agent_server_status",
|
||||
@@ -503,6 +540,29 @@ fn handle_workspace_onboarding_flag_set(params: Map<String, Value>) -> Controlle
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_update_analytics_settings(params: Map<String, Value>) -> ControllerFuture {
|
||||
Box::pin(async move {
|
||||
let update = deserialize_params::<AnalyticsSettingsUpdate>(params)?;
|
||||
let patch = config_rpc::AnalyticsSettingsPatch {
|
||||
enabled: update.enabled,
|
||||
};
|
||||
to_json(config_rpc::load_and_apply_analytics_settings(patch).await?)
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_get_analytics_settings(_params: Map<String, Value>) -> ControllerFuture {
|
||||
Box::pin(async {
|
||||
let config = config_rpc::load_config_with_timeout().await?;
|
||||
let result = serde_json::json!({
|
||||
"enabled": config.observability.analytics_enabled,
|
||||
});
|
||||
to_json(RpcOutcome::new(
|
||||
result,
|
||||
vec!["analytics settings read".to_string()],
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_agent_server_status(_params: Map<String, Value>) -> ControllerFuture {
|
||||
Box::pin(async { to_json(config_rpc::agent_server_status()) })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user