telemetry refactor + unit tests (#2786)

This commit is contained in:
Thomas Brandého 2024-03-13 20:38:54 +01:00 committed by GitHub
parent f52ff56440
commit 92db402539
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 85 additions and 33 deletions

View File

@ -61,23 +61,28 @@ jobs:
working-directory: ./reflex-examples/counter
shell: wsl-bash {0}
run: |
export TELEMETRY_ENABLED=false
poetry run reflex export --backend-only
- name: Check run --backend-only before init for counter example
shell: wsl-bash {0}
run: |
export TELEMETRY_ENABLED=false
dos2unix scripts/integration.sh
poetry run bash scripts/integration.sh ./reflex-examples/counter dev 8001 --backend-only --backend-port 8001
- name: Init Website for counter example
working-directory: ./reflex-examples/counter
shell: wsl-bash {0}
run: |
export TELEMETRY_ENABLED=false
poetry run reflex init --loglevel debug
- name: Check export for counter example
working-directory: ./reflex-examples/counter
shell: wsl-bash {0}
run: |
export TELEMETRY_ENABLED=false
poetry run reflex export --frontend-only --loglevel debug
- name: Run Website and Check for errors
shell: wsl-bash {0}
run: |
export TELEMETRY_ENABLED=false
poetry run bash scripts/integration.sh ./reflex-examples/counter dev

View File

@ -434,19 +434,21 @@ def initialize_app_directory(app_name: str, template: constants.Templates.Kind):
)
def get_project_hash() -> int | None:
def get_project_hash(raise_on_fail: bool = False) -> int | None:
"""Get the project hash from the reflex.json file if the file exists.
Args:
raise_on_fail: Whether to raise an error if the file does not exist.
Returns:
project_hash: The app hash.
"""
if not os.path.exists(constants.Reflex.JSON):
if not os.path.exists(constants.Reflex.JSON) and not raise_on_fail:
return None
# Open and read the file
with open(constants.Reflex.JSON, "r") as file:
data = json.load(file)
project_hash = data["project_hash"]
return project_hash
return data["project_hash"]
def initialize_web_directory():

View File

@ -2,15 +2,16 @@
from __future__ import annotations
import json
import multiprocessing
import platform
from datetime import datetime
import httpx
import psutil
from reflex import constants
from reflex.utils.prerequisites import ensure_reflex_installation_id
from reflex.utils import console
from reflex.utils.prerequisites import ensure_reflex_installation_id, get_project_hash
POSTHOG_API_URL: str = "https://app.posthog.com/capture/"
@ -57,7 +58,52 @@ def get_memory() -> int:
Returns:
The total memory in MB.
"""
return psutil.virtual_memory().total >> 20
try:
return psutil.virtual_memory().total >> 20
except ValueError: # needed to pass ubuntu test
return 0
def _prepare_event(event: str) -> dict:
"""Prepare the event to be sent to the PostHog server.
Args:
event: The event name.
Returns:
The event data.
"""
installation_id = ensure_reflex_installation_id()
project_hash = get_project_hash(raise_on_fail=True)
if installation_id is None or project_hash is None:
console.debug(
f"Could not get installation_id or project_hash: {installation_id}, {project_hash}"
)
return {}
return {
"api_key": "phc_JoMo0fOyi0GQAooY3UyO9k0hebGkMyFJrrCw1Gt5SGb",
"event": event,
"properties": {
"distinct_id": installation_id,
"distinct_app_id": project_hash,
"user_os": get_os(),
"reflex_version": get_reflex_version(),
"python_version": get_python_version(),
"cpu_count": get_cpu_count(),
"memory": get_memory(),
},
"timestamp": datetime.utcnow().isoformat(),
}
def _send_event(event_data: dict) -> bool:
try:
httpx.post(POSTHOG_API_URL, json=event_data)
return True
except Exception:
return False
def send(event: str, telemetry_enabled: bool | None = None) -> bool:
@ -70,8 +116,6 @@ def send(event: str, telemetry_enabled: bool | None = None) -> bool:
Returns:
Whether the telemetry was sent successfully.
"""
import httpx
from reflex.config import get_config
# Get the telemetry_enabled from the config if it is not specified.
@ -82,29 +126,8 @@ def send(event: str, telemetry_enabled: bool | None = None) -> bool:
if not telemetry_enabled:
return False
installation_id = ensure_reflex_installation_id()
if installation_id is None:
event_data = _prepare_event(event)
if not event_data:
return False
try:
with open(constants.Dirs.REFLEX_JSON) as f:
reflex_json = json.load(f)
project_hash = reflex_json["project_hash"]
post_hog = {
"api_key": "phc_JoMo0fOyi0GQAooY3UyO9k0hebGkMyFJrrCw1Gt5SGb",
"event": event,
"properties": {
"distinct_id": installation_id,
"distinct_app_id": project_hash,
"user_os": get_os(),
"reflex_version": get_reflex_version(),
"python_version": get_python_version(),
"cpu_count": get_cpu_count(),
"memory": get_memory(),
},
"timestamp": datetime.utcnow().isoformat(),
}
httpx.post(POSTHOG_API_URL, json=post_hog)
return True
except Exception:
return False
return _send_event(event_data)

View File

@ -1,3 +1,5 @@
import httpx
import pytest
from packaging.version import parse as parse_python_version
from reflex.utils import telemetry
@ -28,3 +30,23 @@ def test_telemetry():
def test_disable():
"""Test that disabling telemetry works."""
assert not telemetry.send("test", telemetry_enabled=False)
@pytest.mark.parametrize("event", ["init", "reinit", "run-dev", "run-prod", "export"])
def test_send(mocker, event):
mocker.patch("httpx.post")
mocker.patch(
"builtins.open",
mocker.mock_open(
read_data='{"project_hash": "78285505863498957834586115958872998605"}'
),
)
telemetry.send(event, telemetry_enabled=True)
httpx.post.assert_called_once()
if telemetry.get_os() == "Windows":
open.assert_called_with(".web\\reflex.json", "r")
elif telemetry.get_os() == "Linux":
open.assert_called_with("/proc/meminfo", "rb", buffering=32768)
else:
open.assert_called_with(".web/reflex.json", "r")