diff --git a/src/uipath/_cli/_utils/_common.py b/src/uipath/_cli/_utils/_common.py index 23208f8d1..ca1515160 100644 --- a/src/uipath/_cli/_utils/_common.py +++ b/src/uipath/_cli/_utils/_common.py @@ -1,4 +1,5 @@ import json +import logging import os import uuid from datetime import date, datetime, time @@ -20,6 +21,8 @@ StudioProjectMetadata, ) +logger = logging.getLogger(__name__) + def get_claim_from_token(claim_name: str) -> str | None: import jwt @@ -202,6 +205,12 @@ async def read_resource_overwrites_from_file( try: with open(file_path, "r") as f: data = json.load(f) + print("loading overwrites...") + print(data) + logger.info("loading overwrites logger info...") + logger.debug("loading overwrites logger debug...") + logger.warning("loading overwrites logger warn...") + resource_overwrites = ( data.get("runtime", {}) .get("internalArguments", {}) @@ -210,10 +219,16 @@ async def read_resource_overwrites_from_file( for key, value in resource_overwrites.items(): overwrites_dict[key] = ResourceOverwriteParser.parse(key, value) + logger.debug( + "Loaded %d resource overwrite(s) from file %s", + len(overwrites_dict), + file_path, + ) + # Return empty dict if file doesn't exist or invalid json except FileNotFoundError: - pass - except json.JSONDecodeError: - pass + logger.debug("Resource overwrites config file not found: %s", file_path) + except json.JSONDecodeError as e: + logger.warning("Failed to parse resource overwrites from %s: %s", file_path, e) return overwrites_dict diff --git a/src/uipath/_cli/_utils/_studio_project.py b/src/uipath/_cli/_utils/_studio_project.py index 320440503..30ab8e192 100644 --- a/src/uipath/_cli/_utils/_studio_project.py +++ b/src/uipath/_cli/_utils/_studio_project.py @@ -1,4 +1,5 @@ import json +import logging import os from enum import Enum from functools import wraps @@ -21,6 +22,8 @@ from uipath.platform.errors import EnrichedException from uipath.tracing import traced +logger = logging.getLogger(__name__) + class NonCodedAgentProjectException(Exception): """Raised when the targeted project is not a coded agent one.""" @@ -545,6 +548,10 @@ async def get_resource_overwrites(self) -> dict[str, ResourceOverwrite]: dict[str, ResourceOverwrite]: Dict of resource overwrites """ if not os.path.exists(UiPathConfig.bindings_file_path): + logger.debug( + "Bindings file not found at %s, no overwrites to fetch from Studio", + UiPathConfig.bindings_file_path, + ) return {} with open(UiPathConfig.bindings_file_path, "rb") as f: @@ -577,6 +584,12 @@ async def get_resource_overwrites(self) -> dict[str, ResourceOverwrite]: for key, value in data.items(): overwrites[key] = ResourceOverwriteParser.parse(key, value) + logger.debug( + "Loaded %d resource overwrite(s) from Studio API for solution %s", + len(overwrites), + solution_id, + ) + return overwrites async def create_virtual_resource( diff --git a/src/uipath/_cli/cli_debug.py b/src/uipath/_cli/cli_debug.py index ab757f53a..411ff9616 100644 --- a/src/uipath/_cli/cli_debug.py +++ b/src/uipath/_cli/cli_debug.py @@ -1,5 +1,6 @@ import asyncio import json +import logging import uuid from pathlib import Path @@ -38,6 +39,7 @@ from .middlewares import Middlewares console = ConsoleLogger() +logger = logging.getLogger(__name__) def load_simulation_config() -> MockingContext | None: @@ -244,6 +246,9 @@ async def execute_debug_runtime(): options=UiPathExecuteOptions(resume=resume), ) else: + logger.debug( + "No UIPATH_PROJECT_ID configured, executing without resource overwrites" + ) ctx.result = await debug_runtime.execute( ctx.get_input(), options=UiPathExecuteOptions(resume=resume), diff --git a/src/uipath/_cli/cli_eval.py b/src/uipath/_cli/cli_eval.py index 7bc4e1898..84b59af9c 100644 --- a/src/uipath/_cli/cli_eval.py +++ b/src/uipath/_cli/cli_eval.py @@ -415,7 +415,9 @@ async def execute_eval(): event_bus, ) else: - # Fall back to execution without overwrites + logger.debug( + "No UIPATH_PROJECT_ID configured, executing evaluation without resource overwrites" + ) ctx.result = await evaluate( runtime_factory, trace_manager, diff --git a/src/uipath/_utils/_bindings.py b/src/uipath/_utils/_bindings.py index d65ac8503..c591a4336 100644 --- a/src/uipath/_utils/_bindings.py +++ b/src/uipath/_utils/_bindings.py @@ -1,5 +1,6 @@ import functools import inspect +import logging from abc import ABC, abstractmethod from contextvars import ContextVar, Token from typing import ( @@ -15,6 +16,8 @@ from pydantic import AliasChoices, BaseModel, ConfigDict, Field, TypeAdapter +logger = logging.getLogger(__name__) + T = TypeVar("T") @@ -128,13 +131,31 @@ def __init__( self.overwrites_count = 0 async def __aenter__(self) -> "ResourceOverwritesContext": + existing = _resource_overwrites.get() + if existing is not None: + logger.warning( + "Entering ResourceOverwritesContext while another context is already active (%d existing overwrite(s))", + len(existing), + ) overwrites = await self.get_overwrites_callable() self._token = _resource_overwrites.set(overwrites) self.overwrites_count = len(overwrites) + if overwrites: + logger.info( + "Resource overwrites context entered: %d overwrite(s) loaded, keys=%s", + len(overwrites), + list(overwrites.keys()), + ) + else: + logger.debug("Resource overwrites context entered: no overwrites loaded") return self async def __aexit__(self, exc_type, exc_val, exc_tb): if self._token: + logger.debug( + "Resource overwrites context exited: %d overwrite(s) cleared", + self.overwrites_count, + ) _resource_overwrites.reset(self._token) @@ -196,6 +217,8 @@ def process_args(args, kwargs) -> dict[str, Any]: # Apply the matched overwrite if matched_overwrite is not None: + old_resource = all_args.get(resource_identifier) + old_folder = all_args.get(folder_identifier) if resource_identifier in sig.parameters: all_args[resource_identifier] = ( matched_overwrite.resource_identifier @@ -204,6 +227,24 @@ def process_args(args, kwargs) -> dict[str, Any]: all_args[folder_identifier] = ( matched_overwrite.folder_identifier ) + logger.info( + "Resource overwrite applied for %s on %s: %s='%s' -> '%s', %s='%s' -> '%s'", + resource_type, + func.__name__, + resource_identifier, + old_resource, + matched_overwrite.resource_identifier, + folder_identifier, + old_folder, + matched_overwrite.folder_identifier, + ) + else: + logger.debug( + "No resource overwrite matched for %s key='%s' on %s", + resource_type, + key, + func.__name__, + ) return all_args