Skip to content

Commit c9e3df2

Browse files
authored
feat(tracking): namespace PostHog events with cli: prefix (#465)
1 parent 72ec7a8 commit c9e3df2

2 files changed

Lines changed: 31 additions & 4 deletions

File tree

comfy_cli/tracking.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@
3232
# Only these events get the tracing_id --> workflow_run_id alias on PostHog.
3333
EXECUTION_EVENTS = frozenset({"execution_start", "execution_success", "execution_error"})
3434

35+
# Namespace applied to event names on PostHog only, matching the
36+
# app:/hub:/registry: surface-prefix convention in the shared project. Mixpanel
37+
# keeps the bare legacy names (see ``mixpanel_name`` in track_event) so its
38+
# historical streams stay continuous.
39+
POSTHOG_EVENT_PREFIX = "cli:"
40+
3541
# Kwargs whose values must never reach tracking system.
3642
# The key is kept (with a redacted marker) so we can still see whether the option was supplied.
3743
SENSITIVE_TRACKING_KEYS = frozenset({"api_key"})
@@ -113,9 +119,11 @@ def track(self, event_name: str, distinct_id: str | None, properties: dict[str,
113119
if not self.enabled or self.client is None or distinct_id is None:
114120
return
115121
merged = {**self._STANDARD_PROPERTIES, **properties}
122+
# Membership check uses the canonical (unprefixed) name; the prefix is
123+
# cosmetic to the PostHog taxonomy and applied only at capture time.
116124
if event_name in EXECUTION_EVENTS and "tracing_id" in merged:
117125
merged.setdefault("workflow_run_id", merged["tracing_id"])
118-
self.client.capture(event=event_name, distinct_id=distinct_id, properties=merged)
126+
self.client.capture(event=f"{POSTHOG_EVENT_PREFIX}{event_name}", distinct_id=distinct_id, properties=merged)
119127

120128
def flush(self) -> None:
121129
if self.client is None:

tests/comfy_cli/test_tracking_providers.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,17 +168,36 @@ def test_mixpanel_name_kwarg_routes_to_mixpanel_only(self, tracking_with_two_pro
168168
_, mp_kwargs = mp_provider.client.track.call_args
169169
assert mp_kwargs["event_name"] == "run"
170170

171+
# PostHog receives the canonical name, prefixed; Mixpanel keeps "run".
171172
ph_kwargs = _posthog_capture_kwargs(ph_provider.client)
172-
assert ph_kwargs["event"] == "execution_start"
173+
assert ph_kwargs["event"] == "cli:execution_start"
173174

174-
def test_without_alias_both_providers_get_same_name(self, tracking_with_two_providers):
175+
def test_posthog_prefixes_event_while_mixpanel_stays_bare(self, tracking_with_two_providers):
175176
tracking_mod, mp_provider, ph_provider = tracking_with_two_providers
176177
tracking_mod.track_event("execution_success")
177178

178179
_, mp_kwargs = mp_provider.client.track.call_args
179180
ph_kwargs = _posthog_capture_kwargs(ph_provider.client)
181+
# Mixpanel keeps the bare name for stream continuity; PostHog is namespaced.
180182
assert mp_kwargs["event_name"] == "execution_success"
181-
assert ph_kwargs["event"] == "execution_success"
183+
assert ph_kwargs["event"] == "cli:execution_success"
184+
185+
186+
class TestPostHogEventPrefix:
187+
def test_top_level_event_is_prefixed(self, tracking_with_two_providers):
188+
tracking_mod, mp_provider, ph_provider = tracking_with_two_providers
189+
tracking_mod.track_event("install")
190+
191+
# Mixpanel bare, PostHog namespaced.
192+
_, mp_kwargs = mp_provider.client.track.call_args
193+
assert mp_kwargs["event_name"] == "install"
194+
assert _posthog_capture_kwargs(ph_provider.client)["event"] == "cli:install"
195+
196+
def test_sub_namespaced_event_composes_with_prefix(self, tracking_with_two_providers):
197+
tracking_mod, _, ph_provider = tracking_with_two_providers
198+
tracking_mod.track_event("node:install")
199+
200+
assert _posthog_capture_kwargs(ph_provider.client)["event"] == "cli:node:install"
182201

183202

184203
class TestProviderConstruction:

0 commit comments

Comments
 (0)