Skip to content

honeyhive.tracer.integration.error_handling

Dynamic error handling and resilience for HoneyHive tracer integration.

This module provides comprehensive error handling using dynamic patterns for graceful degradation, retry mechanisms, and recovery strategies. All error handling logic is extensible and configuration-driven.

IntegrationError

Bases: Exception

Base exception for integration errors with dynamic context.

Source code in src/honeyhive/tracer/integration/error_handling.py
23
24
25
26
27
28
29
30
31
32
33
34
35
class IntegrationError(Exception):
    """Base exception for integration errors with dynamic context."""

    def __init__(
        self,
        message: str,
        error_code: str = "INTEGRATION_ERROR",
        details: Optional[Dict[str, Any]] = None,
    ):
        super().__init__(message)
        self.error_code = error_code
        self.details = details or {}
        self.timestamp = time.time()

error_code instance-attribute

error_code = error_code

details instance-attribute

details = details or {}

timestamp instance-attribute

timestamp = time()

ProviderIncompatibleError

Bases: IntegrationError

Provider doesn't support required operations.

Source code in src/honeyhive/tracer/integration/error_handling.py
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class ProviderIncompatibleError(IntegrationError):
    """Provider doesn't support required operations."""

    def __init__(self, provider_type: str, required_operations: List[str]):
        message = (
            f"Provider {provider_type} doesn't support required operations: "
            f"{required_operations}"
        )
        super().__init__(
            message,
            error_code="PROVIDER_INCOMPATIBLE",
            details={
                "provider_type": provider_type,
                "required_operations": required_operations,
            },
        )

InitializationError

Bases: IntegrationError

Error during tracer initialization.

Source code in src/honeyhive/tracer/integration/error_handling.py
56
57
58
59
60
61
62
63
64
class InitializationError(IntegrationError):
    """Error during tracer initialization."""

    def __init__(self, message: str, cause: Optional[Exception] = None):
        super().__init__(
            message,
            error_code="INITIALIZATION_ERROR",
            details={"cause": str(cause) if cause else None},
        )

SpanProcessingError

Bases: IntegrationError

Error during span processing.

Source code in src/honeyhive/tracer/integration/error_handling.py
67
68
69
70
71
72
73
74
75
76
class SpanProcessingError(IntegrationError):
    """Error during span processing."""

    def __init__(self, span_name: str, cause: Optional[Exception] = None):
        message = f"Error processing span '{span_name}'"
        super().__init__(
            message,
            error_code="SPAN_PROCESSING_ERROR",
            details={"span_name": span_name, "cause": str(cause) if cause else None},
        )

ExportError

Bases: IntegrationError

Error during span export.

Source code in src/honeyhive/tracer/integration/error_handling.py
79
80
81
82
83
84
85
86
87
88
89
90
91
class ExportError(IntegrationError):
    """Error during span export."""

    def __init__(self, export_type: str, cause: Optional[Exception] = None):
        message = f"Error exporting spans via {export_type}"
        super().__init__(
            message,
            error_code="EXPORT_ERROR",
            details={
                "export_type": export_type,
                "cause": str(cause) if cause else None,
            },
        )

ErrorSeverity

Bases: Enum

Error severity levels for dynamic handling.

Source code in src/honeyhive/tracer/integration/error_handling.py
 94
 95
 96
 97
 98
 99
100
class ErrorSeverity(Enum):
    """Error severity levels for dynamic handling."""

    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    CRITICAL = "critical"

LOW class-attribute instance-attribute

LOW = 'low'

MEDIUM class-attribute instance-attribute

MEDIUM = 'medium'

HIGH class-attribute instance-attribute

HIGH = 'high'

CRITICAL class-attribute instance-attribute

CRITICAL = 'critical'

ResilienceLevel

Bases: Enum

Resilience levels for dynamic error handling strategies.

Source code in src/honeyhive/tracer/integration/error_handling.py
103
104
105
106
107
108
class ResilienceLevel(Enum):
    """Resilience levels for dynamic error handling strategies."""

    STRICT = "strict"  # Fail fast, no retries
    BALANCED = "balanced"  # Some retries, graceful degradation
    RESILIENT = "resilient"  # Maximum retries, always degrade gracefully

