Skip to content

Commit 2abca24

Browse files
committed
telemetry: pluggable Unity sender; add MCP_DISABLE_TELEMETRY; server reads version file; locks for milestones
1 parent f6a5568 commit 2abca24

File tree

4 files changed

+66
-21
lines changed

4 files changed

+66
-21
lines changed

UnityMcpBridge/Editor/Helpers/TelemetryHelper.cs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public static class TelemetryHelper
1212
{
1313
private const string TELEMETRY_DISABLED_KEY = "MCPForUnity.TelemetryDisabled";
1414
private const string CUSTOMER_UUID_KEY = "MCPForUnity.CustomerUUID";
15+
private static Action<Dictionary<string, object>> s_sender;
1516

1617
/// <summary>
1718
/// Check if telemetry is enabled (can be disabled via Environment Variable or EditorPrefs)
@@ -34,7 +35,15 @@ public static bool IsEnabled
3435
{
3536
return false;
3637
}
37-
38+
39+
// Honor protocol-wide opt-out as well
40+
var mcpDisable = Environment.GetEnvironmentVariable("MCP_DISABLE_TELEMETRY");
41+
if (!string.IsNullOrEmpty(mcpDisable) &&
42+
(mcpDisable.Equals("true", StringComparison.OrdinalIgnoreCase) || mcpDisable == "1"))
43+
{
44+
return false;
45+
}
46+
3847
// Check EditorPrefs
3948
return !UnityEditor.EditorPrefs.GetBool(TELEMETRY_DISABLED_KEY, false);
4049
}
@@ -110,6 +119,14 @@ public static void RecordEvent(string eventType, Dictionary<string, object> data
110119
}
111120
}
112121

122+
/// <summary>
123+
/// Allows the bridge to register a concrete sender for telemetry payloads.
124+
/// </summary>
125+
public static void RegisterTelemetrySender(Action<Dictionary<string, object>> sender)
126+
{
127+
s_sender = sender;
128+
}
129+
113130
/// <summary>
114131
/// Record bridge startup event
115132
/// </summary>
@@ -162,15 +179,28 @@ public static void RecordToolExecution(string toolName, bool success, float dura
162179

163180
private static void SendTelemetryToPythonServer(Dictionary<string, object> telemetryData)
164181
{
165-
// This would integrate with the existing bridge communication system
166-
// For now, we'll just log it when debug is enabled
182+
var sender = s_sender;
183+
if (sender != null)
184+
{
185+
try
186+
{
187+
sender(telemetryData);
188+
return;
189+
}
190+
catch (Exception e)
191+
{
192+
if (IsDebugEnabled())
193+
{
194+
Debug.LogWarning($"Telemetry sender error (non-blocking): {e.Message}");
195+
}
196+
}
197+
}
198+
199+
// Fallback: log when debug is enabled
167200
if (IsDebugEnabled())
168201
{
169202
Debug.Log($"<b><color=#2EA3FF>MCP-TELEMETRY</color></b>: {telemetryData["event_type"]}");
170203
}
171-
172-
// TODO: Integrate with MCPForUnityBridge command system
173-
// We would send this as a special telemetry command to the Python server
174204
}
175205

176206
private static bool IsDebugEnabled()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.3.0

UnityMcpBridge/UnityMcpServer~/src/server.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,15 @@ async def server_lifespan(server: FastMCP) -> AsyncIterator[Dict[str, Any]]:
2727

2828
# Record server startup telemetry
2929
start_time = time.time()
30+
start_clk = time.perf_counter()
31+
try:
32+
from pathlib import Path
33+
ver_path = Path(__file__).parent / "server-version.txt"
34+
server_version = ver_path.read_text(encoding="utf-8").strip()
35+
except Exception:
36+
server_version = "unknown"
3037
record_telemetry(RecordType.STARTUP, {
31-
"server_version": "3.0.2",
38+
"server_version": server_version,
3239
"startup_time": start_time
3340
})
3441

@@ -45,15 +52,23 @@ async def server_lifespan(server: FastMCP) -> AsyncIterator[Dict[str, Any]]:
4552
"connection_time_ms": (time.time() - start_time) * 1000
4653
})
4754

48-
except Exception as e:
49-
logger.warning(f"Could not connect to Unity on startup: {str(e)}")
55+
except ConnectionError as e:
56+
logger.warning("Could not connect to Unity on startup: %s", e)
5057
_unity_connection = None
5158

5259
# Record connection failure
5360
record_telemetry(RecordType.UNITY_CONNECTION, {
5461
"status": "failed",
5562
"error": str(e)[:200],
56-
"connection_time_ms": (time.time() - start_time) * 1000
63+
"connection_time_ms": (time.perf_counter() - start_clk) * 1000
64+
})
65+
except Exception as e:
66+
logger.warning("Unexpected error connecting to Unity on startup: %s", e)
67+
_unity_connection = None
68+
record_telemetry(RecordType.UNITY_CONNECTION, {
69+
"status": "failed",
70+
"error": str(e)[:200],
71+
"connection_time_ms": (time.perf_counter() - start_clk) * 1000
5772
})
5873

5974
try:

UnityMcpBridge/UnityMcpServer~/src/telemetry.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ def __init__(self):
157157
self.config = TelemetryConfig()
158158
self._customer_uuid: Optional[str] = None
159159
self._milestones: Dict[str, Dict[str, Any]] = {}
160+
self._lock: threading.Lock = threading.Lock()
160161
self._load_persistent_data()
161162

162163
def _load_persistent_data(self):
@@ -199,18 +200,16 @@ def record_milestone(self, milestone: MilestoneType, data: Optional[Dict[str, An
199200
"""Record a milestone event, returns True if this is the first occurrence"""
200201
if not self.config.enabled:
201202
return False
202-
203203
milestone_key = milestone.value
204-
if milestone_key in self._milestones:
205-
return False # Already recorded
206-
207-
milestone_data = {
208-
"timestamp": time.time(),
209-
"data": data or {}
210-
}
211-
212-
self._milestones[milestone_key] = milestone_data
213-
self._save_milestones()
204+
with self._lock:
205+
if milestone_key in self._milestones:
206+
return False # Already recorded
207+
milestone_data = {
208+
"timestamp": time.time(),
209+
"data": data or {},
210+
}
211+
self._milestones[milestone_key] = milestone_data
212+
self._save_milestones()
214213

215214
# Also send as telemetry record
216215
self.record(

0 commit comments

Comments
 (0)