#!/usr/bin/env python3 """ Script to automatically add OpenTelemetry monitoring configuration to all service deployments. This adds environment variables for metrics, logs, and traces export to SigNoz. """ import os import re import sys from pathlib import Path # Services to configure SERVICES = [ "ai-insights", "distribution", "external", "forecasting", "inventory", "notification", "orchestrator", "orders", "pos", "procurement", "production", "recipes", "sales", "suppliers", "tenant", "training", ] OTEL_ENV_VARS_TEMPLATE = """ env: # OpenTelemetry Configuration - name: OTEL_COLLECTOR_ENDPOINT value: "http://signoz-otel-collector.signoz.svc.cluster.local:4318" - name: OTEL_EXPORTER_OTLP_ENDPOINT value: "http://signoz-otel-collector.signoz.svc.cluster.local:4318" - name: OTEL_SERVICE_NAME value: "{service_name}" - name: ENABLE_TRACING value: "true" # Logging Configuration - name: OTEL_LOGS_EXPORTER value: "otlp" - name: OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED value: "true" # Metrics Configuration (all via OTLP, no Prometheus) - name: ENABLE_OTEL_METRICS value: "true" - name: ENABLE_SYSTEM_METRICS value: "true" """ def has_otel_config(content: str) -> bool: """Check if file already has OTEL configuration""" return "OTEL_COLLECTOR_ENDPOINT" in content def add_otel_config(content: str, service_name: str) -> str: """Add OTEL configuration to service deployment""" # Prepare the env vars with the service name env_vars = OTEL_ENV_VARS_TEMPLATE.format(service_name=f"{service_name}-service") # Find the container section and add env vars before envFrom # Pattern: find " containers:" then first " envFrom:" after it pattern = r'( containers:\n - name: [^\n]+\n image: [^\n]+\n(?: ports:\n(?: - [^\n]+\n)+)?)( envFrom:)' replacement = r'\1' + env_vars + r'\2' # Try to replace new_content = re.sub(pattern, replacement, content, count=1) if new_content == content: print(f" ⚠️ Warning: Could not find insertion point automatically") return content return new_content def process_service(service_name: str, base_path: Path) -> bool: """Process a single service deployment file""" service_file = base_path / "components" / service_name / f"{service_name}-service.yaml" if not service_file.exists(): print(f" ⚠️ File not found: {service_file}") return False # Read file with open(service_file, 'r') as f: content = f.read() # Check if already configured if has_otel_config(content): print(f" ✓ Already configured") return True # Add configuration new_content = add_otel_config(content, service_name) if new_content == content: return False # Write back with open(service_file, 'w') as f: f.write(new_content) print(f" ✅ Updated successfully") return True def main(): """Main function""" # Find base path script_dir = Path(__file__).parent base_path = script_dir / "base" if not base_path.exists(): print(f"❌ Error: Base path not found: {base_path}") sys.exit(1) print("=" * 60) print("Adding OpenTelemetry Monitoring Configuration") print("=" * 60) print() success_count = 0 skip_count = 0 fail_count = 0 for service in SERVICES: print(f"📝 Processing {service}-service...") result = process_service(service, base_path) if result: if has_otel_config(open(base_path / "components" / service / f"{service}-service.yaml").read()): success_count += 1 else: fail_count += 1 print() print("=" * 60) print(f"✅ Successfully configured: {success_count}") if fail_count > 0: print(f"⚠️ Failed to configure: {fail_count}") print("=" * 60) print() print("Next steps:") print("1. Review the changes: git diff infrastructure/kubernetes/base/components/") print("2. Update SigNoz: helm upgrade signoz signoz/signoz -n signoz -f infrastructure/helm/signoz-values-dev.yaml") print("3. Apply changes: kubectl apply -k infrastructure/kubernetes/overlays/dev/") print("4. Verify: kubectl logs -n bakery-ia deployment/ | grep -i 'otel\\|metrics'") if __name__ == "__main__": main()