File size: 3,656 Bytes
1fff71f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1ab5126
 
 
 
 
 
 
 
 
 
1fff71f
 
 
 
 
 
 
1ab5126
 
1fff71f
 
 
 
1ab5126
1fff71f
018ba2e
1ab5126
 
018ba2e
 
 
1ab5126
 
1fff71f
 
 
 
018ba2e
 
1fff71f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
018ba2e
1fff71f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
"""
Jaeger tracing utilities using OpenTelemetry.

Uses OpenTelemetry OTLP HTTP exporter to send traces to Jaeger.
This matches the Go API approach of using HTTP instead of unreliable UDP.
"""

import logging
import os
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.instrumentation.requests import RequestsInstrumentor

logger = logging.getLogger(__name__)


def is_tracing_enabled() -> bool:
    """
    Check if tracing is enabled via ENABLE_TRACING environment variable.
    
    Returns:
        True if tracing is enabled (default), False otherwise
    """
    return os.getenv("ENABLE_TRACING", "true").lower() in ("true", "1", "yes")


def init_tracer(service_name: str) -> trace.Tracer:
    """
    Initialize OpenTelemetry tracer with OTLP HTTP exporter for Jaeger.
    
    Uses HTTP protocol like the Go API (instead of unreliable UDP).
    Jaeger >= 1.35 supports OTLP natively on port 4318.
    
    Can be disabled by setting ENABLE_TRACING=false environment variable.
    
    Args:
        service_name: Name of the service for tracing
        
    Returns:
        Configured tracer instance (or no-op tracer if disabled)
    """
    # Check if tracing is enabled BEFORE doing anything
    if not is_tracing_enabled():
        print(f"[TRACING] Tracing disabled via ENABLE_TRACING environment variable")
        logger.info("OpenTelemetry tracing disabled - no exporter or instrumentation will be initialized")
        # Return no-op tracer WITHOUT setting up any exporters or instrumentation
        # This prevents any connection attempts to Jaeger
        return trace.get_tracer(service_name)
    
    # Jaeger OTLP HTTP endpoint (port 4318)
    otlp_endpoint = os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT", "http://jaeger:4318")
    sampling_rate = float(os.getenv("JAEGER_SAMPLING_RATE", "1.0"))
    
    print(f"[TRACING] Initializing OpenTelemetry with endpoint={otlp_endpoint}")
    
    # Create resource with service name
    resource = Resource.create({"service.name": service_name})
    
    # Create tracer provider
    provider = TracerProvider(resource=resource)
    
    # Create OTLP HTTP exporter
    otlp_exporter = OTLPSpanExporter(
        endpoint=f"{otlp_endpoint}/v1/traces",
        timeout=2,  # 2 second timeout like Go API
    )
    
    # Add batch span processor (matches Go API's buffering)
    processor = BatchSpanProcessor(
        otlp_exporter,
        max_queue_size=2048,  # Default queue size
        max_export_batch_size=512,  # Must be <= max_queue_size
        schedule_delay_millis=1000,  # 1 second flush interval like Go API
    )
    provider.add_span_processor(processor)
    
    # Set as global tracer provider
    trace.set_tracer_provider(provider)
    
    # Get tracer
    tracer = trace.get_tracer(service_name)
    
    # Auto-instrument Flask and requests ONLY when tracing is enabled
    FlaskInstrumentor().instrument()
    RequestsInstrumentor().instrument()
    
    print(f"[TRACING] OpenTelemetry tracer initialized: service={service_name}, endpoint={otlp_endpoint}, sampling={sampling_rate}")
    
    logger.info(
        f"OpenTelemetry tracer initialized with OTLP HTTP exporter",
        extra={
            "service": service_name,
            "otlp_endpoint": otlp_endpoint,
            "sampling_rate": sampling_rate,
        }
    )
    
    return tracer