move analytics code from scripts to skyvern module (#32)

This commit is contained in:
Shuchang Zheng
2024-03-06 19:06:15 -08:00
committed by GitHub
parent 213ef9d325
commit 7085334607
9 changed files with 27 additions and 26 deletions

View File

@@ -8,5 +8,4 @@ if [ ! -f .env ]; then
fi fi
source "$(poetry env info --path)/bin/activate" source "$(poetry env info --path)/bin/activate"
./run_alembic_check.sh ./run_alembic_check.sh
python scripts/tracking.py skyvern-oss-run-server
poetry run python -m skyvern.forge poetry run python -m skyvern.forge

View File

@@ -1,5 +1,2 @@
source "$(poetry env info --path)/bin/activate" source "$(poetry env info --path)/bin/activate"
python scripts/tracking.py skyvern-oss-run-ui
streamlit run streamlit_app/visualizer/streamlit.py -- $@ streamlit run streamlit_app/visualizer/streamlit.py -- $@

View File

@@ -3,7 +3,7 @@
# Call function to send telemetry event # Call function to send telemetry event
log_event() { log_event() {
if [ -n $1 ]; then if [ -n $1 ]; then
python scripts/tracking.py $1 python skyvern/analytics.py $1
fi fi
} }
@@ -36,7 +36,7 @@ initialize_env_file() {
# Ask for email or generate UUID # Ask for email or generate UUID
read -p "Please enter your email for analytics tracking (press enter to skip): " analytics_id read -p "Please enter your email for analytics (press enter to skip): " analytics_id
if [ -z "$analytics_id" ]; then if [ -z "$analytics_id" ]; then
analytics_id=$(uuidgen) analytics_id=$(uuidgen)
fi fi
@@ -140,4 +140,4 @@ main() {
} }
# Execute main function # Execute main function
main main

View File

@@ -3,12 +3,14 @@ import uvicorn
from dotenv import load_dotenv from dotenv import load_dotenv
import skyvern.forge.sdk.forge_log as forge_log import skyvern.forge.sdk.forge_log as forge_log
from skyvern import analytics
from skyvern.forge.sdk.settings_manager import SettingsManager from skyvern.forge.sdk.settings_manager import SettingsManager
LOG = structlog.stdlib.get_logger() LOG = structlog.stdlib.get_logger()
if __name__ == "__main__": if __name__ == "__main__":
analytics.capture("skyvern-oss-run-server")
forge_log.setup_logger() forge_log.setup_logger()
port = SettingsManager.get_settings().PORT port = SettingsManager.get_settings().PORT
LOG.info("Agent server starting.", host="0.0.0.0", port=port) LOG.info("Agent server starting.", host="0.0.0.0", port=port)

View File

@@ -8,7 +8,7 @@ import requests
import structlog import structlog
from playwright._impl._errors import TargetClosedError from playwright._impl._errors import TargetClosedError
from scripts import tracking from skyvern import analytics
from skyvern.exceptions import ( from skyvern.exceptions import (
BrowserStateMissingPage, BrowserStateMissingPage,
FailedToSendWebhook, FailedToSendWebhook,
@@ -195,7 +195,7 @@ class ForgeAgent(Agent):
await self.validate_step_execution(task, step) await self.validate_step_execution(task, step)
step, browser_state, detailed_output = await self._initialize_execution_state(task, step, workflow_run) step, browser_state, detailed_output = await self._initialize_execution_state(task, step, workflow_run)
step, detailed_output = await self.agent_step(task, step, browser_state, organization=organization) step, detailed_output = await self.agent_step(task, step, browser_state, organization=organization)
tracking.capture("skyvern-oss-agent-step-status", {"status": step.status}) analytics.capture("skyvern-oss-agent-step-status", {"status": step.status})
retry = False retry = False
# If the step failed, mark the step as failed and retry # If the step failed, mark the step as failed and retry
@@ -674,7 +674,7 @@ class ForgeAgent(Agent):
raise TaskNotFound(task_id=task.task_id) from e raise TaskNotFound(task_id=task.task_id) from e
task = refreshed_task task = refreshed_task
# log the task status as an event # log the task status as an event
tracking.capture("skyvern-oss-agent-task-status", {"status": task.status}) analytics.capture("skyvern-oss-agent-task-status", {"status": task.status})
# Take one last screenshot and create an artifact before closing the browser to see the final state # Take one last screenshot and create an artifact before closing the browser to see the final state
browser_state: BrowserState = await app.BROWSER_MANAGER.get_or_create_for_task(task) browser_state: BrowserState = await app.BROWSER_MANAGER.get_or_create_for_task(task)
page = await browser_state.get_or_create_page() page = await browser_state.get_or_create_page()

View File

@@ -5,7 +5,7 @@ from fastapi import APIRouter, BackgroundTasks, Depends, Header, HTTPException,
from fastapi.responses import ORJSONResponse from fastapi.responses import ORJSONResponse
from pydantic import BaseModel from pydantic import BaseModel
from scripts import tracking from skyvern import analytics
from skyvern.exceptions import StepNotFound from skyvern.exceptions import StepNotFound
from skyvern.forge import app from skyvern.forge import app
from skyvern.forge.sdk.artifact.models import Artifact, ArtifactType from skyvern.forge.sdk.artifact.models import Artifact, ArtifactType
@@ -32,7 +32,7 @@ async def webhook(
x_skyvern_signature: Annotated[str | None, Header()] = None, x_skyvern_signature: Annotated[str | None, Header()] = None,
x_skyvern_timestamp: Annotated[str | None, Header()] = None, x_skyvern_timestamp: Annotated[str | None, Header()] = None,
) -> Response: ) -> Response:
tracking.capture("skyvern-oss-agent-webhook-received") analytics.capture("skyvern-oss-agent-webhook-received")
payload = await request.body() payload = await request.body()
if not x_skyvern_signature or not x_skyvern_timestamp: if not x_skyvern_signature or not x_skyvern_timestamp:
@@ -77,7 +77,7 @@ async def create_agent_task(
x_api_key: Annotated[str | None, Header()] = None, x_api_key: Annotated[str | None, Header()] = None,
x_max_steps_override: Annotated[int | None, Header()] = None, x_max_steps_override: Annotated[int | None, Header()] = None,
) -> CreateTaskResponse: ) -> CreateTaskResponse:
tracking.capture("skyvern-oss-agent-task-create", data={"url": task.url}) analytics.capture("skyvern-oss-agent-task-create", data={"url": task.url})
agent = request["agent"] agent = request["agent"]
created_task = await agent.create_task(task, current_org.organization_id) created_task = await agent.create_task(task, current_org.organization_id)
@@ -111,7 +111,7 @@ async def execute_agent_task_step(
step_id: str | None = None, step_id: str | None = None,
current_org: Organization = Depends(org_auth_service.get_current_org), current_org: Organization = Depends(org_auth_service.get_current_org),
) -> Response: ) -> Response:
tracking.capture("skyvern-oss-agent-task-step-execute") analytics.capture("skyvern-oss-agent-task-step-execute")
agent = request["agent"] agent = request["agent"]
task = await app.DATABASE.get_task(task_id, organization_id=current_org.organization_id) task = await app.DATABASE.get_task(task_id, organization_id=current_org.organization_id)
if not task: if not task:
@@ -170,7 +170,7 @@ async def get_task(
task_id: str, task_id: str,
current_org: Organization = Depends(org_auth_service.get_current_org), current_org: Organization = Depends(org_auth_service.get_current_org),
) -> TaskResponse: ) -> TaskResponse:
tracking.capture("skyvern-oss-agent-task-get") analytics.capture("skyvern-oss-agent-task-get")
request["agent"] request["agent"]
task_obj = await app.DATABASE.get_task(task_id, organization_id=current_org.organization_id) task_obj = await app.DATABASE.get_task(task_id, organization_id=current_org.organization_id)
if not task_obj: if not task_obj:
@@ -234,7 +234,7 @@ async def retry_webhook(
current_org: Organization = Depends(org_auth_service.get_current_org), current_org: Organization = Depends(org_auth_service.get_current_org),
x_api_key: Annotated[str | None, Header()] = None, x_api_key: Annotated[str | None, Header()] = None,
) -> TaskResponse: ) -> TaskResponse:
tracking.capture("skyvern-oss-agent-task-retry-webhook") analytics.capture("skyvern-oss-agent-task-retry-webhook")
agent = request["agent"] agent = request["agent"]
task_obj = await agent.db.get_task(task_id, organization_id=current_org.organization_id) task_obj = await agent.db.get_task(task_id, organization_id=current_org.organization_id)
if not task_obj: if not task_obj:
@@ -268,7 +268,7 @@ async def get_task_internal(
:return: List of tasks with pagination without steps populated. Steps can be populated by calling the :return: List of tasks with pagination without steps populated. Steps can be populated by calling the
get_agent_task endpoint. get_agent_task endpoint.
""" """
tracking.capture("skyvern-oss-agent-task-get-internal") analytics.capture("skyvern-oss-agent-task-get-internal")
task = await app.DATABASE.get_task(task_id, organization_id=current_org.organization_id) task = await app.DATABASE.get_task(task_id, organization_id=current_org.organization_id)
if not task: if not task:
raise HTTPException( raise HTTPException(
@@ -293,7 +293,7 @@ async def get_agent_tasks(
:return: List of tasks with pagination without steps populated. Steps can be populated by calling the :return: List of tasks with pagination without steps populated. Steps can be populated by calling the
get_agent_task endpoint. get_agent_task endpoint.
""" """
tracking.capture("skyvern-oss-agent-tasks-get") analytics.capture("skyvern-oss-agent-tasks-get")
request["agent"] request["agent"]
tasks = await app.DATABASE.get_tasks(page, page_size, organization_id=current_org.organization_id) tasks = await app.DATABASE.get_tasks(page, page_size, organization_id=current_org.organization_id)
return ORJSONResponse([task.to_task_response().model_dump() for task in tasks]) return ORJSONResponse([task.to_task_response().model_dump() for task in tasks])
@@ -314,7 +314,7 @@ async def get_agent_tasks_internal(
:return: List of tasks with pagination without steps populated. Steps can be populated by calling the :return: List of tasks with pagination without steps populated. Steps can be populated by calling the
get_agent_task endpoint. get_agent_task endpoint.
""" """
tracking.capture("skyvern-oss-agent-tasks-get-internal") analytics.capture("skyvern-oss-agent-tasks-get-internal")
request["agent"] request["agent"]
tasks = await app.DATABASE.get_tasks(page, page_size, organization_id=current_org.organization_id) tasks = await app.DATABASE.get_tasks(page, page_size, organization_id=current_org.organization_id)
return ORJSONResponse([task.model_dump() for task in tasks]) return ORJSONResponse([task.model_dump() for task in tasks])
@@ -332,7 +332,7 @@ async def get_agent_task_steps(
:param task_id: :param task_id:
:return: List of steps for a task with pagination. :return: List of steps for a task with pagination.
""" """
tracking.capture("skyvern-oss-agent-task-steps-get") analytics.capture("skyvern-oss-agent-task-steps-get")
request["agent"] request["agent"]
steps = await app.DATABASE.get_task_steps(task_id, organization_id=current_org.organization_id) steps = await app.DATABASE.get_task_steps(task_id, organization_id=current_org.organization_id)
return ORJSONResponse([step.model_dump() for step in steps]) return ORJSONResponse([step.model_dump() for step in steps])
@@ -352,7 +352,7 @@ async def get_agent_task_step_artifacts(
:param step_id: :param step_id:
:return: List of artifacts for a list of steps. :return: List of artifacts for a list of steps.
""" """
tracking.capture("skyvern-oss-agent-task-step-artifacts-get") analytics.capture("skyvern-oss-agent-task-step-artifacts-get")
request["agent"] request["agent"]
artifacts = await app.DATABASE.get_artifacts_for_task_step( artifacts = await app.DATABASE.get_artifacts_for_task_step(
task_id, task_id,
@@ -375,7 +375,7 @@ async def get_task_actions(
task_id: str, task_id: str,
current_org: Organization = Depends(org_auth_service.get_current_org), current_org: Organization = Depends(org_auth_service.get_current_org),
) -> list[ActionResultTmp]: ) -> list[ActionResultTmp]:
tracking.capture("skyvern-oss-agent-task-actions-get") analytics.capture("skyvern-oss-agent-task-actions-get")
request["agent"] request["agent"]
steps = await app.DATABASE.get_task_step_models(task_id, organization_id=current_org.organization_id) steps = await app.DATABASE.get_task_step_models(task_id, organization_id=current_org.organization_id)
results: list[ActionResultTmp] = [] results: list[ActionResultTmp] = []
@@ -397,7 +397,7 @@ async def execute_workflow(
x_api_key: Annotated[str | None, Header()] = None, x_api_key: Annotated[str | None, Header()] = None,
x_max_steps_override: Annotated[int | None, Header()] = None, x_max_steps_override: Annotated[int | None, Header()] = None,
) -> RunWorkflowResponse: ) -> RunWorkflowResponse:
tracking.capture("skyvern-oss-agent-workflow-execute") analytics.capture("skyvern-oss-agent-workflow-execute")
LOG.info( LOG.info(
f"Running workflow {workflow_id}", f"Running workflow {workflow_id}",
workflow_id=workflow_id, workflow_id=workflow_id,
@@ -434,7 +434,7 @@ async def get_workflow_run(
workflow_run_id: str, workflow_run_id: str,
current_org: Organization = Depends(org_auth_service.get_current_org), current_org: Organization = Depends(org_auth_service.get_current_org),
) -> WorkflowRunStatusResponse: ) -> WorkflowRunStatusResponse:
tracking.capture("skyvern-oss-agent-workflow-run-get") analytics.capture("skyvern-oss-agent-workflow-run-get")
request["agent"] request["agent"]
return await app.WORKFLOW_SERVICE.build_workflow_run_status_response( return await app.WORKFLOW_SERVICE.build_workflow_run_status_response(
workflow_id=workflow_id, workflow_run_id=workflow_run_id, organization_id=current_org.organization_id workflow_id=workflow_id, workflow_run_id=workflow_run_id, organization_id=current_org.organization_id

View File

@@ -6,7 +6,7 @@ from datetime import datetime
import requests import requests
import structlog import structlog
from scripts import tracking from skyvern import analytics
from skyvern.exceptions import ( from skyvern.exceptions import (
FailedToSendWebhook, FailedToSendWebhook,
MissingValueForParameter, MissingValueForParameter,
@@ -375,7 +375,7 @@ class WorkflowService:
api_key: str | None = None, api_key: str | None = None,
close_browser_on_completion: bool = True, close_browser_on_completion: bool = True,
) -> None: ) -> None:
tracking.capture("skyvern-oss-agent-workflow-status", {"status": workflow_run.status}) analytics.capture("skyvern-oss-agent-workflow-status", {"status": workflow_run.status})
browser_state = await app.BROWSER_MANAGER.cleanup_for_workflow_run( browser_state = await app.BROWSER_MANAGER.cleanup_for_workflow_run(
workflow_run.workflow_run_id, close_browser_on_completion workflow_run.workflow_run_id, close_browser_on_completion
) )

View File

@@ -4,6 +4,7 @@ import clipboard
import pandas as pd import pandas as pd
import streamlit as st import streamlit as st
from skyvern import analytics
from skyvern.forge.sdk.schemas.tasks import ProxyLocation, TaskRequest from skyvern.forge.sdk.schemas.tasks import ProxyLocation, TaskRequest
from streamlit_app.visualizer import styles from streamlit_app.visualizer import styles
from streamlit_app.visualizer.api import SkyvernClient from streamlit_app.visualizer.api import SkyvernClient
@@ -15,6 +16,8 @@ from streamlit_app.visualizer.artifact_loader import (
from streamlit_app.visualizer.repository import TaskRepository from streamlit_app.visualizer.repository import TaskRepository
from streamlit_app.visualizer.sample_data import supported_examples from streamlit_app.visualizer.sample_data import supported_examples
analytics.capture("skyvern-oss-run-ui")
# Streamlit UI Configuration # Streamlit UI Configuration
st.set_page_config(layout="wide") st.set_page_config(layout="wide")