|
29 | 29 | import pandas as pd |
30 | 30 |
|
31 | 31 | from src.telemetry import setup_telemetry |
32 | | -from src.numerical.optimization import gradient_descent |
33 | | -from src.algorithms.graph import graph_traversal, find_node_clusters, PathFinder, calculate_node_betweenness |
34 | | -from src.algorithms.dynamic_programming import fibonacci, matrix_sum, matrix_chain_order, coin_change, knapsack |
35 | | -from src.data_processing.dataframe import dataframe_filter, groupby_mean, dataframe_merge |
36 | | -from src.statistics.descriptive import describe, correlation |
| 32 | +from src.telemetry.auto_instrumentation import auto_instrument_package |
37 | 33 |
|
38 | | -# Initialize OpenTelemetry with auto-instrumentation |
| 34 | +# Initialize OpenTelemetry with auto-instrumentation FIRST |
39 | 35 | # Uses environment variables if set, otherwise defaults to console exporter |
40 | 36 | print("=" * 80) |
41 | 37 | print("Initializing OpenTelemetry with auto-instrumentation...") |
|
51 | 47 | exporter_type = os.getenv("OTEL_TRACES_EXPORTER") or os.getenv("OTEL_EXPORTER_TYPE", "console") |
52 | 48 | exporter_endpoint = os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4317") |
53 | 49 |
|
54 | | -setup_telemetry( |
55 | | - service_name="optimize-me", |
56 | | - service_version="0.1.0", |
57 | | - exporter_type=exporter_type, |
58 | | - exporter_endpoint=exporter_endpoint, |
59 | | - use_auto_instrumentation=True, # Use auto-instrumentation (standard pattern) |
| 50 | +# Detect if running under opentelemetry-instrument |
| 51 | +# opentelemetry-instrument sets up its own TracerProvider, so we shouldn't replace it |
| 52 | +from opentelemetry import trace |
| 53 | +existing_provider = trace.get_tracer_provider() |
| 54 | +is_opentelemetry_instrument = ( |
| 55 | + existing_provider is not None |
| 56 | + and not isinstance(existing_provider, trace.NoOpTracerProvider) |
| 57 | + and type(existing_provider).__name__ in ("ProxyTracerProvider", "TracerProvider") |
| 58 | +) |
| 59 | + |
| 60 | +if is_opentelemetry_instrument: |
| 61 | + print("Detected opentelemetry-instrument - using existing OpenTelemetry setup") |
| 62 | + print(f"Exporter: {exporter_type}, Endpoint: {exporter_endpoint}") |
| 63 | + # Still call setup_telemetry to ensure console exporter is added if needed |
| 64 | + # setup_telemetry handles ProxyTracerProvider by creating a new TracerProvider |
| 65 | + # This ensures we have a console exporter configured for immediate output |
| 66 | + setup_telemetry( |
| 67 | + service_name="optimize-me", |
| 68 | + service_version="0.1.0", |
| 69 | + exporter_type=exporter_type, # Use console when OTEL_TRACES_EXPORTER=console |
| 70 | + exporter_endpoint=exporter_endpoint, |
| 71 | + use_auto_instrumentation=True, |
| 72 | + ) |
| 73 | + if exporter_type == "console": |
| 74 | + print("✅ Console exporter configured - traces will appear below") |
| 75 | +else: |
| 76 | + # Call setup_telemetry to create TracerProvider and configure exporter |
| 77 | + setup_telemetry( |
| 78 | + service_name="optimize-me", |
| 79 | + service_version="0.1.0", |
| 80 | + exporter_type=exporter_type, |
| 81 | + exporter_endpoint=exporter_endpoint, |
| 82 | + use_auto_instrumentation=True, # Use auto-instrumentation (standard pattern) |
| 83 | + ) |
| 84 | + |
| 85 | +# Auto-instrument all custom functions in src package |
| 86 | +# This automatically traces all functions without requiring decorators |
| 87 | +# IMPORTANT: This must happen BEFORE importing the modules |
| 88 | +print("\nSetting up auto-instrumentation for custom functions...") |
| 89 | +auto_instrument_package( |
| 90 | + 'src', |
| 91 | + include_private=False, # Don't instrument private functions (starting with _) |
| 92 | + exclude_modules=['src.tests', 'src.telemetry'] # Exclude test and telemetry modules |
60 | 93 | ) |
| 94 | +print("✅ Auto-instrumentation enabled - all functions will be traced automatically") |
| 95 | + |
| 96 | +# NOW import modules - functions will be automatically wrapped |
| 97 | +from src.numerical.optimization import gradient_descent |
| 98 | +from src.algorithms.graph import graph_traversal, find_node_clusters, PathFinder, calculate_node_betweenness |
| 99 | +from src.algorithms.dynamic_programming import fibonacci, matrix_sum, matrix_chain_order, coin_change, knapsack |
| 100 | +from src.data_processing.dataframe import dataframe_filter, groupby_mean, dataframe_merge |
| 101 | +from src.statistics.descriptive import describe, correlation |
61 | 102 |
|
62 | 103 | print("\n" + "=" * 80) |
63 | 104 | print("RUNNING ALL INSTRUMENTED FUNCTIONS") |
|
202 | 243 | # Force flush spans to ensure they're exported (especially for console exporter) |
203 | 244 | try: |
204 | 245 | from opentelemetry import trace |
| 246 | + from opentelemetry.sdk.trace import TracerProvider |
205 | 247 | provider = trace.get_tracer_provider() |
206 | | - if hasattr(provider, "force_flush"): |
207 | | - provider.force_flush() |
208 | | -except Exception: |
209 | | - pass |
| 248 | + if isinstance(provider, TracerProvider): |
| 249 | + if hasattr(provider, "force_flush"): |
| 250 | + provider.force_flush(timeout_millis=5000) # Wait up to 5 seconds |
| 251 | + print("\n✅ Spans flushed to exporter") |
| 252 | +except Exception as e: |
| 253 | + if os.getenv("OTEL_LOG_LEVEL", "").upper() == "DEBUG": |
| 254 | + print(f"\n⚠️ Could not flush spans: {e}") |
210 | 255 |
|
211 | 256 | print() |
212 | 257 |
|
0 commit comments