Skip to content

honeyhive.tracer.registry

Tracer registry for automatic tracer discovery via OpenTelemetry baggage.

This module provides a lightweight registry system that enables backward-compatible @trace decorator usage by automatically discovering the appropriate HoneyHiveTracer instance from OpenTelemetry baggage context.

The registry uses weak references to prevent memory leaks and automatically cleans up when tracer instances are garbage collected.

register_tracer

register_tracer(tracer: HoneyHiveTracer) -> str

Register a tracer instance and return its unique ID.

Parameters:

Name Type Description Default
tracer HoneyHiveTracer

HoneyHiveTracer instance to register

required

Returns:

Type Description
str

Unique tracer ID for use in baggage context

Example

tracer = HoneyHiveTracer(api_key="your-api-key") # project from API key tracer_id = register_tracer(tracer) print(f"Registered tracer with ID: {tracer_id}")

Source code in src/honeyhive/tracer/registry.py
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
def register_tracer(tracer: "HoneyHiveTracer") -> str:
    """Register a tracer instance and return its unique ID.

    Args:
        tracer: HoneyHiveTracer instance to register

    Returns:
        Unique tracer ID for use in baggage context

    Example:
        >>> tracer = HoneyHiveTracer(api_key="your-api-key")  # project from API key
        >>> tracer_id = register_tracer(tracer)
        >>> print(f"Registered tracer with ID: {tracer_id}")
    """
    tracer_id = str(id(tracer))
    # PYTEST-XDIST COMPATIBLE: No cross-process locks needed
    _TRACER_REGISTRY[tracer_id] = tracer
    return tracer_id

unregister_tracer

unregister_tracer(tracer_id: str) -> bool

Unregister a tracer instance by ID.

Parameters:

Name Type Description Default
tracer_id str

Unique tracer ID to unregister

required

Returns:

Type Description
bool

True if tracer was found and unregistered, False otherwise

Note

This is typically not needed as the WeakValueDictionary automatically cleans up when tracers are garbage collected.

Source code in src/honeyhive/tracer/registry.py
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
def unregister_tracer(tracer_id: str) -> bool:
    """Unregister a tracer instance by ID.

    Args:
        tracer_id: Unique tracer ID to unregister

    Returns:
        True if tracer was found and unregistered, False otherwise

    Note:
        This is typically not needed as the WeakValueDictionary
        automatically cleans up when tracers are garbage collected.
    """
    if tracer_id in _TRACER_REGISTRY:
        del _TRACER_REGISTRY[tracer_id]
        return True
    return False

get_tracer_from_baggage

get_tracer_from_baggage(
    ctx: Optional[Context] = None,
) -> Optional[HoneyHiveTracer]

Discover and return the HoneyHiveTracer instance from baggage context.

This function looks up the tracer ID from OpenTelemetry baggage and returns the corresponding registered tracer instance.

Parameters:

Name Type Description Default
ctx Optional[Context]

OpenTelemetry context to read baggage from. If None, uses current context.

None

Returns:

Type Description
Optional[HoneyHiveTracer]

HoneyHiveTracer instance if found in baggage and registry,

Optional[HoneyHiveTracer]

None otherwise

Example

Within a traced context:

tracer = get_tracer_from_baggage() if tracer: ... print(f"Found tracer for project: {tracer.project}")

Source code in src/honeyhive/tracer/registry.py
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
def get_tracer_from_baggage(
    ctx: Optional["Context"] = None,
) -> "Optional[HoneyHiveTracer]":
    """Discover and return the HoneyHiveTracer instance from baggage context.

    This function looks up the tracer ID from OpenTelemetry baggage and
    returns the corresponding registered tracer instance.

    Args:
        ctx: OpenTelemetry context to read baggage from.
             If None, uses current context.

    Returns:
        HoneyHiveTracer instance if found in baggage and registry,
        None otherwise

    Example:
        >>> # Within a traced context:
        >>> tracer = get_tracer_from_baggage()
        >>> if tracer:
        ...     print(f"Found tracer for project: {tracer.project}")
    """

    try:
        ctx = ctx or context.get_current()
        tracer_id = baggage.get_baggage("honeyhive_tracer_id", ctx)

        if tracer_id:
            if isinstance(tracer_id, str) and tracer_id in _TRACER_REGISTRY:
                tracer = _TRACER_REGISTRY[tracer_id]
                # Debug logging for successful baggage discovery
                if hasattr(tracer, "logger"):
                    safe_log(
                        tracer,
                        "debug",
                        "Tracer discovered from baggage: tracer_id=%s, project=%s",
                        tracer_id,
                        getattr(tracer, "project", "unknown"),
                        honeyhive_data={
                            "tracer_id": tracer_id,
                            "discovery_method": "baggage",
                        },
                    )
                return tracer

    except Exception as e:
        # Log error for debugging but don't crash
        logging.debug("Baggage tracer discovery failed: %s", e)

    return None

