Monitor imports and instrument packages as they are imported. This replaces the built-in import function to intercept package imports.
(name: str, globals_dict=None, locals_dict=None, fromlist=(), level=0)
| 373 | |
| 374 | |
| 375 | def _import_monitor(name: str, globals_dict=None, locals_dict=None, fromlist=(), level=0): |
| 376 | """ |
| 377 | Monitor imports and instrument packages as they are imported. |
| 378 | This replaces the built-in import function to intercept package imports. |
| 379 | """ |
| 380 | global _instrumenting_packages, _has_agentic_library |
| 381 | |
| 382 | # If an agentic library is already instrumented, skip all further instrumentation |
| 383 | if _has_agentic_library: |
| 384 | return _original_builtins_import(name, globals_dict, locals_dict, fromlist, level) |
| 385 | |
| 386 | # First, do the actual import |
| 387 | module = _original_builtins_import(name, globals_dict, locals_dict, fromlist, level) |
| 388 | |
| 389 | # Check for exact matches first (handles package.module like google.adk) |
| 390 | packages_to_check = set() |
| 391 | |
| 392 | # Check the imported module itself |
| 393 | if name in TARGET_PACKAGES: |
| 394 | packages_to_check.add(name) |
| 395 | else: |
| 396 | # Check if any target package is a prefix of the import name |
| 397 | for target in TARGET_PACKAGES: |
| 398 | if name.startswith(target + ".") or name == target: |
| 399 | packages_to_check.add(target) |
| 400 | |
| 401 | # For "from X import Y" style imports, also check submodules |
| 402 | if fromlist: |
| 403 | for item in fromlist: |
| 404 | # Construct potential full name, e.g., "google.adk" from name="google", item="adk" |
| 405 | # Or if name="os", item="path", full_name="os.path" |
| 406 | # If the original name itself is a multi-part name like "a.b", and item is "c", then "a.b.c" |
| 407 | # This logic needs to correctly identify the root package if 'name' is already a sub-package. |
| 408 | # The existing TARGET_PACKAGES check is simpler: it checks against pre-defined full names. |
| 409 | |
| 410 | # Check full name if item forms part of a target package name |
| 411 | full_item_name_candidate = f"{name}.{item}" |
| 412 | |
| 413 | if full_item_name_candidate in TARGET_PACKAGES: |
| 414 | packages_to_check.add(full_item_name_candidate) |
| 415 | else: # Fallback to checking if 'name' itself is a target |
| 416 | for target in TARGET_PACKAGES: |
| 417 | if name == target or name.startswith(target + "."): |
| 418 | packages_to_check.add(target) # Check the base target if a submodule is imported from it. |
| 419 | |
| 420 | # Instrument all matching packages |
| 421 | for package_to_check in packages_to_check: |
| 422 | if package_to_check not in _instrumenting_packages and not _is_package_instrumented(package_to_check): |
| 423 | target_module_obj = sys.modules.get(package_to_check) |
| 424 | |
| 425 | if target_module_obj: |
| 426 | is_sdk = _is_installed_package(target_module_obj, package_to_check) |
| 427 | if not is_sdk: |
| 428 | logger.debug( |
| 429 | f"AgentOps: Target '{package_to_check}' appears to be a local module/directory. Skipping AgentOps SDK instrumentation for it." |
| 430 | ) |
| 431 | continue |
| 432 | else: |
nothing calls this directly
no test coverage detected
searching dependent graphs…