STRICT class-attribute instance-attribute

STRICT = 'strict'

BALANCED class-attribute instance-attribute

BALANCED = 'balanced'

RESILIENT class-attribute instance-attribute

RESILIENT = 'resilient'

ErrorContext dataclass

Dynamic error context with extensible metadata.

Source code in src/honeyhive/tracer/integration/error_handling.py
111
112
113
114
115
116
117
118
119
120
121
122
@dataclass
class ErrorContext:
    """Dynamic error context with extensible metadata."""

    error: Exception
    severity: ErrorSeverity = ErrorSeverity.MEDIUM
    component: str = "unknown"
    operation: str = "unknown"
    metadata: Dict[str, Any] = field(default_factory=dict)
    timestamp: float = field(default_factory=time.time)
    retry_count: int = 0
    max_retries: int = 3

error instance-attribute

error: Exception

severity class-attribute instance-attribute

severity: ErrorSeverity = MEDIUM

component class-attribute instance-attribute

component: str = 'unknown'

operation class-attribute instance-attribute

operation: str = 'unknown'

metadata class-attribute instance-attribute

metadata: Dict[str, Any] = field(default_factory=dict)

timestamp class-attribute instance-attribute

timestamp: float = field(default_factory=time)

retry_count class-attribute instance-attribute

retry_count: int = 0

max_retries class-attribute instance-attribute

max_retries: int = 3

RecoveryStrategy dataclass

Dynamic recovery strategy configuration.

Source code in src/honeyhive/tracer/integration/error_handling.py
125
126
127
128
129
130
131
132
133
134
@dataclass
class RecoveryStrategy:
    """Dynamic recovery strategy configuration."""

    name: str
    handler: Callable[[ErrorContext], bool]
    applicable_errors: List[str] = field(default_factory=list)
    max_attempts: int = 3
    backoff_multiplier: float = 1.5
    base_delay: float = 0.1

name instance-attribute

name: str

handler instance-attribute

handler: Callable[[ErrorContext], bool]

applicable_errors class-attribute instance-attribute

applicable_errors: List[str] = field(default_factory=list)

max_attempts class-attribute instance-attribute

max_attempts: int = 3

backoff_multiplier class-attribute instance-attribute

backoff_multiplier: float = 1.5

base_delay class-attribute instance-attribute

base_delay: float = 0.1

ErrorHandler

Dynamic error handler with extensible strategies and patterns.

