Skip to content

Commit 804e193

Browse files
test cases for telemetry
1 parent 01d643d commit 804e193

File tree

7 files changed

+226
-0
lines changed

7 files changed

+226
-0
lines changed

tests/telemetry/__init__.py

Whitespace-only changes.

tests/telemetry/conftest.py

Whitespace-only changes.

tests/telemetry/product/__init__.py

Whitespace-only changes.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import pytest
2+
3+
from datu.telemetry.product.events import ProductTelemetryEvent
4+
5+
6+
@pytest.fixture
7+
def sample_event_data():
8+
return {
9+
"event_name": "test_event",
10+
"user_id": "12345",
11+
"timestamp": "2024-06-01T12:00:00Z",
12+
"properties": {"plan": "pro", "source": "web"},
13+
}
14+
15+
16+
@pytest.fixture
17+
def event(sample_event_data):
18+
return ProductTelemetryEvent(
19+
event_name=sample_event_data["event_name"],
20+
user_id=sample_event_data["user_id"],
21+
timestamp=sample_event_data["timestamp"],
22+
properties=sample_event_data["properties"],
23+
)
24+
25+
26+
@pytest.fixture
27+
def sample_event():
28+
return ProductTelemetryEvent(foo="bar")
29+
30+
31+
@pytest.fixture
32+
def telemetry_settings():
33+
from datu.telemetry.config import TelemetryConfig
34+
35+
return TelemetryConfig(api_key="dummy_key", package_name="datu-core")
36+
37+
38+
@pytest.fixture
39+
def posthog_client(telemetry_settings):
40+
from datu.telemetry.product.posthog import PostHogClient
41+
42+
return PostHogClient(settings=telemetry_settings)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import pytest
2+
3+
from datu.telemetry.product.events import MCPClientEvent, OpenAIEvent, ProductTelemetryEvent
4+
5+
6+
def test_event_initialization(event, sample_event_data):
7+
assert event.properties["event_name"] == sample_event_data["event_name"]
8+
assert event.properties["user_id"] == sample_event_data["user_id"]
9+
assert event.properties["timestamp"] == sample_event_data["timestamp"]
10+
assert event.properties["properties"] == sample_event_data["properties"]
11+
12+
13+
def test_event_name_and_batch_key(event):
14+
assert event.name == "ProductTelemetryEvent"
15+
assert event.batch_key == event.name
16+
17+
18+
def test_batching_same_type(event):
19+
other = ProductTelemetryEvent(event_name="other_event")
20+
batched = event.batch(other)
21+
22+
# Batch size increments
23+
assert batched.batch_size == 2
24+
assert batched is event # batching modifies self
25+
26+
27+
def test_batching_different_type_raises():
28+
class AnotherEvent(ProductTelemetryEvent):
29+
pass
30+
31+
e1 = ProductTelemetryEvent()
32+
e2 = AnotherEvent()
33+
with pytest.raises(ValueError):
34+
e1.batch(e2)
35+
36+
37+
def test_batch_size_increment(event):
38+
# Initial batch_size
39+
assert event.batch_size == 1
40+
event.batch(ProductTelemetryEvent())
41+
assert event.batch_size == 2
42+
event.batch(ProductTelemetryEvent())
43+
assert event.batch_size == 3
44+
45+
46+
def test_mcp_client_event_properties():
47+
servers = ["playwright", "puppeteer"]
48+
event = MCPClientEvent(server_names=servers)
49+
50+
# Check properties
51+
assert event.properties["mcp_server_names"] == servers
52+
# Name and batch_key should come from base class
53+
assert event.name == "MCPClientEvent"
54+
assert event.batch_key == event.name
55+
assert event.batch_size == 1
56+
57+
58+
def test_openai_event_properties():
59+
from datu.app_config import get_app_settings
60+
61+
app_settings = get_app_settings()
62+
data = {"user_id": "123", "action": "test"}
63+
event = OpenAIEvent(**data)
64+
65+
# Base properties
66+
for k, v in data.items():
67+
assert event.properties[k] == v
68+
69+
# Extra property added in subclass
70+
assert event.properties["openai_model"] == app_settings.openai_model
71+
72+
# Name and batch_key
73+
assert event.name == "OpenAIEvent"
74+
assert event.batch_key == event.name
75+
assert event.batch_size == 1
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
from unittest.mock import patch
2+
3+
4+
def test_posthog_client_initialization(posthog_client, telemetry_settings):
5+
from datu.telemetry.product.posthog import PostHogClient
6+
7+
assert posthog_client.settings == telemetry_settings
8+
assert isinstance(posthog_client._batched_events, dict)
9+
assert isinstance(posthog_client.session_id, str)
10+
assert posthog_client._user_id == ""
11+
assert posthog_client._user_id_path == PostHogClient.USER_ID_PATH
12+
13+
14+
def test_user_id_creation(tmp_path):
15+
from datu.telemetry.config import TelemetryConfig
16+
from datu.telemetry.product.posthog import PostHogClient
17+
18+
path = tmp_path / "telemetry_user_id"
19+
client = PostHogClient(settings=TelemetryConfig())
20+
client._user_id_path = path
21+
22+
# file does not exist yet
23+
uid = client.user_id
24+
assert uid != PostHogClient.UNKNOWN_USER_ID
25+
assert path.read_text().strip() == uid
26+
27+
# file exists, reads the same
28+
uid2 = client.user_id
29+
assert uid2 == uid
30+
31+
32+
def test_user_id_fallback_patch():
33+
from pathlib import Path
34+
35+
from datu.telemetry.config import TelemetryConfig
36+
from datu.telemetry.product.posthog import PostHogClient
37+
38+
client = PostHogClient(settings=TelemetryConfig())
39+
40+
with (
41+
patch.object(Path, "exists", side_effect=OSError("fail")),
42+
patch.object(Path, "read_text", side_effect=OSError("fail")),
43+
):
44+
uid = client.user_id
45+
46+
assert uid == PostHogClient.UNKNOWN_USER_ID
47+
48+
49+
def test_base_context(monkeypatch):
50+
from datu.telemetry.config import TelemetryConfig
51+
from datu.telemetry.product.posthog import PostHogClient
52+
53+
client = PostHogClient(settings=TelemetryConfig(package_name="nonexistent_pkg"))
54+
55+
context = client._base_context()
56+
assert "python_version" in context
57+
assert "os" in context
58+
assert "os_version" in context
59+
assert context["package_version"] == "unknown"
60+
assert isinstance(context["extras_installed"], dict)
61+
62+
63+
def test_capture_single_event(monkeypatch, posthog_client, sample_event):
64+
# Ensure _send is called
65+
called = {}
66+
67+
def fake_send(event):
68+
called["event_name"] = event.name
69+
70+
posthog_client._send = fake_send
71+
72+
posthog_client.capture(sample_event)
73+
assert called["event_name"] == sample_event.name
74+
75+
76+
def test_capture_batching(monkeypatch):
77+
from datu.telemetry.config import TelemetryConfig
78+
from datu.telemetry.product.events import ProductTelemetryEvent
79+
from datu.telemetry.product.posthog import PostHogClient
80+
81+
settings = TelemetryConfig(api_key="dummy")
82+
client = PostHogClient(settings=settings)
83+
84+
class BatchEvent(ProductTelemetryEvent):
85+
max_batch_size = 2
86+
87+
e1 = BatchEvent(foo=1)
88+
e2 = BatchEvent(foo=2)
89+
90+
sent = []
91+
92+
def fake_send(event):
93+
sent.append(event)
94+
95+
client._send = fake_send
96+
97+
client.capture(e1)
98+
assert client._batched_events[e1.batch_key].batch_size == 1
99+
assert sent == []
100+
101+
client.capture(e2)
102+
assert sent[0].batch_size == 2
103+
assert e1.batch_key not in client._batched_events

tests/telemetry/test_config.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
def test_config():
2+
from datu.telemetry.config import get_telemetry_settings
3+
4+
settings = get_telemetry_settings()
5+
assert settings.api_key == "phc_m74dfR9nLpm2nipvkL2swyFDtNuQNC9o2FL2CSbh6Je"
6+
assert settings.package_name == "datu-core"

0 commit comments

Comments
 (0)