set_default_tracer

set_default_tracer(
    tracer: Optional[HoneyHiveTracer],
) -> None

Set a global default tracer for backward compatibility.

This tracer will be used as a fallback when no tracer is found in baggage context and no explicit tracer is provided.

Parameters:

Name Type Description Default
tracer Optional[HoneyHiveTracer]

HoneyHiveTracer instance to use as default, or None to clear the default

required
Example

default_tracer = HoneyHiveTracer(api_key="your-api-key") # auto project set_default_tracer(default_tracer)

Now @trace will use default_tracer when no context available

@trace ... def my_function(): ... pass

Source code in src/honeyhive/tracer/registry.py
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
def set_default_tracer(tracer: "Optional[HoneyHiveTracer]") -> None:
    """Set a global default tracer for backward compatibility.

    This tracer will be used as a fallback when no tracer is found
    in baggage context and no explicit tracer is provided.

    Args:
        tracer: HoneyHiveTracer instance to use as default,
                or None to clear the default

    Example:
        >>> default_tracer = HoneyHiveTracer(api_key="your-api-key")  # auto project
        >>> set_default_tracer(default_tracer)
        >>>
        >>> # Now @trace will use default_tracer when no context available
        >>> @trace
        ... def my_function():
        ...     pass
    """
    global _DEFAULT_TRACER

    # PYTEST-XDIST COMPATIBLE: No cross-process locks needed
    if tracer is None:
        _DEFAULT_TRACER = None
    else:
        # Register the tracer to ensure it's in the registry
        register_tracer(tracer)
        _DEFAULT_TRACER = weakref.ref(tracer)

get_default_tracer

get_default_tracer() -> Optional[HoneyHiveTracer]

Get the global default tracer if set and still alive.

Returns:

Type Description
Optional[HoneyHiveTracer]

Default HoneyHiveTracer instance if set and not garbage collected,

Optional[HoneyHiveTracer]

None otherwise

Example

tracer = get_default_tracer() if tracer: ... print(f"Default tracer project: {tracer.project}")

Source code in src/honeyhive/tracer/registry.py
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
def get_default_tracer() -> "Optional[HoneyHiveTracer]":
    """Get the global default tracer if set and still alive.

    Returns:
        Default HoneyHiveTracer instance if set and not garbage collected,
        None otherwise

    Example:
        >>> tracer = get_default_tracer()
        >>> if tracer:
        ...     print(f"Default tracer project: {tracer.project}")
    """
    global _DEFAULT_TRACER

    # PYTEST-XDIST COMPATIBLE: No cross-process locks needed
    if _DEFAULT_TRACER is not None:
        # Weak reference - check if still alive
        tracer = _DEFAULT_TRACER()
        if tracer is not None:
            return tracer
        # Tracer was garbage collected, clear the reference
        _DEFAULT_TRACER = None

    return None

discover_tracer

discover_tracer(
    explicit_tracer: Optional[HoneyHiveTracer] = None,
    ctx: Optional[Context] = None,
) -> Optional[HoneyHiveTracer]

Discover the appropriate tracer using priority-based fallback.

This is the main function used by decorators to find the right tracer instance using the following priority order: 1. Explicit tracer parameter (highest priority) 2. Baggage-discovered tracer (context-aware) 3. Global default tracer (fallback)

Parameters:

Name Type Description Default
explicit_tracer Optional[HoneyHiveTracer]

Explicitly provided tracer (from decorator parameter)

None
ctx Optional[Context]

OpenTelemetry context to read baggage from

None

Returns:

Type Description
Optional[HoneyHiveTracer]

HoneyHiveTracer instance using priority fallback, None if none found

