Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lite: Fix the analytics module to use asyncio to work in the Wasm env #5045

Merged
merged 14 commits into from Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/hungry-bobcats-own.md
@@ -0,0 +1,5 @@
---
"gradio": minor
---

feat:Lite: Fix the analytics module to use asyncio to work in the Wasm env
5 changes: 5 additions & 0 deletions .changeset/rare-feet-travel.md
@@ -0,0 +1,5 @@
---
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can delete this changeset file

Copy link
Member Author

@whitphx whitphx Jul 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, will delete it.

btw, it was added by the CI bot. Did it detect something wrong?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why it added two different changeset files! Will keep an eye out to see if it happens again

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I added this one, and the bot added the another one: .changeset/hungry-bobcats-own.md

Should only this file about @gradio/lite be deleted, or another one about the gradio Python package too?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh you don't need to add a changeset manually, the bot will take care of it. You can delete the changeset you created.

I don't think we have the automatic changeset support for @gradio/lite at the moment. Would be good to add it closer to the release

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see.
While it may also work, I have added the changeset for @gradio/lite in each PR, like #4779 (comment), btw.

"@gradio/lite": patch
---

Modify the analytics module to work on the Pyodide runtime
83 changes: 55 additions & 28 deletions gradio/analytics.py
@@ -1,17 +1,20 @@
""" Functions related to analytics and telemetry. """
from __future__ import annotations

import asyncio
import json
import os
import pkgutil
import threading
import urllib.parse
import warnings
from distutils.version import StrictVersion
from typing import Any

import requests

import gradio
from gradio import wasm_utils
from gradio.context import Context
from gradio.utils import GRADIO_VERSION

Expand All @@ -27,13 +30,52 @@ def analytics_enabled() -> bool:


def _do_analytics_request(url: str, data: dict[str, Any]) -> None:
if wasm_utils.IS_WASM:
asyncio.ensure_future(
_do_wasm_analytics_request(
url=url,
data=data,
)
)
else:
threading.Thread(
target=_do_normal_analytics_request,
kwargs={
"url": url,
"data": data,
},
).start()


def _do_normal_analytics_request(url: str, data: dict[str, Any]) -> None:
data["ip_address"] = get_local_ip_address()
try:
requests.post(url, data=data, timeout=5)
except (requests.ConnectionError, requests.exceptions.ReadTimeout):
pass # do not push analytics if no network


async def _do_wasm_analytics_request(url: str, data: dict[str, Any]) -> None:
import pyodide.http

data["ip_address"] = get_local_ip_address()

# We use urllib.parse.urlencode to encode the data as a form.
# Ref: https://docs.python.org/3/library/urllib.request.html#urllib-examples
body = urllib.parse.urlencode(data).encode("ascii")
headers = {
"Content-Type": "application/x-www-form-urlencoded",
}

try:
await asyncio.wait_for(
pyodide.http.pyfetch(url, method="POST", headers=headers, body=body),
timeout=5,
)
except asyncio.TimeoutError:
pass # do not push analytics if no network


def version_check():
try:
version_data = pkgutil.get_data(__name__, "version.txt")
Expand Down Expand Up @@ -84,13 +126,10 @@ def initiated_analytics(data: dict[str, Any]) -> None:
if not analytics_enabled():
return

threading.Thread(
target=_do_analytics_request,
kwargs={
"url": f"{ANALYTICS_URL}gradio-initiated-analytics/",
"data": data,
},
).start()
_do_analytics_request(
url=f"{ANALYTICS_URL}gradio-initiated-analytics/",
data=data,
)


def launched_analytics(blocks: gradio.Blocks, data: dict[str, Any]) -> None:
Expand Down Expand Up @@ -146,26 +185,17 @@ def launched_analytics(blocks: gradio.Blocks, data: dict[str, Any]) -> None:

abidlabs marked this conversation as resolved.
Show resolved Hide resolved
data.update(additional_data)

threading.Thread(
target=_do_analytics_request,
kwargs={
"url": f"{ANALYTICS_URL}gradio-launched-telemetry/",
"data": data,
},
).start()
_do_analytics_request(url=f"{ANALYTICS_URL}gradio-launched-telemetry/", data=data)


def integration_analytics(data: dict[str, Any]) -> None:
if not analytics_enabled():
return

threading.Thread(
target=_do_analytics_request,
kwargs={
"url": f"{ANALYTICS_URL}gradio-integration-analytics/",
"data": data,
},
).start()
_do_analytics_request(
url=f"{ANALYTICS_URL}gradio-integration-analytics/",
data=data,
)


def error_analytics(message: str) -> None:
Expand All @@ -179,10 +209,7 @@ def error_analytics(message: str) -> None:

data = {"error": message}

threading.Thread(
target=_do_analytics_request,
kwargs={
"url": f"{ANALYTICS_URL}gradio-error-analytics/",
"data": data,
},
).start()
_do_analytics_request(
url=f"{ANALYTICS_URL}gradio-error-analytics/",
data=data,
)
9 changes: 6 additions & 3 deletions gradio/blocks.py
Expand Up @@ -721,8 +721,11 @@ def __init__(
else analytics.analytics_enabled()
)
if self.analytics_enabled:
t = threading.Thread(target=analytics.version_check)
t.start()
if wasm_utils.IS_WASM:
analytics.version_check()
whitphx marked this conversation as resolved.
Show resolved Hide resolved
else:
t = threading.Thread(target=analytics.version_check)
t.start()
else:
os.environ["HF_HUB_DISABLE_TELEMETRY"] = "True"
super().__init__(render=False, **kwargs)
Expand Down Expand Up @@ -761,7 +764,7 @@ def __init__(
self.root_path = ""
self.root_urls = set()

if not wasm_utils.IS_WASM and self.analytics_enabled:
if self.analytics_enabled:
is_custom_theme = not any(
self.theme.to_dict() == built_in_theme.to_dict()
for built_in_theme in BUILT_IN_THEMES.values()
Expand Down