Source code in src/honeyhive/tracer/integration/error_handling.py
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
class ErrorHandler:
    """Dynamic error handler with extensible strategies and patterns."""

    def __init__(
        self,
        resilience_level: ResilienceLevel = ResilienceLevel.BALANCED,
        tracer_instance: Any = None,
    ):
        """Initialize error handler with dynamic configuration.

        Args:
            resilience_level: Level of resilience for error handling
            tracer_instance: Optional tracer instance for logging context
        """
        self.resilience_level = resilience_level
        self.tracer_instance = tracer_instance
        self._lock = threading.Lock()
        self._error_history: List[ErrorContext] = []
        self._recovery_strategies = self._build_recovery_strategies_dynamically()
        self._error_patterns = self._build_error_patterns_dynamically()

    def _build_recovery_strategies_dynamically(self) -> List[RecoveryStrategy]:
        """Dynamically build recovery strategies based on resilience level.

        Returns:
            List of recovery strategies
        """
        strategies = []

        # Base strategies available for all resilience levels
        strategies.extend(
            [
                RecoveryStrategy(
                    name="graceful_degradation",
                    handler=self._graceful_degradation_handler,
                    applicable_errors=["PROVIDER_INCOMPATIBLE", "INITIALIZATION_ERROR"],
                    max_attempts=1,
                ),
                RecoveryStrategy(
                    name="retry_with_backoff",
                    handler=self._retry_with_backoff_handler,
                    applicable_errors=["EXPORT_ERROR", "SPAN_PROCESSING_ERROR"],
                    max_attempts=self._get_max_retries_for_level(),
                    backoff_multiplier=1.5,
                    base_delay=0.1,
                ),
            ]
        )

        # Add resilience-level specific strategies
        if self.resilience_level in {
            ResilienceLevel.BALANCED,
            ResilienceLevel.RESILIENT,
        }:
            strategies.append(
                RecoveryStrategy(
                    name="fallback_provider",
                    handler=self._fallback_provider_handler,
                    applicable_errors=["PROVIDER_INCOMPATIBLE"],
                    max_attempts=1,
                )
            )

        if self.resilience_level == ResilienceLevel.RESILIENT:
            strategies.append(
                RecoveryStrategy(
                    name="console_fallback",
                    handler=self._console_fallback_handler,
                    applicable_errors=["EXPORT_ERROR"],
                    max_attempts=1,
                )
            )

        return strategies

    def _build_error_patterns_dynamically(self) -> Dict[str, Dict[str, Any]]:
        """Dynamically build error patterns for classification.

        Returns:
            Dictionary of error patterns and their configurations
        """
        return {
            "connection_errors": {
                "patterns": ["connection", "timeout", "network", "unreachable"],
                "severity": ErrorSeverity.MEDIUM,
                "retry_eligible": True,
            },
            "authentication_errors": {
                "patterns": ["auth", "unauthorized", "forbidden", "api_key"],
                "severity": ErrorSeverity.HIGH,
                "retry_eligible": False,
            },
            "provider_errors": {
                "patterns": ["provider", "incompatible", "unsupported"],
                "severity": ErrorSeverity.HIGH,
                "retry_eligible": False,
            },
            "processing_errors": {
                "patterns": ["processing", "span", "attribute"],
                "severity": ErrorSeverity.LOW,
                "retry_eligible": True,
            },
        }

    def _get_max_retries_for_level(self) -> int:
        """Dynamically get max retries based on resilience level.

        Returns:
            Maximum number of retries
        """
        retry_mapping = {
            ResilienceLevel.STRICT: 0,
            ResilienceLevel.BALANCED: 3,
            ResilienceLevel.RESILIENT: 5,
        }
        return retry_mapping.get(self.resilience_level, 3)

    def handle_error(
        self,
        error: Exception,
        component: str = "unknown",
        operation: str = "unknown",
        **metadata: Any,
    ) -> bool:
        """Dynamically handle error with appropriate recovery strategy.

        Args:
            error: Exception that occurred
            component: Component where error occurred
            operation: Operation that failed
            **metadata: Additional error metadata

        Returns:
            bool: True if error was handled successfully, False otherwise
        """
        with self._lock:
            # Create error context
            error_context = self._create_error_context_dynamically(
                error, component, operation, metadata
            )

            # Record error in history
            self._record_error_dynamically(error_context)

            # Classify error severity
            error_context.severity = self._classify_error_severity_dynamically(error)

            # Apply recovery strategies
            recovery_success = self._apply_recovery_strategies_dynamically(
                error_context
            )

            # Log error handling result
            self._log_error_handling_result_dynamically(error_context, recovery_success)

            return recovery_success

    def _create_error_context_dynamically(
        self,
        error: Exception,
        component: str,
        operation: str,
        metadata: Dict[str, Any],
    ) -> ErrorContext:
        """Dynamically create error context with comprehensive information.

        Args:
            error: Exception that occurred
            component: Component where error occurred
            operation: Operation that failed
            metadata: Additional error metadata

        Returns:
            ErrorContext with comprehensive error information
        """
        return ErrorContext(
            error=error,
            component=component,
            operation=operation,
            metadata=metadata,
            max_retries=self._get_max_retries_for_level(),
        )

    def _record_error_dynamically(self, error_context: ErrorContext) -> None:
        """Dynamically record error in history with size management.

        Args:
            error_context: Error context to record
        """
        self._error_history.append(error_context)

        # Dynamic history size management
        max_history_size = 100
        if len(self._error_history) > max_history_size:
            self._error_history = self._error_history[-max_history_size:]

    def _classify_error_severity_dynamically(self, error: Exception) -> ErrorSeverity:
        """Dynamically classify error severity using pattern matching.

        Args:
            error: Exception to classify

        Returns:
            ErrorSeverity level
        """
        error_message = str(error).lower()
        error_type = type(error).__name__.lower()

        # Dynamic pattern matching
        for _pattern_name, pattern_config in self._error_patterns.items():
            patterns = pattern_config["patterns"]
            if any(
                pattern in error_message or pattern in error_type
                for pattern in patterns
            ):
                return ErrorSeverity(pattern_config["severity"])

        # Default severity for unclassified errors
        return ErrorSeverity.MEDIUM

    def _apply_recovery_strategies_dynamically(
        self, error_context: ErrorContext
    ) -> bool:
        """Dynamically apply recovery strategies based on error context.

        Args:
            error_context: Error context to handle

        Returns:
            bool: True if recovery was successful
        """
        error_code = getattr(error_context.error, "error_code", "UNKNOWN_ERROR")

        # Find applicable strategies
        applicable_strategies = self._find_applicable_strategies_dynamically(error_code)

        # Apply strategies in order
        for strategy in applicable_strategies:
            try:
                if self._execute_recovery_strategy_dynamically(strategy, error_context):
                    return True
            except Exception as strategy_error:
                safe_log(
                    self.tracer_instance,
                    "warning",
                    "Recovery strategy failed",
                    honeyhive_data={
                        "strategy": strategy.name,
                        "error": str(strategy_error),
                        "original_error": str(error_context.error),
                    },
                )
                continue

        return False

    def _find_applicable_strategies_dynamically(
        self, error_code: str
    ) -> List[RecoveryStrategy]:
        """Dynamically find applicable recovery strategies.

        Args:
            error_code: Error code to match against

        Returns:
            List of applicable recovery strategies
        """
        applicable = []

        for strategy in self._recovery_strategies:
            if (
                not strategy.applicable_errors
                or error_code in strategy.applicable_errors
            ):
                applicable.append(strategy)

        # Sort by priority (could be made dynamic in future)
        return applicable

    def _execute_recovery_strategy_dynamically(
        self, strategy: RecoveryStrategy, error_context: ErrorContext
    ) -> bool:
        """Dynamically execute recovery strategy with backoff.

        Args:
            strategy: Recovery strategy to execute
            error_context: Error context

        Returns:
            bool: True if strategy succeeded
        """
        for attempt in range(strategy.max_attempts):
            try:
                if strategy.handler(error_context):
                    return True

                # Dynamic backoff calculation
                if attempt < strategy.max_attempts - 1:
                    delay = strategy.base_delay * (strategy.backoff_multiplier**attempt)
                    time.sleep(delay)

            except Exception as handler_error:
                safe_log(
                    self.tracer_instance,
                    "debug",
                    "Recovery strategy handler failed",
                    honeyhive_data={
                        "strategy": strategy.name,
                        "attempt": attempt + 1,
                        "error": str(handler_error),
                    },
                )
                continue

        return False

    def _log_error_handling_result_dynamically(
        self, error_context: ErrorContext, recovery_success: bool
    ) -> None:
        """Dynamically log error handling result.

        Args:
            error_context: Error context that was handled
            recovery_success: Whether recovery was successful
        """
        log_level = "info" if recovery_success else "warning"
        log_message = (
            "Error handled successfully"
            if recovery_success
            else "Error handling failed"
        )

        safe_log(
            self.tracer_instance,
            log_level,
            log_message,
            honeyhive_data={
                "component": error_context.component,
                "operation": error_context.operation,
                "error_type": type(error_context.error).__name__,
                "severity": error_context.severity.value,
                "recovery_success": recovery_success,
                "retry_count": error_context.retry_count,
            },
        )

    # Recovery strategy handlers
    def _graceful_degradation_handler(self, error_context: ErrorContext) -> bool:
        """Handle error with graceful degradation.

        Args:
            error_context: Error context

        Returns:
            bool: True if degradation successful
        """
        safe_log(
            self.tracer_instance,
            "info",
            "Applying graceful degradation",
            honeyhive_data={
                "component": error_context.component,
                "operation": error_context.operation,
            },
        )
        # Graceful degradation always succeeds by definition
        return True

    def _retry_with_backoff_handler(self, error_context: ErrorContext) -> bool:
        """Handle error with retry and backoff.

        Args:
            error_context: Error context

        Returns:
            bool: True if retry should be attempted
        """
        if error_context.retry_count < error_context.max_retries:
            error_context.retry_count += 1
            return False  # Indicate retry needed
        return True  # Max retries reached, give up

    def _fallback_provider_handler(self, error_context: ErrorContext) -> bool:
        """Handle error by falling back to alternative provider.

        Args:
            error_context: Error context

        Returns:
            bool: True if fallback successful
        """
        safe_log(
            self.tracer_instance,
            "info",
            "Falling back to alternative provider",
            honeyhive_data={
                "component": error_context.component,
                "original_error": str(error_context.error),
            },
        )
        # Implementation would set up fallback provider
        return True

    def _console_fallback_handler(self, error_context: ErrorContext) -> bool:
        """Handle error by falling back to console logging.

        Args:
            error_context: Error context

        Returns:
            bool: True if console fallback successful
        """
        safe_log(
            self.tracer_instance,
            "info",
            "Falling back to console logging",
            honeyhive_data={
                "component": error_context.component,
                "original_error": str(error_context.error),
            },
        )
        # Console fallback always succeeds
        return True

    def get_error_statistics(self) -> Dict[str, Any]:
        """Get dynamic error statistics.

        Returns:
            Dictionary with error statistics
        """
        with self._lock:
            if not self._error_history:
                return {"total_errors": 0}

            # Dynamic statistics calculation
            stats = {
                "total_errors": len(self._error_history),
                "error_types": self._calculate_error_type_distribution(),
                "severity_distribution": self._calculate_severity_distribution(),
                "component_distribution": self._calculate_component_distribution(),
                "recent_errors": len(
                    [
                        e
                        for e in self._error_history
                        if time.time() - e.timestamp < 300  # Last 5 minutes
                    ]
                ),
            }

            return stats

    def _calculate_error_type_distribution(self) -> Dict[str, int]:
        """Calculate error type distribution."""
        distribution: Dict[str, int] = {}
        for error_context in self._error_history:
            error_type = type(error_context.error).__name__
            distribution[error_type] = distribution.get(error_type, 0) + 1
        return distribution

    def _calculate_severity_distribution(self) -> Dict[str, int]:
        """Calculate severity distribution."""
        distribution: Dict[str, int] = {}
        for error_context in self._error_history:
            severity = error_context.severity.value
            distribution[severity] = distribution.get(severity, 0) + 1
        return distribution

    def _calculate_component_distribution(self) -> Dict[str, int]:
        """Calculate component distribution."""
        distribution: Dict[str, int] = {}
        for error_context in self._error_history:
            component = error_context.component
            distribution[component] = distribution.get(component, 0) + 1
        return distribution

