diff --git a/src/crewai/__init__.py b/src/crewai/__init__.py index 9545675b1..0bab2ee92 100644 --- a/src/crewai/__init__.py +++ b/src/crewai/__init__.py @@ -1,4 +1,6 @@ import warnings +import threading +import urllib.request from crewai.agent import Agent from crewai.crew import Crew @@ -11,6 +13,7 @@ from crewai.process import Process from crewai.task import Task from crewai.tasks.llm_guardrail import LLMGuardrail from crewai.tasks.task_output import TaskOutput +from crewai.telemetry.telemetry import Telemetry warnings.filterwarnings( "ignore", @@ -18,6 +21,39 @@ warnings.filterwarnings( category=UserWarning, module="pydantic.main", ) + +_telemetry_submitted = False + + +def _track_install(): + """Track package installation/first-use via Scarf analytics.""" + global _telemetry_submitted + + if _telemetry_submitted or Telemetry._is_telemetry_disabled(): + return + + try: + pixel_url = "https://api.scarf.sh/v2/packages/CrewAI/crewai/docs/00f2dad1-8334-4a39-934e-003b2e1146db" + + req = urllib.request.Request(pixel_url) + req.add_header('User-Agent', f'CrewAI-Python/{__version__}') + + with urllib.request.urlopen(req, timeout=2): # nosec B310 + _telemetry_submitted = True + + except Exception: + pass + + +def _track_install_async(): + """Track installation in background thread to avoid blocking imports.""" + if not Telemetry._is_telemetry_disabled(): + thread = threading.Thread(target=_track_install, daemon=True) + thread.start() + + +_track_install_async() + __version__ = "0.134.0" __all__ = [ "Agent", diff --git a/src/crewai/telemetry/telemetry.py b/src/crewai/telemetry/telemetry.py index f75809a02..d43bd276d 100644 --- a/src/crewai/telemetry/telemetry.py +++ b/src/crewai/telemetry/telemetry.py @@ -111,11 +111,13 @@ class Telemetry: raise # Re-raise the exception to not interfere with system signals self.ready = False - def _is_telemetry_disabled(self) -> bool: + @classmethod + def _is_telemetry_disabled(cls) -> bool: """Check if telemetry should be disabled based on environment variables.""" return ( os.getenv("OTEL_SDK_DISABLED", "false").lower() == "true" or os.getenv("CREWAI_DISABLE_TELEMETRY", "false").lower() == "true" + or os.getenv("CREWAI_DISABLE_TRACKING", "false").lower() == "true" ) def _should_execute_telemetry(self) -> bool: