Anonymous Telemetry Opt Out Available (#550)
* Added anonymous telemetry with opt-out.
This commit is contained in:
parent
d0b47e1c23
commit
b36680fefd
18
poetry.lock
generated
18
poetry.lock
generated
@ -628,14 +628,14 @@ plugins = ["importlib-metadata"]
|
||||
|
||||
[[package]]
|
||||
name = "pyright"
|
||||
version = "1.1.293"
|
||||
version = "1.1.294"
|
||||
description = "Command line wrapper for pyright"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pyright-1.1.293-py3-none-any.whl", hash = "sha256:afc05309e775a9869c864da4e8c0c7a3e3be9d8fe202e780c3bae981bbb13936"},
|
||||
{file = "pyright-1.1.293.tar.gz", hash = "sha256:9397fdfcbc684fe5b87abbf9c27f540fe3b8d75999a5f187519cae1d065be38c"},
|
||||
{file = "pyright-1.1.294-py3-none-any.whl", hash = "sha256:5b27e28a1cfc60cea707fd3b644769fa6dd0b194481cdcc2399cf2a51cc5a846"},
|
||||
{file = "pyright-1.1.294.tar.gz", hash = "sha256:fea5fed3d6a3f02259e622c901e86a7b8bcf237d35e1cdfe01d0e0723768dcb6"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -832,14 +832,14 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "67.2.0"
|
||||
version = "67.3.2"
|
||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "setuptools-67.2.0-py3-none-any.whl", hash = "sha256:16ccf598aab3b506593c17378473978908a2734d7336755a8769b480906bec1c"},
|
||||
{file = "setuptools-67.2.0.tar.gz", hash = "sha256:b440ee5f7e607bb8c9de15259dba2583dd41a38879a7abc1d43a71c59524da48"},
|
||||
{file = "setuptools-67.3.2-py3-none-any.whl", hash = "sha256:bb6d8e508de562768f2027902929f8523932fcd1fb784e6d573d2cafac995a48"},
|
||||
{file = "setuptools-67.3.2.tar.gz", hash = "sha256:95f00380ef2ffa41d9bba85d95b27689d923c93dfbafed4aecd7cf988a25e012"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@ -1082,14 +1082,14 @@ test = ["black (>=22.3.0,<23.0.0)", "coverage (>=5.2,<6.0)", "isort (>=5.0.6,<6.
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.4.0"
|
||||
version = "4.5.0"
|
||||
description = "Backported and Experimental Type Hints for Python 3.7+"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"},
|
||||
{file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"},
|
||||
{file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"},
|
||||
{file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1 +0,0 @@
|
||||
0.1.16
|
3
pynecone/.templates/web/pynecone.json
Normal file
3
pynecone/.templates/web/pynecone.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "0.1.16"
|
||||
}
|
@ -27,6 +27,9 @@ class Config(Base):
|
||||
# The redis url.
|
||||
redis_url: Optional[str] = None
|
||||
|
||||
# Telemetry opt-in.
|
||||
telemetry_enabled: bool = True
|
||||
|
||||
# The deploy url.
|
||||
deploy_url: Optional[str] = None
|
||||
|
||||
|
@ -55,9 +55,9 @@ NODE_MODULES = "node_modules"
|
||||
# The package lock file.
|
||||
PACKAGE_LOCK = "package-lock.json"
|
||||
# The pcversion template file.
|
||||
PCVERSION_TEMPLATE_FILE = os.path.join(WEB_TEMPLATE_DIR, "pcversion.txt")
|
||||
PCVERSION_TEMPLATE_FILE = os.path.join(WEB_TEMPLATE_DIR, "pynecone.json")
|
||||
# The pcversion app file.
|
||||
PCVERSION_APP_FILE = os.path.join(WEB_DIR, "pcversion.txt")
|
||||
PCVERSION_APP_FILE = os.path.join(WEB_DIR, "pynecone.json")
|
||||
|
||||
|
||||
# Commands to run the app.
|
||||
|
@ -7,6 +7,7 @@ import httpx
|
||||
import typer
|
||||
|
||||
from pynecone import constants, utils
|
||||
from pynecone.telemetry import pynecone_telemetry
|
||||
|
||||
# Create the app.
|
||||
cli = typer.Typer()
|
||||
@ -43,6 +44,12 @@ def init():
|
||||
# Initialize the .gitignore.
|
||||
utils.initialize_gitignore()
|
||||
|
||||
# Set the pynecone project hash.
|
||||
utils.set_pynecone_project_hash()
|
||||
|
||||
# Post a telemetry event.
|
||||
pynecone_telemetry("init", utils.get_config().telemetry_enabled)
|
||||
|
||||
# Finish initializing the app.
|
||||
utils.console.log(f"[bold green]Finished Initializing: {app_name}")
|
||||
|
||||
@ -100,6 +107,9 @@ def run(
|
||||
frontend_cmd, backend_cmd = utils.run_frontend_prod, utils.run_backend_prod
|
||||
assert frontend_cmd and backend_cmd, "Invalid env"
|
||||
|
||||
# Post a telemetry event.
|
||||
pynecone_telemetry(f"run-{env.value}", utils.get_config().telemetry_enabled)
|
||||
|
||||
# Run the frontend and backend.
|
||||
try:
|
||||
if frontend:
|
||||
@ -174,6 +184,10 @@ def export(
|
||||
utils.console.rule("[bold]Compiling production app and preparing for export.")
|
||||
app = utils.get_app().app
|
||||
utils.export_app(app, backend=backend, frontend=frontend, zip=zipping)
|
||||
|
||||
# Post a telemetry event.
|
||||
pynecone_telemetry("export", utils.get_config().telemetry_enabled)
|
||||
|
||||
if zipping:
|
||||
utils.console.rule(
|
||||
"""Backend & Frontend compiled. See [green bold]backend.zip[/green bold]
|
||||
|
@ -1,39 +1,98 @@
|
||||
"""Anonymous telemetry for Pynecone."""
|
||||
|
||||
import json
|
||||
import multiprocessing
|
||||
import platform
|
||||
from datetime import datetime
|
||||
|
||||
import httpx
|
||||
import psutil
|
||||
|
||||
from pynecone import constants
|
||||
from pynecone.base import Base
|
||||
|
||||
|
||||
def get_os() -> str:
|
||||
"""Get the operating system.
|
||||
|
||||
Returns:
|
||||
The operating system.
|
||||
"""
|
||||
return platform.system()
|
||||
|
||||
|
||||
def get_python_version() -> str:
|
||||
"""Get the Python version.
|
||||
|
||||
Returns:
|
||||
The Python version.
|
||||
"""
|
||||
return platform.python_version()
|
||||
|
||||
|
||||
def get_pynecone_version() -> str:
|
||||
"""Get the Pynecone version.
|
||||
|
||||
Returns:
|
||||
The Pynecone version.
|
||||
"""
|
||||
return constants.VERSION
|
||||
|
||||
|
||||
def get_cpu_count() -> int:
|
||||
"""Get the number of CPUs.
|
||||
|
||||
Returns:
|
||||
The number of CPUs.
|
||||
"""
|
||||
return multiprocessing.cpu_count()
|
||||
|
||||
|
||||
def get_memory() -> int:
|
||||
"""Get the total memory in MB.
|
||||
|
||||
Returns:
|
||||
The total memory in MB.
|
||||
"""
|
||||
return psutil.virtual_memory().total >> 20
|
||||
|
||||
|
||||
class Telemetry(Base):
|
||||
"""Anonymous telemetry for Pynecone."""
|
||||
|
||||
user_os: str = ""
|
||||
cpu_count: int = 0
|
||||
memory: int = 0
|
||||
pynecone_version: str = ""
|
||||
python_version: str = ""
|
||||
user_os: str = get_os()
|
||||
cpu_count: int = get_cpu_count()
|
||||
memory: int = get_memory()
|
||||
pynecone_version: str = get_pynecone_version()
|
||||
python_version: str = get_python_version()
|
||||
|
||||
def get_os(self) -> None:
|
||||
"""Get the operating system."""
|
||||
self.user_os = platform.system()
|
||||
|
||||
def get_python_version(self) -> None:
|
||||
"""Get the Python version."""
|
||||
self.python_version = platform.python_version()
|
||||
def pynecone_telemetry(event: str, telemetry_enabled: bool) -> None:
|
||||
"""Send anonymous telemetry for Pynecone.
|
||||
|
||||
def get_pynecone_version(self) -> None:
|
||||
"""Get the Pynecone version."""
|
||||
self.pynecone_version = constants.VERSION
|
||||
|
||||
def get_cpu_count(self) -> None:
|
||||
"""Get the number of CPUs."""
|
||||
self.cpu_count = multiprocessing.cpu_count()
|
||||
|
||||
def get_memory(self) -> None:
|
||||
"""Get the total memory in MB."""
|
||||
self.memory = psutil.virtual_memory().total >> 20
|
||||
Args:
|
||||
event: The event name.
|
||||
telemetry_enabled: Whether to send the telemetry.
|
||||
"""
|
||||
try:
|
||||
if telemetry_enabled:
|
||||
telemetry = Telemetry()
|
||||
with open(constants.PCVERSION_APP_FILE) as f: # type: ignore
|
||||
pynecone_json = json.load(f)
|
||||
distinct_id = pynecone_json["project_hash"]
|
||||
post_hog = {
|
||||
"api_key": "phc_JoMo0fOyi0GQAooY3UyO9k0hebGkMyFJrrCw1Gt5SGb",
|
||||
"event": event,
|
||||
"properties": {
|
||||
"distinct_id": distinct_id,
|
||||
"user_os": telemetry.user_os,
|
||||
"pynecone_version": telemetry.pynecone_version,
|
||||
"python_version": telemetry.python_version,
|
||||
"cpu_count": telemetry.cpu_count,
|
||||
"memory": telemetry.memory,
|
||||
},
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
}
|
||||
httpx.post("https://app.posthog.com/capture/", json=post_hog)
|
||||
except Exception:
|
||||
pass
|
||||
|
@ -476,7 +476,7 @@ def is_latest_template() -> bool:
|
||||
Whether the app is using the latest template.
|
||||
"""
|
||||
with open(constants.PCVERSION_TEMPLATE_FILE) as f: # type: ignore
|
||||
template_version = f.read()
|
||||
template_version = json.load(f)["version"]
|
||||
if not os.path.exists(constants.PCVERSION_APP_FILE):
|
||||
return False
|
||||
with open(constants.PCVERSION_APP_FILE) as f: # type: ignore
|
||||
@ -484,6 +484,15 @@ def is_latest_template() -> bool:
|
||||
return app_version >= template_version
|
||||
|
||||
|
||||
def set_pynecone_project_hash():
|
||||
"""Write the hash of the Pynecone project to a PCVERSION_APP_FILE."""
|
||||
with open(constants.PCVERSION_APP_FILE) as f: # type: ignore
|
||||
pynecone_json = json.load(f)
|
||||
pynecone_json["project_hash"] = random.getrandbits(128)
|
||||
with open(constants.PCVERSION_APP_FILE, "w") as f:
|
||||
json.dump(pynecone_json, f, ensure_ascii=False)
|
||||
|
||||
|
||||
def export_app(
|
||||
app: App, backend: bool = True, frontend: bool = True, zip: bool = False
|
||||
):
|
||||
|
@ -12,28 +12,19 @@ def test_telemetry():
|
||||
tel = telemetry.Telemetry()
|
||||
|
||||
# Check that the user OS is one of the supported operating systems.
|
||||
tel.get_os()
|
||||
|
||||
assert tel.user_os is not None
|
||||
assert tel.user_os in ["Linux", "Darwin", "Java", "Windows"]
|
||||
|
||||
# Check that the CPU count and memory are greater than 0.
|
||||
tel.get_cpu_count()
|
||||
|
||||
assert tel.cpu_count > 0
|
||||
|
||||
# Check that the available memory is greater than 0
|
||||
tel.get_memory()
|
||||
|
||||
assert tel.memory > 0
|
||||
|
||||
# Check that the Pynecone version is not None.
|
||||
tel.get_python_version()
|
||||
assert tel.pynecone_version is not None
|
||||
|
||||
# Check that the Python version is greater than 3.7.
|
||||
tel.get_pynecone_version()
|
||||
|
||||
assert tel.python_version is not None
|
||||
assert versiontuple(tel.python_version) >= versiontuple("3.7")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user