mirror of
https://github.com/langflow-ai/langflow.git
synced 2026-07-26 03:10:37 +08:00
feat: Add common telemetry fields (#7899)
* feat: add common telemetry fields and dynamic timestamp to telemetry payloads * test: Add common telemetry fields to exception telemetry tests - Introduced common telemetry fields including langflow_version, platform, and os to the telemetry service in multiple test cases. - Updated assertions to verify the inclusion of these fields in the telemetry data sent during exception handling. * test: Enhance exception telemetry tests with common telemetry fields - Added common telemetry fields (langflow_version, platform, os) to the telemetry service in multiple test cases. - Updated assertions to ensure these fields are included in the telemetry data during exception handling. --------- Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
d12bb50320
commit
b840b71193
@ -50,6 +50,14 @@ class TelemetryService(Service):
|
||||
self.log_package_version_task: asyncio.Task | None = None
|
||||
self.client_type = self._get_client_type()
|
||||
|
||||
# Initialize static telemetry fields
|
||||
version_info = get_version_info()
|
||||
self.common_telemetry_fields = {
|
||||
"langflow_version": version_info["version"],
|
||||
"platform": "desktop" if self._get_langflow_desktop() else "python_package",
|
||||
"os": platform.system().lower(),
|
||||
}
|
||||
|
||||
async def telemetry_worker(self) -> None:
|
||||
while self.running:
|
||||
func, payload, path = await self.telemetry_queue.get()
|
||||
@ -74,6 +82,14 @@ class TelemetryService(Service):
|
||||
|
||||
try:
|
||||
payload_dict = payload.model_dump(by_alias=True, exclude_none=True, exclude_unset=True)
|
||||
|
||||
# Add common fields to all payloads except VersionPayload
|
||||
if not isinstance(payload, VersionPayload):
|
||||
payload_dict.update(self.common_telemetry_fields)
|
||||
# Add timestamp dynamically
|
||||
if "timestamp" not in payload_dict:
|
||||
payload_dict["timestamp"] = datetime.now(timezone.utc).isoformat()
|
||||
|
||||
response = await self.client.get(url, params=payload_dict)
|
||||
if response.status_code != httpx.codes.OK:
|
||||
await logger.aerror(f"Failed to send telemetry data: {response.status_code} {response.text}")
|
||||
|
||||
@ -26,6 +26,11 @@ class TestExceptionTelemetryIntegration:
|
||||
telemetry_service.base_url = "https://mock-telemetry.example.com"
|
||||
telemetry_service.do_not_track = False
|
||||
telemetry_service.client_type = "oss"
|
||||
telemetry_service.common_telemetry_fields = {
|
||||
"langflow_version": "1.0.0",
|
||||
"platform": "python_package",
|
||||
"os": "darwin",
|
||||
}
|
||||
|
||||
# Mock successful response
|
||||
mock_response = MagicMock()
|
||||
@ -78,6 +83,11 @@ class TestExceptionTelemetryIntegration:
|
||||
telemetry_service.base_url = "https://mock-telemetry.example.com"
|
||||
telemetry_service.do_not_track = False
|
||||
telemetry_service.client_type = "oss"
|
||||
telemetry_service.common_telemetry_fields = {
|
||||
"langflow_version": "1.0.0",
|
||||
"platform": "python_package",
|
||||
"os": "darwin",
|
||||
}
|
||||
|
||||
# Mock the async queue and HTTP client
|
||||
telemetry_service.telemetry_queue = asyncio.Queue()
|
||||
@ -296,21 +306,21 @@ class TestTelemetryPayloadValidation:
|
||||
exception_type="ValueError",
|
||||
exception_message="Invalid input parameter",
|
||||
exception_context="handler",
|
||||
stack_trace_hash="abc123def456",
|
||||
stack_trace_hash="abc123def456", # pragma: allowlist secret
|
||||
client_type="oss",
|
||||
)
|
||||
|
||||
assert payload.exception_type == "ValueError"
|
||||
assert payload.exception_message == "Invalid input parameter"
|
||||
assert payload.exception_context == "handler"
|
||||
assert payload.stack_trace_hash == "abc123def456"
|
||||
assert payload.stack_trace_hash == "abc123def456" # pragma: allowlist secret
|
||||
|
||||
serialized = payload.model_dump(by_alias=True)
|
||||
expected = {
|
||||
"exceptionType": "ValueError",
|
||||
"exceptionMessage": "Invalid input parameter",
|
||||
"exceptionContext": "handler",
|
||||
"stackTraceHash": "abc123def456",
|
||||
"stackTraceHash": "abc123def456", # pragma: allowlist secret
|
||||
"clientType": "oss",
|
||||
}
|
||||
assert serialized == expected
|
||||
|
||||
@ -18,7 +18,7 @@ class TestExceptionTelemetry:
|
||||
exception_type="ValueError",
|
||||
exception_message="Test error message",
|
||||
exception_context="handler",
|
||||
stack_trace_hash="abc123def456",
|
||||
stack_trace_hash="abc123def456", # pragma: allowlist secret
|
||||
)
|
||||
|
||||
# Test serialization with aliases
|
||||
@ -28,7 +28,7 @@ class TestExceptionTelemetry:
|
||||
"exceptionType": "ValueError",
|
||||
"exceptionMessage": "Test error message",
|
||||
"exceptionContext": "handler",
|
||||
"stackTraceHash": "abc123def456",
|
||||
"stackTraceHash": "abc123def456", # pragma: allowlist secret
|
||||
}
|
||||
|
||||
assert data == expected_fields
|
||||
@ -80,6 +80,11 @@ class TestExceptionTelemetry:
|
||||
telemetry_service.base_url = "https://mock-telemetry.example.com"
|
||||
telemetry_service.do_not_track = False
|
||||
telemetry_service.client_type = "oss"
|
||||
telemetry_service.common_telemetry_fields = {
|
||||
"langflow_version": "1.0.0",
|
||||
"platform": "python_package",
|
||||
"os": "linux",
|
||||
}
|
||||
|
||||
# Mock HTTP client
|
||||
mock_response = MagicMock()
|
||||
@ -105,15 +110,17 @@ class TestExceptionTelemetry:
|
||||
# Check URL
|
||||
assert call_args[0][0] == "https://mock-telemetry.example.com/exception"
|
||||
|
||||
# Check query parameters
|
||||
expected_params = {
|
||||
"exceptionType": "ValueError",
|
||||
"exceptionMessage": "Test error",
|
||||
"exceptionContext": "handler",
|
||||
"stackTraceHash": "abc123",
|
||||
"clientType": "oss",
|
||||
}
|
||||
assert call_args[1]["params"] == expected_params
|
||||
# Check query parameters (should include common telemetry fields)
|
||||
params = call_args[1]["params"]
|
||||
assert params["exceptionType"] == "ValueError"
|
||||
assert params["exceptionMessage"] == "Test error"
|
||||
assert params["exceptionContext"] == "handler"
|
||||
assert params["stackTraceHash"] == "abc123"
|
||||
assert params["clientType"] == "oss"
|
||||
assert params["langflow_version"] == "1.0.0"
|
||||
assert params["platform"] == "python_package"
|
||||
assert params["os"] == "linux"
|
||||
assert "timestamp" in params
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_telemetry_data_respects_do_not_track(self):
|
||||
@ -123,6 +130,11 @@ class TestExceptionTelemetry:
|
||||
telemetry_service.base_url = "https://mock-telemetry.example.com"
|
||||
telemetry_service.do_not_track = True
|
||||
telemetry_service.client_type = "oss"
|
||||
telemetry_service.common_telemetry_fields = {
|
||||
"langflow_version": "1.0.0",
|
||||
"platform": "python_package",
|
||||
"os": "linux",
|
||||
}
|
||||
|
||||
# Mock HTTP client
|
||||
mock_client = AsyncMock()
|
||||
@ -173,6 +185,11 @@ class TestExceptionTelemetry:
|
||||
telemetry_service.base_url = "https://mock-telemetry.example.com"
|
||||
telemetry_service.do_not_track = False
|
||||
telemetry_service.client_type = "oss"
|
||||
telemetry_service.common_telemetry_fields = {
|
||||
"langflow_version": "1.0.0",
|
||||
"platform": "python_package",
|
||||
"os": "linux",
|
||||
}
|
||||
|
||||
# Create payload with very long message
|
||||
long_message = "A" * 2000 # Very long message
|
||||
@ -203,6 +220,11 @@ class TestExceptionTelemetry:
|
||||
telemetry_service.base_url = "https://mock-telemetry.example.com"
|
||||
telemetry_service.do_not_track = False
|
||||
telemetry_service.client_type = "oss"
|
||||
telemetry_service.common_telemetry_fields = {
|
||||
"langflow_version": "1.0.0",
|
||||
"platform": "python_package",
|
||||
"os": "linux",
|
||||
}
|
||||
|
||||
# Create payload with special characters
|
||||
special_message = "Error with special chars: &?=#@!$%^&*()"
|
||||
@ -235,6 +257,11 @@ class TestExceptionTelemetry:
|
||||
telemetry_service.base_url = "https://mock-telemetry.example.com"
|
||||
telemetry_service.do_not_track = False
|
||||
telemetry_service.client_type = "oss"
|
||||
telemetry_service.common_telemetry_fields = {
|
||||
"langflow_version": "1.0.0",
|
||||
"platform": "python_package",
|
||||
"os": "linux",
|
||||
}
|
||||
|
||||
# Create payload with potentially sensitive data
|
||||
sensitive_message = "Password: secret123, API Key: sk-abc123, Token: xyz789"
|
||||
@ -267,6 +294,11 @@ class TestExceptionTelemetry:
|
||||
telemetry_service.base_url = "https://mock-telemetry.example.com"
|
||||
telemetry_service.do_not_track = False
|
||||
telemetry_service.client_type = "oss"
|
||||
telemetry_service.common_telemetry_fields = {
|
||||
"langflow_version": "1.0.0",
|
||||
"platform": "python_package",
|
||||
"os": "linux",
|
||||
}
|
||||
|
||||
# Create payload with unicode characters
|
||||
unicode_message = "Error with unicode: 世界, 🚀, émojis"
|
||||
|
||||
Reference in New Issue
Block a user