mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-09-22 19:06:25 +00:00
feat(telemetry): count deployments from any origin and record where they started (#6974)
Deployments were only countable through two span types that no aggregation reads, and cli_usage:deploy counted the TUI button rather than deployments. Emit deploy:created and deploy:pushed alongside the existing spans so a deployment is countable from the feature-usage aggregation no matter how it was started, and tag Create Crew Deployment / Start Deployment with source=cli|tui so the two origins stay distinguishable. Separately, the TUI's `t` and `d` key bindings dispatch straight to action_view_traces / action_deploy_crew, which never recorded anything - only on_button_pressed did. Every keyboard-driven trace view and deploy was therefore invisible. Move the recording into the actions, which both input paths funnel through, and past the completed guard so a mid-run keypress that does nothing is not counted as usage. Claude-Session: https://claude.ai/code/session_01ASfWmW3RGy4qAQm6s8U9jH Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1027,6 +1027,9 @@ FooterKey .footer-key--key {
|
||||
def action_view_traces(self) -> None:
|
||||
if self._status != "completed":
|
||||
return
|
||||
# Recorded here rather than in on_button_pressed so the `t` key binding
|
||||
# is counted too, and only once the action can actually do something.
|
||||
self._record_tui_button_click("view_traces")
|
||||
if self._trace_url:
|
||||
import webbrowser
|
||||
|
||||
@@ -1115,6 +1118,9 @@ FooterKey .footer-key--key {
|
||||
def action_deploy_crew(self) -> None:
|
||||
if self._status != "completed":
|
||||
return
|
||||
# Recorded here rather than in on_button_pressed so the `d` key binding
|
||||
# is counted too, and only once the action can actually do something.
|
||||
self._record_tui_button_click("deploy")
|
||||
self._want_deploy = True
|
||||
self._unsubscribe()
|
||||
self.exit(self._crew_result)
|
||||
@@ -1130,10 +1136,8 @@ FooterKey .footer-key--key {
|
||||
|
||||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||||
if event.button.id in ("btn-traces", "btn-traces-done"):
|
||||
self._record_tui_button_click("view_traces")
|
||||
self.action_view_traces()
|
||||
elif event.button.id == "btn-deploy":
|
||||
self._record_tui_button_click("deploy")
|
||||
self.action_deploy_crew()
|
||||
|
||||
def _scroll_to_result(self) -> None:
|
||||
|
||||
@@ -5,6 +5,7 @@ from urllib.parse import quote
|
||||
import webbrowser
|
||||
|
||||
from crewai_core.plus_api import CreateCrewPayload
|
||||
from crewai_core.telemetry import DeploySource
|
||||
from rich.console import Console
|
||||
|
||||
from crewai_cli import git
|
||||
@@ -285,17 +286,23 @@ class DeployCommand(BaseCommand, PlusAPIMixin):
|
||||
|
||||
return _deployment_identifier(status_response)
|
||||
|
||||
def deploy(self, uuid: str | None = None, skip_validate: bool = False) -> None:
|
||||
def deploy(
|
||||
self,
|
||||
uuid: str | None = None,
|
||||
skip_validate: bool = False,
|
||||
source: DeploySource = "cli",
|
||||
) -> None:
|
||||
"""
|
||||
Deploy a crew using either UUID or project name.
|
||||
|
||||
Args:
|
||||
uuid (Optional[str]): The UUID of the crew to deploy.
|
||||
skip_validate (bool): Skip pre-deploy validation checks.
|
||||
source (DeploySource): Where the deployment was initiated from.
|
||||
"""
|
||||
if not _prepare_project_for_deploy(skip_validate):
|
||||
return
|
||||
self._telemetry.start_deployment_span(uuid)
|
||||
self._telemetry.start_deployment_span(uuid, source=source)
|
||||
console.print("Starting deployment...", style="bold blue")
|
||||
repository = self._prepare_git_repository()
|
||||
remote_repo_url = repository.origin_url() if repository else None
|
||||
@@ -337,17 +344,23 @@ class DeployCommand(BaseCommand, PlusAPIMixin):
|
||||
raise ValueError("Deployment status response did not include a uuid")
|
||||
return str(uuid)
|
||||
|
||||
def create_crew(self, confirm: bool = False, skip_validate: bool = False) -> None:
|
||||
def create_crew(
|
||||
self,
|
||||
confirm: bool = False,
|
||||
skip_validate: bool = False,
|
||||
source: DeploySource = "cli",
|
||||
) -> None:
|
||||
"""
|
||||
Create a new crew deployment.
|
||||
|
||||
Args:
|
||||
confirm (bool): Whether to skip the interactive confirmation prompt.
|
||||
skip_validate (bool): Skip pre-deploy validation checks.
|
||||
source (DeploySource): Where the deployment was initiated from.
|
||||
"""
|
||||
if not _prepare_project_for_deploy(skip_validate):
|
||||
return
|
||||
self._telemetry.create_crew_deployment_span()
|
||||
self._telemetry.create_crew_deployment_span(source=source)
|
||||
console.print("Creating deployment...", style="bold blue")
|
||||
env_vars = fetch_and_json_env_file()
|
||||
repository = self._prepare_git_repository()
|
||||
|
||||
@@ -512,14 +512,14 @@ def _chain_deploy() -> None:
|
||||
from crewai_cli.deploy.main import DeployCommand
|
||||
|
||||
console.print("\nStarting deployment…\n", style="bold #FF5A50")
|
||||
DeployCommand().create_crew(confirm=True, skip_validate=True)
|
||||
DeployCommand().create_crew(confirm=True, skip_validate=True, source="tui")
|
||||
except AuthenticationRequiredError:
|
||||
from crewai_cli.authentication.main import AuthenticationCommand
|
||||
|
||||
console.print()
|
||||
AuthenticationCommand().login()
|
||||
try:
|
||||
DeployCommand().create_crew(confirm=True, skip_validate=True)
|
||||
DeployCommand().create_crew(confirm=True, skip_validate=True, source="tui")
|
||||
except AuthenticationRequiredError:
|
||||
console.print(
|
||||
"\nDeploy failed: authentication is still required.\n",
|
||||
|
||||
Reference in New Issue
Block a user