resilience_level instance-attribute

resilience_level = resilience_level

tracer_instance instance-attribute

tracer_instance = tracer_instance

handle_error

handle_error(
    error: Exception,
    component: str = "unknown",
    operation: str = "unknown",
    **metadata: Any
) -> bool

Dynamically handle error with appropriate recovery strategy.

Parameters:

Name Type Description Default
error Exception

Exception that occurred

required
component str

Component where error occurred

'unknown'
operation str

Operation that failed

'unknown'
**metadata Any

Additional error metadata

{}

Returns:

Name Type Description
bool bool

True if error was handled successfully, False otherwise

Source code in src/honeyhive/tracer/integration/error_handling.py
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
def handle_error(
    self,
    error: Exception,
    component: str = "unknown",
    operation: str = "unknown",
    **metadata: Any,
) -> bool:
    """Dynamically handle error with appropriate recovery strategy.

    Args:
        error: Exception that occurred
        component: Component where error occurred
        operation: Operation that failed
        **metadata: Additional error metadata

    Returns:
        bool: True if error was handled successfully, False otherwise
    """
    with self._lock:
        # Create error context
        error_context = self._create_error_context_dynamically(
            error, component, operation, metadata
        )

        # Record error in history
        self._record_error_dynamically(error_context)

        # Classify error severity
        error_context.severity = self._classify_error_severity_dynamically(error)

        # Apply recovery strategies
        recovery_success = self._apply_recovery_strategies_dynamically(
            error_context
        )

        # Log error handling result
        self._log_error_handling_result_dynamically(error_context, recovery_success)

        return recovery_success