Example

In decorator implementation:

tracer = discover_tracer( ... explicit_tracer=kwargs.get("tracer"), ... ctx=context.get_current() ... ) if tracer: ... # Use discovered tracer for tracing ... with tracer.start_span("operation") as span: ... # ... tracing logic

Source code in src/honeyhive/tracer/registry.py
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
def discover_tracer(
    explicit_tracer: "Optional[HoneyHiveTracer]" = None,
    ctx: Optional["Context"] = None,
) -> "Optional[HoneyHiveTracer]":
    """Discover the appropriate tracer using priority-based fallback.

    This is the main function used by decorators to find the right tracer
    instance using the following priority order:
    1. Explicit tracer parameter (highest priority)
    2. Baggage-discovered tracer (context-aware)
    3. Global default tracer (fallback)

    Args:
        explicit_tracer: Explicitly provided tracer (from decorator parameter)
        ctx: OpenTelemetry context to read baggage from

    Returns:
        HoneyHiveTracer instance using priority fallback, None if none found

    Example:
        >>> # In decorator implementation:
        >>> tracer = discover_tracer(
        ...     explicit_tracer=kwargs.get("tracer"),
        ...     ctx=context.get_current()
        ... )
        >>> if tracer:
        ...     # Use discovered tracer for tracing
        ...     with tracer.start_span("operation") as span:
        ...         # ... tracing logic
    """
    # Priority 1: Explicit tracer parameter
    if explicit_tracer is not None:
        return explicit_tracer

    # Priority 2: Baggage-discovered tracer (context-aware)
    baggage_tracer = get_tracer_from_baggage(ctx)
    if baggage_tracer is not None:
        return baggage_tracer

    # Priority 3: Global default tracer (fallback)
    default_tracer = get_default_tracer()
    if default_tracer is not None:
        return default_tracer

    # No tracer found
    return None

get_all_tracers

get_all_tracers() -> List[HoneyHiveTracer]

Get all registered tracers.

Returns:

Type Description
List[HoneyHiveTracer]

List of all registered HoneyHiveTracer instances

Example

tracers = get_all_tracers() print(f"Found {len(tracers)} active tracers")

Source code in src/honeyhive/tracer/registry.py
238
239
240
241
242
243
244
245
246
247
248
def get_all_tracers() -> List["HoneyHiveTracer"]:
    """Get all registered tracers.

    Returns:
        List of all registered HoneyHiveTracer instances

    Example:
        >>> tracers = get_all_tracers()
        >>> print(f"Found {len(tracers)} active tracers")
    """
    return list(_TRACER_REGISTRY.values())

get_registry_stats

get_registry_stats() -> Dict[str, int]

Get statistics about the tracer registry for debugging.

Returns:

Type Description
Dict[str, int]

Dictionary with registry statistics

Example

stats = get_registry_stats() print(f"Active tracers: {stats['active_tracers']}") print(f"Has default: {stats['has_default_tracer']}")

Source code in src/honeyhive/tracer/registry.py
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
def get_registry_stats() -> Dict[str, int]:
    """Get statistics about the tracer registry for debugging.

    Returns:
        Dictionary with registry statistics

    Example:
        >>> stats = get_registry_stats()
        >>> print(f"Active tracers: {stats['active_tracers']}")
        >>> print(f"Has default: {stats['has_default_tracer']}")
    """
    return {
        "active_tracers": len(_TRACER_REGISTRY),
        "has_default_tracer": 1 if get_default_tracer() is not None else 0,
    }

clear_registry

clear_registry() -> None

Clear all registered tracers and default tracer.

This is primarily useful for testing and cleanup scenarios.

Warning

This will break any ongoing tracing operations that depend on auto-discovery. Use with caution.

Example

In test teardown:

clear_registry()

Source code in src/honeyhive/tracer/registry.py
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
def clear_registry() -> None:
    """Clear all registered tracers and default tracer.

    This is primarily useful for testing and cleanup scenarios.

    Warning:
        This will break any ongoing tracing operations that depend
        on auto-discovery. Use with caution.

    Example:
        >>> # In test teardown:
        >>> clear_registry()
    """
    global _DEFAULT_TRACER
    _TRACER_REGISTRY.clear()
    _DEFAULT_TRACER = None