Skip to content

Commit 70df373

Browse files
authored
[feat]: add support for sending anonymous user_id in telemetry (#491)
1 parent 4388f6b commit 70df373

File tree

2 files changed

+34
-18
lines changed

2 files changed

+34
-18
lines changed

embedchain/embedchain.py

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import hashlib
22
import importlib.metadata
3+
import json
34
import logging
45
import os
56
import threading
67
import uuid
8+
from pathlib import Path
79
from typing import Dict, Optional
810

911
import requests
@@ -25,6 +27,9 @@
2527

2628
ABS_PATH = os.getcwd()
2729
DB_DIR = os.path.join(ABS_PATH, "db")
30+
HOME_DIR = str(Path.home())
31+
CONFIG_DIR = os.path.join(HOME_DIR, ".embedchain")
32+
CONFIG_FILE = os.path.join(CONFIG_DIR, "config.json")
2833

2934

3035
class EmbedChain:
@@ -46,9 +51,30 @@ def __init__(self, config: BaseAppConfig):
4651

4752
# Send anonymous telemetry
4853
self.s_id = self.config.id if self.config.id else str(uuid.uuid4())
54+
self.u_id = self._load_or_generate_user_id()
4955
thread_telemetry = threading.Thread(target=self._send_telemetry_event, args=("init",))
5056
thread_telemetry.start()
5157

58+
def _load_or_generate_user_id(self):
59+
"""
60+
Loads the user id from the config file if it exists, otherwise generates a new
61+
one and saves it to the config file.
62+
"""
63+
if not os.path.exists(CONFIG_DIR):
64+
os.makedirs(CONFIG_DIR)
65+
66+
if os.path.exists(CONFIG_FILE):
67+
with open(CONFIG_FILE, "r") as f:
68+
data = json.load(f)
69+
if "user_id" in data:
70+
return data["user_id"]
71+
72+
u_id = str(uuid.uuid4())
73+
with open(CONFIG_FILE, "w") as f:
74+
json.dump({"user_id": u_id}, f)
75+
76+
return u_id
77+
5278
def add(
5379
self,
5480
source,
@@ -443,9 +469,11 @@ def _send_telemetry_event(self, method: str, extra_metadata: Optional[dict] = No
443469
"version": importlib.metadata.version(__package__ or __name__),
444470
"method": method,
445471
"language": "py",
472+
"u_id": self.u_id,
446473
}
447474
if extra_metadata:
448475
metadata.update(extra_metadata)
449476

450477
response = requests.post(url, json={"metadata": metadata})
451-
response.raise_for_status()
478+
if response.status_code != 200:
479+
logging.warning(f"Telemetry event failed with status code {response.status_code}")

tests/embedchain/test_chat.py

+5-17
Original file line numberDiff line numberDiff line change
@@ -7,43 +7,31 @@
77

88

99
class TestApp(unittest.TestCase):
10-
os.environ["OPENAI_API_KEY"] = "test_key"
11-
1210
def setUp(self):
11+
os.environ["OPENAI_API_KEY"] = "test_key"
1312
self.app = App(config=AppConfig(collect_metrics=False))
1413

15-
@patch("embedchain.embedchain.memory", autospec=True)
1614
@patch.object(App, "retrieve_from_database", return_value=["Test context"])
1715
@patch.object(App, "get_answer_from_llm", return_value="Test answer")
18-
def test_chat_with_memory(self, mock_answer, mock_retrieve, mock_memory):
16+
def test_chat_with_memory(self, mock_get_answer, mock_retrieve):
1917
"""
2018
This test checks the functionality of the 'chat' method in the App class with respect to the chat history
2119
memory.
2220
The 'chat' method is called twice. The first call initializes the chat history memory.
2321
The second call is expected to use the chat history from the first call.
2422
2523
Key assumptions tested:
26-
- After the first call, 'memory.chat_memory.add_user_message' and 'memory.chat_memory.add_ai_message' are
2724
called with correct arguments, adding the correct chat history.
25+
- After the first call, 'memory.chat_memory.add_user_message' and 'memory.chat_memory.add_ai_message' are
2826
- During the second call, the 'chat' method uses the chat history from the first call.
2927
3028
The test isolates the 'chat' method behavior by mocking out 'retrieve_from_database', 'get_answer_from_llm' and
3129
'memory' methods.
3230
"""
33-
mock_memory.load_memory_variables.return_value = {"history": []}
3431
app = App()
35-
36-
# First call to chat
3732
first_answer = app.chat("Test query 1")
3833
self.assertEqual(first_answer, "Test answer")
39-
mock_memory.chat_memory.add_user_message.assert_called_once_with("Test query 1")
40-
mock_memory.chat_memory.add_ai_message.assert_called_once_with("Test answer")
41-
42-
mock_memory.chat_memory.add_user_message.reset_mock()
43-
mock_memory.chat_memory.add_ai_message.reset_mock()
44-
45-
# Second call to chat
34+
self.assertEqual(len(app.memory.chat_memory.messages), 2)
4635
second_answer = app.chat("Test query 2")
4736
self.assertEqual(second_answer, "Test answer")
48-
mock_memory.chat_memory.add_user_message.assert_called_once_with("Test query 2")
49-
mock_memory.chat_memory.add_ai_message.assert_called_once_with("Test answer")
37+
self.assertEqual(len(app.memory.chat_memory.messages), 4)

0 commit comments

Comments
 (0)