get_error_statistics

get_error_statistics() -> Dict[str, Any]

Get dynamic error statistics.

Returns:

Type Description
Dict[str, Any]

Dictionary with error statistics

Source code in src/honeyhive/tracer/integration/error_handling.py
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
def get_error_statistics(self) -> Dict[str, Any]:
    """Get dynamic error statistics.

    Returns:
        Dictionary with error statistics
    """
    with self._lock:
        if not self._error_history:
            return {"total_errors": 0}

        # Dynamic statistics calculation
        stats = {
            "total_errors": len(self._error_history),
            "error_types": self._calculate_error_type_distribution(),
            "severity_distribution": self._calculate_severity_distribution(),
            "component_distribution": self._calculate_component_distribution(),
            "recent_errors": len(
                [
                    e
                    for e in self._error_history
                    if time.time() - e.timestamp < 300  # Last 5 minutes
                ]
            ),
        }

        return stats

get_error_handler

get_error_handler(
    resilience_level: ResilienceLevel = BALANCED,
    tracer_instance: Any = None,
) -> ErrorHandler

Get or create per-tracer-instance error handler with dynamic configuration.

Parameters:

Name Type Description Default
resilience_level ResilienceLevel

Resilience level for error handling

BALANCED
tracer_instance Any

Tracer instance for logging context and isolation

