diff --git a/src/snowflake/cli/_plugins/nativeapp/artifacts.py b/src/snowflake/cli/_plugins/nativeapp/artifacts.py index 9c99cf8047..b5114e30f6 100644 --- a/src/snowflake/cli/_plugins/nativeapp/artifacts.py +++ b/src/snowflake/cli/_plugins/nativeapp/artifacts.py @@ -650,7 +650,7 @@ def resolve_without_follow(path: Path) -> Path: return Path(os.path.abspath(path)) -@span("build_initial_bundle") +@span("bundle") def build_bundle( project_root: Path, deploy_root: Path, diff --git a/src/snowflake/cli/_plugins/nativeapp/entities/application.py b/src/snowflake/cli/_plugins/nativeapp/entities/application.py index 87493a7146..040e60e82f 100644 --- a/src/snowflake/cli/_plugins/nativeapp/entities/application.py +++ b/src/snowflake/cli/_plugins/nativeapp/entities/application.py @@ -57,7 +57,11 @@ from snowflake.cli._plugins.workspace.context import ActionContext from snowflake.cli.api.cli_global_context import get_cli_context, span from snowflake.cli.api.console.abc import AbstractConsole -from snowflake.cli.api.entities.common import EntityBase, get_sql_executor +from snowflake.cli.api.entities.common import ( + EntityBase, + attach_spans_to_entity_actions, + get_sql_executor, +) from snowflake.cli.api.entities.utils import ( drop_generic_object, execute_post_deploy_hooks, @@ -321,6 +325,7 @@ def append_test_resource_suffix_to_identifier( return with_suffix +@attach_spans_to_entity_actions(entity_name="app") class ApplicationEntity(EntityBase[ApplicationEntityModel]): """ A Native App application object, created from an application package. @@ -355,7 +360,6 @@ def post_deploy_hooks(self) -> list[PostDeployHook] | None: model = self._entity_model return model.meta and model.meta.post_deploy - @span("deploy_app") def action_deploy( self, action_ctx: ActionContext, @@ -440,7 +444,6 @@ def action_deploy( interactive=interactive, ) - @span("drop_app") def action_drop( self, action_ctx: ActionContext, diff --git a/src/snowflake/cli/_plugins/nativeapp/entities/application_package.py b/src/snowflake/cli/_plugins/nativeapp/entities/application_package.py index 9f60355d03..52538cd222 100644 --- a/src/snowflake/cli/_plugins/nativeapp/entities/application_package.py +++ b/src/snowflake/cli/_plugins/nativeapp/entities/application_package.py @@ -50,7 +50,11 @@ from snowflake.cli._plugins.stage.manager import StageManager from snowflake.cli._plugins.workspace.context import ActionContext from snowflake.cli.api.cli_global_context import span -from snowflake.cli.api.entities.common import EntityBase, get_sql_executor +from snowflake.cli.api.entities.common import ( + EntityBase, + attach_spans_to_entity_actions, + get_sql_executor, +) from snowflake.cli.api.entities.utils import ( drop_generic_object, execute_post_deploy_hooks, @@ -157,6 +161,7 @@ def validate_source_stage(cls, input_value: str): return input_value +@attach_spans_to_entity_actions(entity_name="app_pkg") class ApplicationPackageEntity(EntityBase[ApplicationPackageEntityModel]): """ A Native App application package. @@ -235,7 +240,6 @@ def action_deploy( force=force, ) - @span("drop_app_package") def action_drop(self, action_ctx: ActionContext, force_drop: bool, *args, **kwargs): console = self._workspace_ctx.console sql_executor = get_sql_executor() @@ -553,7 +557,6 @@ def _bundle(self): compiler.compile_artifacts() return bundle_map - @span("deploy_app_package") def _deploy( self, bundle_map: BundleMap | None, diff --git a/src/snowflake/cli/api/console/console.py b/src/snowflake/cli/api/console/console.py index b294d4ccc6..94c80c9cc9 100644 --- a/src/snowflake/cli/api/console/console.py +++ b/src/snowflake/cli/api/console/console.py @@ -64,11 +64,7 @@ def _format_message(self, message: str, output: Output) -> Text: return text @contextmanager - def phase( - self, - enter_message: str, - exit_message: Optional[str] = None, - ): + def phase(self, enter_message: str, exit_message: Optional[str] = None): """A context manager for organising steps into logical group.""" self._print(self._format_message(enter_message, Output.PHASE)) self._extra_indent += 1 diff --git a/src/snowflake/cli/api/entities/common.py b/src/snowflake/cli/api/entities/common.py index 9f98f970ec..3c377bae2f 100644 --- a/src/snowflake/cli/api/entities/common.py +++ b/src/snowflake/cli/api/entities/common.py @@ -2,6 +2,7 @@ from typing import Generic, Type, TypeVar, get_args from snowflake.cli._plugins.workspace.context import ActionContext, WorkspaceContext +from snowflake.cli.api.cli_global_context import span from snowflake.cli.api.sql_execution import SqlExecutor @@ -20,6 +21,23 @@ class EntityActions(str, Enum): T = TypeVar("T") +def attach_spans_to_entity_actions(entity_name: str): + def decorator(cls): + for attr_name, attr_value in vars(cls).items(): + is_entity_action = attr_name in [ + enum_member for enum_member in EntityActions + ] + + if is_entity_action and callable(attr_value): + attr_name_without_action_prefix = attr_name.partition("_")[2] + span_name = f"action.{entity_name}.{attr_name_without_action_prefix}" + action_with_span = span(span_name)(attr_value) + setattr(cls, attr_name, action_with_span) + return cls + + return decorator + + class EntityBase(Generic[T]): """ Base class for the fully-featured entity classes. diff --git a/src/snowflake/cli/api/entities/utils.py b/src/snowflake/cli/api/entities/utils.py index 39322364ae..4c5b8b0c78 100644 --- a/src/snowflake/cli/api/entities/utils.py +++ b/src/snowflake/cli/api/entities/utils.py @@ -76,7 +76,7 @@ def _get_stage_paths_to_sync( return stage_paths -@span("sync_remote_and_local_files") +@span("sync_deploy_root_with_stage") def sync_deploy_root_with_stage( console: AbstractConsole, deploy_root: Path, @@ -213,9 +213,10 @@ def execute_post_deploy_hooks( get_cli_context().metrics.set_counter(CLICounterField.POST_DEPLOY_SCRIPTS, 1) - with console.phase( - f"Executing {deployed_object_type} post-deploy actions", - ), get_cli_context().metrics.span("post_deploy_hooks"): + with ( + console.phase(f"Executing {deployed_object_type} post-deploy actions"), + get_cli_context().metrics.span("post_deploy_hooks"), + ): sql_scripts_paths = [] display_paths = [] for hook in post_deploy_hooks: diff --git a/tests_integration/nativeapp/test_metrics.py b/tests_integration/nativeapp/test_metrics.py index a12a5630e4..a1678b3c1c 100644 --- a/tests_integration/nativeapp/test_metrics.py +++ b/tests_integration/nativeapp/test_metrics.py @@ -339,9 +339,7 @@ def test_spans_bundle( assert_spans_within_limits(spans) - assert extract_span_keys_to_check(spans) == [ - {"name": "build_initial_bundle", "parent": None} - ] + assert extract_span_keys_to_check(spans) == [{"name": "bundle", "parent": None}] @pytest.mark.integration @@ -397,40 +395,40 @@ def test_spans_run_with_all_features( assert extract_span_keys_to_check(spans) == [ { - "name": "deploy_app", + "name": "action.app.deploy", "parent": None, }, { - "name": "deploy_app_package", - "parent": "deploy_app", + "name": "action.app_pkg.deploy", + "parent": "action.app.deploy", }, { - "name": "build_initial_bundle", - "parent": "deploy_app_package", + "name": "bundle", + "parent": "action.app_pkg.deploy", }, { "name": "artifact_processors", - "parent": "deploy_app_package", + "parent": "action.app_pkg.deploy", }, { "name": "templates_processor", "parent": "artifact_processors", }, { - "name": "sync_remote_and_local_files", - "parent": "deploy_app_package", + "name": "sync_deploy_root_with_stage", + "parent": "action.app_pkg.deploy", }, { "name": "post_deploy_hooks", - "parent": "deploy_app_package", + "parent": "action.app_pkg.deploy", }, { "name": "validate_setup_script", - "parent": "deploy_app_package", + "parent": "action.app_pkg.deploy", }, { "name": "update_app_object", - "parent": "deploy_app", + "parent": "action.app.deploy", }, { "name": "post_deploy_hooks", @@ -486,20 +484,20 @@ def test_spans_validate( assert extract_span_keys_to_check(spans) == [ { - "name": "validate_setup_script", + "name": "action.app_pkg.validate", "parent": None, }, { - "name": "deploy_app_package", - "parent": "validate_setup_script", + "name": "validate_setup_script", + "parent": "action.app_pkg.validate", }, { - "name": "build_initial_bundle", - "parent": "deploy_app_package", + "name": "bundle", + "parent": "validate_setup_script", }, { - "name": "sync_remote_and_local_files", - "parent": "deploy_app_package", + "name": "sync_deploy_root_with_stage", + "parent": "validate_setup_script", }, ] @@ -546,6 +544,6 @@ def test_spans_teardown( assert_spans_within_limits(spans) assert extract_span_keys_to_check(spans) == [ - {"name": "drop_app", "parent": None}, - {"name": "drop_app_package", "parent": None}, + {"name": "action.app.drop", "parent": None}, + {"name": "action.app_pkg.drop", "parent": None}, ]