Skip to content

Decorators not working properly when imported from agentops.sdk.decorators namespace #1110

@devin-ai-integration

Description

@devin-ai-integration
Contributor

Decorators not working properly when imported from agentops.sdk.decorators namespace

Summary

There is a critical issue with AgentOps decorators that affects both import paths:

  1. SDK Namespace Import: Decorators imported from agentops.sdk.decorators fail silently when applied before agentops.init()
  2. Main Namespace Import: Decorators imported from agentops work but have incorrect span timing that breaks parent-child relationships in traces

Problem Description

SDK Namespace Import (Silent Failure)

from agentops.sdk.decorators import trace
from agentops import init

@trace  # Applied before init - becomes a no-op
def my_function():
    return "success"

init(api_key="your-key")  # Too late - decorator already disabled
my_function()  # No span created

Main Namespace Import (Timing Issues)

import agentops
from agentops import trace

agentops.init(api_key="your-key")

@trace  # Works but has timing problems
def parent_function():
    return child_function()

@trace
def child_function():
    return "success"

# Spans created but parent-child timing is incorrect

Root Cause Analysis

Issue 1: SDK Namespace Silent Failure

The primary issue stems from the decorator factory implementation in agentops/sdk/decorators/factory.py at line 84:

@wrapt.decorator
def wrapper(wrapped_func: Callable[..., Any], instance: Optional[Any], args: tuple, kwargs: Dict[str, Any]) -> Any:
    if not tracer.initialized:  # ← This is the problem
        return wrapped_func(*args, **kwargs)

When decorators are imported directly from agentops.sdk.decorators, the tracer.initialized check happens at decoration time (import time), not at function execution time. If AgentOps hasn't been initialized yet when the decorator is applied, the decorator essentially becomes a no-op and never gets a chance to instrument the function properly, even after agentops.init() is called later.

Issue 2: Main Namespace Span Timing Problems

Even when using the main namespace workaround (from agentops import trace), there's a secondary issue with span timing that breaks parent-child relationships:

Problem: Span start times are set when tracer.start_span() is called in _create_as_current_span() (utility.py:122-123), not when the decorated function actually begins execution. This causes:

  1. Incorrect span hierarchy: Child spans may appear to start before their parents
  2. Broken trace visualization: Timeline views show incorrect execution order
  3. Context propagation issues: Parent-child relationships are not properly maintained

Technical Details:

  • _create_as_current_span() uses start_as_current_span() with current timestamp
  • Span timing reflects decorator execution time, not actual function execution time
  • OpenTelemetry context management works but timing metadata is incorrect

Impact

SDK Namespace Issues:

  1. Silent Failures: Functions decorated with @trace, @agent, @tool, etc. imported from the SDK namespace don't get instrumented
  2. Missing Telemetry Data: No spans are created, leading to complete loss of observability
  3. No Error Messages: Failures are completely silent, making debugging difficult

Main Namespace Issues:

  1. Broken Trace Hierarchy: Parent-child relationships appear incorrect in trace visualizations
  2. Timing Inaccuracies: Span start/end times don't reflect actual function execution
  3. Context Propagation Problems: Nested function calls may not maintain proper trace context
  4. Misleading Performance Data: Timing metrics are unreliable for performance analysis

Overall Impact:

  1. Inconsistent Behavior: Same code works differently depending on import path
  2. Data Quality Issues: Telemetry data is either missing or incorrect
  3. Developer Experience: Confusing behavior leads to lost development time

Reproduction Steps

  1. Create a Python script that imports decorators from agentops.sdk.decorators
  2. Apply decorators to functions BEFORE calling agentops.init()
  3. Initialize AgentOps after decoration
  4. Call the decorated functions
  5. Observe that no spans are created and no telemetry is captured

Expected vs Actual Behavior

SDK Namespace

Expected: Decorators should work regardless of import path and should check tracer initialization at function execution time, not decoration time.

Actual: Decorators imported from agentops.sdk.decorators become no-ops if applied before agentops.init() is called.

Main Namespace

Expected: Decorators should create spans with accurate timing that reflects actual function execution and maintains proper parent-child relationships.

Actual: Decorators create spans but with incorrect timing metadata that breaks trace hierarchy visualization and context propagation.

Proposed Solutions

For SDK Namespace Issue:

  1. Move initialization check to execution time: The tracer.initialized check in factory.py:84 should happen when the function is called, not when the decorator is applied
  2. Lazy initialization: Store a reference to check initialization when the decorated function is actually invoked
  3. Decorator state management: Allow decorators to "activate" retroactively when the tracer becomes initialized

For Main Namespace Timing Issue:

  1. Defer span creation: Create spans at function entry time, not decorator application time
  2. Proper timing capture: Ensure span start/end times accurately reflect function execution boundaries
  3. Context preservation: Maintain proper parent-child relationships with correct timing metadata
  4. OpenTelemetry best practices: Follow OTel guidelines for span lifecycle management in decorators

Files Affected

  • agentops/sdk/decorators/factory.py (line 84)
  • agentops/__init__.py (import/export structure)
  • All decorator implementations that use create_entity_decorator

Test Cases Needed

SDK Namespace Tests:

  1. Test decorators imported from agentops.sdk.decorators with various initialization orders
  2. Test that late initialization properly enables previously "no-op" decorators
  3. Test error handling when decorators fail silently

Main Namespace Tests:

  1. Test span timing accuracy for nested function calls
  2. Test parent-child relationship preservation in trace hierarchy
  3. Test context propagation with correct timing metadata
  4. Test performance metric accuracy

Cross-Namespace Tests:

  1. Test mixed import sources in the same application
  2. Test initialization order dependencies
  3. Test behavior consistency across import paths

Workarounds

Current Partial Workaround:

Import decorators from the main agentops namespace and ensure initialization happens before decoration:

import agentops

# Initialize FIRST
agentops.init(api_key="your-key")

# Then import and use decorators
from agentops import trace, agent, tool

@trace
def my_function():
    return "success"

Limitations of Workaround:

  • Still has span timing issues that affect trace visualization
  • Parent-child relationships may appear incorrect in dashboards
  • Performance metrics may be inaccurate
  • Not a complete solution - just reduces the severity of the problem

Priority

Critical - This affects core SDK functionality in multiple ways:

  • Data Loss: Complete telemetry loss with SDK namespace imports
  • Data Quality: Incorrect timing and hierarchy with main namespace imports
  • Silent Failures: No error messages make debugging extremely difficult
  • User Experience: Inconsistent behavior confuses developers and breaks observability workflows

Both issues need to be addressed to ensure reliable telemetry collection and accurate trace visualization.

Activity

self-assigned this
on Jun 26, 2025
bboynton97

bboynton97 commented on Jun 30, 2025

@bboynton97
Contributor

code fix in, waiting for token to test

devin-ai-integration

devin-ai-integration commented on Jul 6, 2025

@devin-ai-integration
ContributorAuthor

This issue was resolved by PR #1123 (fix instrumentation)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @bboynton97@Dwij1704

      Issue actions

        Decorators not working properly when imported from agentops.sdk.decorators namespace · Issue #1110 · AgentOps-AI/agentops