None

Returns:

Type Description
ErrorHandler

ErrorHandler instance (per-tracer-instance for proper isolation)

Source code in src/honeyhive/tracer/integration/error_handling.py
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
def get_error_handler(
    resilience_level: ResilienceLevel = ResilienceLevel.BALANCED,
    tracer_instance: Any = None,
) -> ErrorHandler:
    """Get or create per-tracer-instance error handler with dynamic configuration.

    Args:
        resilience_level: Resilience level for error handling
        tracer_instance: Tracer instance for logging context and isolation

    Returns:
        ErrorHandler instance (per-tracer-instance for proper isolation)
    """
    # Multi-instance architecture: Each tracer gets its own error handler
    if tracer_instance is not None:
        # Check if tracer already has an error handler
        if not hasattr(tracer_instance, "_error_handler"):
            # Internal SDK code accessing tracer's error handler attribute
            # Protected access is required for multi-instance architecture
            tracer_instance._error_handler = (  # pylint: disable=protected-access
                ErrorHandler(resilience_level, tracer_instance)
            )
        error_handler = (
            tracer_instance._error_handler  # pylint: disable=protected-access
        )
        return cast(ErrorHandler, error_handler)

    # Fallback: Create new handler for cases without tracer instance
    return ErrorHandler(resilience_level, tracer_instance)

with_error_handling

with_error_handling(
    component: str = "unknown",
    operation: str = "unknown",
    resilience_level: ResilienceLevel = BALANCED,
    tracer_instance: Any = None,
) -> Any

Decorator for dynamic error handling.

Parameters:

Name Type Description Default
component str

Component name for error context

'unknown'
operation str

Operation name for error context

'unknown'
resilience_level ResilienceLevel

Resilience level for error handling

BALANCED
tracer_instance Any

Optional tracer instance for logging context

None

Returns:

Type Description
Any

Decorator function

Source code in src/honeyhive/tracer/integration/error_handling.py
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
def with_error_handling(
    component: str = "unknown",
    operation: str = "unknown",
    resilience_level: ResilienceLevel = ResilienceLevel.BALANCED,
    tracer_instance: Any = None,
) -> Any:
    """Decorator for dynamic error handling.

    Args:
        component: Component name for error context
        operation: Operation name for error context
        resilience_level: Resilience level for error handling
        tracer_instance: Optional tracer instance for logging context

    Returns:
        Decorator function
    """

    def decorator(func: Callable) -> Callable:
        @wraps(func)
        def wrapper(*args: Any, **kwargs: Any) -> Any:
            try:
                return func(*args, **kwargs)
            except Exception as e:
                error_handler = get_error_handler(resilience_level, tracer_instance)
                handled = error_handler.handle_error(
                    e,
                    component=component,
                    operation=operation,
                    function_name=func.__name__,
                    args_count=len(args),
                    kwargs_keys=list(kwargs.keys()),
                )

                if not handled and resilience_level == ResilienceLevel.STRICT:
                    raise

                # Return None or appropriate default for graceful degradation
                return None

        return wrapper

    return decorator