From 6f9657a3a8060bf390ed8f1ab66622c491173447 Mon Sep 17 00:00:00 2001 From: bigtux Date: Fri, 6 Feb 2026 19:28:43 -0300 Subject: [PATCH] feat: Universal auto-instrumentation for all languages ## New Features ### Universal Instrumentation Container - Created deploy/instrumentation/ with Dockerfile that downloads OTel agents for: - .NET (glibc and musl/Alpine versions) - Node.js (with auto-instrumentation package) - Python (bootstrap script + requirements) - Java (javaagent JAR) - Go (example code for compile-time instrumentation) - PHP (composer package + init script) ### Universal instrument.sh Script - Auto-detects application language from running processes - Generates docker-compose snippets for each language - Supports: dotnet, nodejs, python, java, go, php - Usage: ./instrument.sh [language] [otlp_endpoint] ### Improved docker-compose.yml - Added instrumentation init container with shared volume - Added AGENT_KEY environment variable for proper auth - Added ophion-agent service for host metrics collection - Named containers for easier management - Added ophion-network for service discovery ### Documentation - Created docs/QUICK_START.md with: - Single-command installation - Instrumentation guide for all languages - Troubleshooting section - Authentication guide ### Auth Fixes - Server now properly validates AGENT_KEY for agent authentication - OTel Collector configured with AGENT_KEY for forwarding to server - Fixed 401 errors when agents connect ## Files Changed - docker-compose.yml: Complete stack with all services - deploy/instrumentation/*: Universal OTel agent container - deploy/docker/otel-collector-config.yaml: Fixed auth headers - instrument.sh: Universal instrumentation script - docs/QUICK_START.md: Complete quick start guide - README.md: Updated with new features - .env.example: Added AGENT_KEY ## Testing - Go code compiles successfully - Docker images build correctly - All changes are backwards compatible --- .env.example | 3 + README.md | 165 +++++-- deploy/docker/otel-collector-config.yaml | 60 ++- deploy/instrumentation/Dockerfile | 74 ++++ deploy/instrumentation/files/README.md | 51 +++ .../instrumentation/files/go/go.mod.example | 5 + .../instrumentation/files/go/init.go.example | 34 ++ .../files/nodejs/instrument.js | 25 ++ .../instrumentation/files/nodejs/package.json | 11 + .../instrumentation/files/php/composer.json | 9 + .../instrumentation/files/php/otel_init.php | 29 ++ .../instrumentation/files/python/bootstrap.sh | 5 + .../files/python/requirements.txt | 3 + docker-compose.yml | 201 +++++---- docs/QUICK_START.md | 347 +++++++++++++++ instrument.sh | 405 ++++++++++++++++++ 16 files changed, 1279 insertions(+), 148 deletions(-) create mode 100644 deploy/instrumentation/Dockerfile create mode 100644 deploy/instrumentation/files/README.md create mode 100644 deploy/instrumentation/files/go/go.mod.example create mode 100644 deploy/instrumentation/files/go/init.go.example create mode 100644 deploy/instrumentation/files/nodejs/instrument.js create mode 100644 deploy/instrumentation/files/nodejs/package.json create mode 100644 deploy/instrumentation/files/php/composer.json create mode 100644 deploy/instrumentation/files/php/otel_init.php create mode 100644 deploy/instrumentation/files/python/bootstrap.sh create mode 100644 deploy/instrumentation/files/python/requirements.txt create mode 100644 docs/QUICK_START.md create mode 100755 instrument.sh diff --git a/.env.example b/.env.example index 239fb10..ebc5879 100644 --- a/.env.example +++ b/.env.example @@ -25,6 +25,9 @@ API_URL=http://ophion-server:8080 JWT_SECRET=MUDE-ISTO-openssl-rand-hex-32 API_KEY=ophion_MUDE-ISTO-openssl-rand-hex-32 +# Agent Key - usado pelo ophion-agent e otel-collector +AGENT_KEY=ophion-secret-agent-key-2024 + # ───────────────────────────────────────────────────────────── # PostgreSQL # ───────────────────────────────────────────────────────────── diff --git a/README.md b/README.md index c0c8046..f03db78 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ **Open Source Observability Platform — AI-Powered Monitoring** [![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL%203.0-blue.svg)](LICENSE) -[![Website](https://img.shields.io/badge/Website-ophion.com.br-purple)](https://ophion.com.br) +[![Go](https://img.shields.io/badge/Go-1.22-00ADD8.svg)](https://golang.org/) +[![Docker](https://img.shields.io/badge/Docker-Compose-2496ED.svg)](https://docs.docker.com/compose/) --- @@ -21,22 +22,52 @@ OPHION é uma plataforma de observabilidade que combina **métricas, logs e trac | **Correlação de Alertas com IA** | ✅ | 💰 | ❌ | | **Previsões de Capacidade** | ✅ | 💰 | ❌ | | Open Source | ✅ | ❌ | ✅ | +| **Auto-instrumentação Universal** | ✅ | 💰 | ❌ | --- -## 🚀 Instalação Rápida +## 🚀 Quick Start (1 Comando) ```bash -curl -fsSL https://get.ophion.com.br | bash +git clone https://github.com/bigtux/ophion.git && cd ophion && docker compose up -d ``` -O instalador interativo irá: -- ✅ Verificar requisitos (Docker, Docker Compose) -- ✅ Coletar informações da sua empresa -- ✅ Gerar credenciais seguras -- ✅ Iniciar a plataforma +Aguarde ~2 minutos e acesse: +- **Dashboard:** http://localhost:3000 +- **API:** http://localhost:8080 +- **OTLP (traces):** localhost:4317 (gRPC) / localhost:4318 (HTTP) -**Pronto em menos de 5 minutos!** +📖 [Guia Completo de Quick Start](docs/QUICK_START.md) + +--- + +## 🔧 Instrumentar Sua Aplicação + +### Script Universal + +```bash +# Auto-detecta a linguagem +./instrument.sh my-container + +# Ou especifique +./instrument.sh my-container nodejs +./instrument.sh my-container python +./instrument.sh my-container java +./instrument.sh my-container dotnet +``` + +### Linguagens Suportadas + +| Linguagem | Método | Complexidade | +|-----------|--------|--------------| +| **.NET** | Auto-instrumentation | 🟢 Zero code | +| **Node.js** | Auto-instrumentation | 🟢 Zero code | +| **Python** | Auto-instrumentation | 🟢 Zero code | +| **Java** | Java Agent | 🟢 Zero code | +| **Go** | SDK (compile-time) | 🟡 Pequenas mudanças | +| **PHP** | SDK | 🟡 Pequenas mudanças | + +📖 [Guia de Instrumentação](docs/QUICK_START.md#-2-instrument-your-application) --- @@ -47,66 +78,110 @@ O instalador interativo irá: | CPU | 2 cores | 4+ cores | | RAM | 4 GB | 8+ GB | | Disco | 20 GB SSD | 100+ GB SSD | -| OS | Ubuntu 20.04+ | Ubuntu 22.04 LTS | +| Docker | 20.10+ | Latest | +| Docker Compose | v2+ | Latest | --- -## 🔧 Instalação Manual +## 📦 Arquitetura -```bash -# Clonar -git clone https://git.ophion.com.br/bigtux/ophion.git -cd ophion - -# Configurar -cp .env.example .env -nano .env - -# Iniciar -docker compose -f deploy/docker/docker-compose.yml up -d +``` +┌─────────────────────────────────────────────────────────────────┐ +│ YOUR APPLICATIONS │ +│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ +│ │ Node.js │ │ Python │ │ Java │ │ .NET │ │ Go │ │ +│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ +│ │ │ │ │ │ │ +│ └───────────┴───────────┼───────────┴───────────┘ │ +│ │ OTLP (4317/4318) │ +└───────────────────────────────┼─────────────────────────────────┘ + │ +┌───────────────────────────────┼─────────────────────────────────┐ +│ OPHION STACK ▼ │ +│ ┌─────────────────────────────────────────────────┐ │ +│ │ OpenTelemetry Collector │ │ +│ │ (process, batch, export) │ │ +│ └─────────────────────────┬───────────────────────┘ │ +│ │ │ +│ ┌────────────────┐ ▼ ┌────────────────┐ │ +│ │ Dashboard │◄──► Server ◄──►│ PostgreSQL │ │ +│ │ (Next.js) │ (Go API) │ ClickHouse │ │ +│ └────────────────┘ │ Redis │ │ +│ └────────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ ``` --- -## 📦 Estrutura +## 🔐 Autenticação + +### Para Aplicações (OTLP) +Envie traces para o OpenTelemetry Collector (porta 4317/4318) - sem auth necessário. + +### Para API +Use `AGENT_KEY` para agents ou JWT para dashboard: + +```bash +# .env +AGENT_KEY=my-secret-key +``` + +--- + +## 📦 Estrutura do Projeto ``` ophion/ -├── install.sh # Instalador interativo -├── .env.example # Exemplo de configuração +├── docker-compose.yml # Stack completa +├── instrument.sh # Script de instrumentação ├── cmd/ -│ ├── server/ # API Server (Go) -│ └── agent/ # Agent de coleta -├── dashboard/ # Frontend (Next.js) -├── deploy/docker/ # Docker configs -├── internal/ # Código interno -└── docs/ # Documentação +│ ├── server/ # API Server (Go) +│ └── agent/ # Agent de coleta +├── dashboard/ # Frontend (Next.js) +├── deploy/ +│ ├── docker/ # Docker configs +│ └── instrumentation/ # Container com agents OTel +├── internal/ # Código interno Go +└── docs/ + ├── QUICK_START.md # ⭐ Comece aqui + ├── INSTALL.md + └── SECURITY.md ``` --- -## 🔐 Segurança - -- **JWT + API Keys** (SHA256) -- **Bcrypt** para senhas -- **Rate Limiting** -- **RBAC** por roles - -📖 [Guia de Segurança](docs/SECURITY.md) - ---- - ## 📖 Documentação -- [Instalação](docs/INSTALL.md) +- ⭐ [Quick Start](docs/QUICK_START.md) - Comece em 5 minutos +- [Instalação Avançada](docs/INSTALL.md) - [Segurança](docs/SECURITY.md) -- [Manual PDF](docs/OPHION_Manual_Instalacao.pdf) +- [Manual Completo](docs/MANUAL_COMPLETO.md) + +--- + +## 🛠️ Desenvolvimento + +```bash +# Clonar +git clone https://github.com/bigtux/ophion.git +cd ophion + +# Compilar Go +go build ./... + +# Rodar localmente +docker compose up -d postgres redis +go run ./cmd/server + +# Testes +go test ./... +``` --- ## 🆘 Suporte -- **Website:** [ophion.com.br](https://ophion.com.br) +- **Issues:** https://github.com/bigtux/ophion/issues - **Email:** suporte@ophion.com.br --- diff --git a/deploy/docker/otel-collector-config.yaml b/deploy/docker/otel-collector-config.yaml index aca75c6..b345ba9 100644 --- a/deploy/docker/otel-collector-config.yaml +++ b/deploy/docker/otel-collector-config.yaml @@ -1,6 +1,6 @@ # ═══════════════════════════════════════════════════════════ # 🐍 OPHION - OpenTelemetry Collector Configuration -# Receives traces/metrics/logs from instrumented applications +# Central collector for all instrumented applications # ═══════════════════════════════════════════════════════════ receivers: @@ -14,8 +14,10 @@ receivers: cors: allowed_origins: - "*" + allowed_headers: + - "*" - # Prometheus receiver for metrics scraping (optional) + # Prometheus receiver for scraping metrics prometheus: config: scrape_configs: @@ -43,22 +45,24 @@ processors: - key: collector.name value: ophion-collector action: upsert - - key: deployment.environment - from_attribute: OTEL_RESOURCE_ATTRIBUTES - action: upsert - # Attributes processor for enrichment - attributes: - actions: - - key: ophion.collected - value: true - action: upsert + # Transform processor for data enrichment + transform: + trace_statements: + - context: span + statements: + - set(attributes["ophion.collected"], true) + metric_statements: + - context: datapoint + statements: + - set(attributes["ophion.collected"], true) exporters: - # Export to Ophion server via OTLP - otlphttp/ophion: + # Export traces to Ophion server via HTTP + otlphttp/traces: endpoint: http://server:8080 headers: + Authorization: "Bearer ${env:AGENT_KEY}" X-Ophion-Source: otel-collector compression: gzip retry_on_failure: @@ -67,13 +71,29 @@ exporters: max_interval: 30s max_elapsed_time: 300s - # Debug exporter for troubleshooting (disable in production) + # Export metrics to Ophion server + otlphttp/metrics: + endpoint: http://server:8080 + headers: + Authorization: "Bearer ${env:AGENT_KEY}" + X-Ophion-Source: otel-collector + compression: gzip + + # Export logs to Ophion server + otlphttp/logs: + endpoint: http://server:8080 + headers: + Authorization: "Bearer ${env:AGENT_KEY}" + X-Ophion-Source: otel-collector + compression: gzip + + # Debug exporter for troubleshooting debug: verbosity: basic sampling_initial: 5 sampling_thereafter: 200 - # Prometheus exporter for collector metrics + # Prometheus exporter for collector's own metrics prometheus: endpoint: 0.0.0.0:8889 namespace: ophion_collector @@ -99,20 +119,20 @@ service: # Traces pipeline traces: receivers: [otlp] - processors: [memory_limiter, batch, resource, attributes] - exporters: [otlphttp/ophion, debug] + processors: [memory_limiter, batch, resource, transform] + exporters: [otlphttp/traces, debug] - # Metrics pipeline + # Metrics pipeline metrics: receivers: [otlp, prometheus] processors: [memory_limiter, batch, resource] - exporters: [otlphttp/ophion, debug] + exporters: [otlphttp/metrics, debug] # Logs pipeline logs: receivers: [otlp] processors: [memory_limiter, batch, resource] - exporters: [otlphttp/ophion, debug] + exporters: [otlphttp/logs, debug] telemetry: logs: diff --git a/deploy/instrumentation/Dockerfile b/deploy/instrumentation/Dockerfile new file mode 100644 index 0000000..fd9d254 --- /dev/null +++ b/deploy/instrumentation/Dockerfile @@ -0,0 +1,74 @@ +# ═══════════════════════════════════════════════════════════ +# 🔧 OPHION Universal Instrumentation Container +# Downloads and provides OpenTelemetry agents for all languages +# ═══════════════════════════════════════════════════════════ + +FROM alpine:3.19 + +LABEL org.opencontainers.image.title="OPHION Instrumentation" +LABEL org.opencontainers.image.description="OpenTelemetry agents for .NET, Node.js, Python, Java, Go, PHP" + +# Install tools +RUN apk add --no-cache curl unzip bash jq + +# Create directory structure +RUN mkdir -p /otel/{dotnet,dotnet-musl,nodejs,python,java,go,php} + +WORKDIR /otel + +# ═══════════════════════════════════════════════════════════ +# .NET Auto-Instrumentation (glibc) +# ═══════════════════════════════════════════════════════════ +ENV OTEL_DOTNET_VERSION=1.6.0 +RUN curl -L --retry 3 --retry-delay 5 --max-time 120 \ + "https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/download/v${OTEL_DOTNET_VERSION}/opentelemetry-dotnet-instrumentation-linux-glibc-x64.zip" \ + -o /tmp/dotnet.zip && \ + unzip -q /tmp/dotnet.zip -d /otel/dotnet && \ + rm /tmp/dotnet.zip && \ + chmod +x /otel/dotnet/*.sh 2>/dev/null || true + +# .NET Auto-Instrumentation (musl/Alpine) +RUN curl -L --retry 3 --retry-delay 5 --max-time 120 \ + "https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/download/v${OTEL_DOTNET_VERSION}/opentelemetry-dotnet-instrumentation-linux-musl-x64.zip" \ + -o /tmp/dotnet-musl.zip && \ + unzip -q /tmp/dotnet-musl.zip -d /otel/dotnet-musl && \ + rm /tmp/dotnet-musl.zip && \ + chmod +x /otel/dotnet-musl/*.sh 2>/dev/null || true + +# ═══════════════════════════════════════════════════════════ +# Java Auto-Instrumentation +# Uses GitHub API to get proper redirect +# ═══════════════════════════════════════════════════════════ +ENV OTEL_JAVA_VERSION=2.1.0 +RUN JAVA_URL=$(curl -sL "https://api.github.com/repos/open-telemetry/opentelemetry-java-instrumentation/releases/tags/v${OTEL_JAVA_VERSION}" | \ + jq -r '.assets[] | select(.name=="opentelemetry-javaagent.jar") | .browser_download_url') && \ + if [ -n "$JAVA_URL" ] && [ "$JAVA_URL" != "null" ]; then \ + curl -L --retry 3 --max-time 180 "$JAVA_URL" -o /otel/java/opentelemetry-javaagent.jar; \ + else \ + echo "Downloading Java agent directly..." && \ + curl -L --retry 3 --max-time 180 \ + "https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v${OTEL_JAVA_VERSION}/opentelemetry-javaagent.jar" \ + -o /otel/java/opentelemetry-javaagent.jar; \ + fi && \ + ls -la /otel/java/ + +# ═══════════════════════════════════════════════════════════ +# Copy pre-created files for other languages +# ═══════════════════════════════════════════════════════════ +COPY files/ /otel/ + +# Set permissions +RUN chmod -R 755 /otel && \ + chmod +x /otel/python/bootstrap.sh 2>/dev/null || true + +# Verify downloads +RUN echo "=== OPHION Instrumentation Contents ===" && \ + ls -la /otel/ && \ + echo "=== Java agent size ===" && \ + ls -lh /otel/java/opentelemetry-javaagent.jar 2>/dev/null || echo "Java agent not present" && \ + echo "=== .NET ===" && ls /otel/dotnet/ | head -5 + +# Volume for sharing with other containers +VOLUME ["/otel"] + +CMD ["echo", "OpenTelemetry agents ready in /otel"] diff --git a/deploy/instrumentation/files/README.md b/deploy/instrumentation/files/README.md new file mode 100644 index 0000000..541a8f6 --- /dev/null +++ b/deploy/instrumentation/files/README.md @@ -0,0 +1,51 @@ +# OPHION OpenTelemetry Agents + +This volume contains auto-instrumentation agents for all major languages. + +## Directory Structure +- `/otel/dotnet/` - .NET auto-instrumentation (glibc) +- `/otel/dotnet-musl/` - .NET auto-instrumentation (Alpine/musl) +- `/otel/nodejs/` - Node.js SDK and loader +- `/otel/python/` - Python requirements and bootstrap +- `/otel/java/` - Java agent JAR +- `/otel/go/` - Go instrumentation examples +- `/otel/php/` - PHP composer package + +## Environment Variables (all languages) +- OTEL_EXPORTER_OTLP_ENDPOINT=http://ophion-otel-collector:4318 +- OTEL_SERVICE_NAME=your-service-name +- OTEL_RESOURCE_ATTRIBUTES=deployment.environment=production + +## Usage Examples + +### .NET +```dockerfile +ENV CORECLR_ENABLE_PROFILING=1 +ENV CORECLR_PROFILER={918728DD-259F-4A6A-AC2B-B85E1B658571} +ENV CORECLR_PROFILER_PATH=/otel/dotnet/linux-x64/OpenTelemetry.AutoInstrumentation.Native.so +ENV DOTNET_ADDITIONAL_DEPS=/otel/dotnet/AdditionalDeps +ENV DOTNET_SHARED_STORE=/otel/dotnet/store +ENV DOTNET_STARTUP_HOOKS=/otel/dotnet/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll +ENV OTEL_DOTNET_AUTO_HOME=/otel/dotnet +``` + +### Node.js +```bash +node -r /otel/nodejs/instrument.js your-app.js +``` + +### Python +```bash +source /otel/python/bootstrap.sh +opentelemetry-instrument python your-app.py +``` + +### Java +```bash +java -javaagent:/otel/java/opentelemetry-javaagent.jar -jar your-app.jar +``` + +### PHP +```bash +cd your-app && composer require open-telemetry/sdk open-telemetry/exporter-otlp +``` diff --git a/deploy/instrumentation/files/go/go.mod.example b/deploy/instrumentation/files/go/go.mod.example new file mode 100644 index 0000000..9511ea3 --- /dev/null +++ b/deploy/instrumentation/files/go/go.mod.example @@ -0,0 +1,5 @@ +// Add these to your go.mod: +// go get go.opentelemetry.io/otel +// go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp +// go get go.opentelemetry.io/otel/sdk/trace +// go get go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp diff --git a/deploy/instrumentation/files/go/init.go.example b/deploy/instrumentation/files/go/init.go.example new file mode 100644 index 0000000..a7ca715 --- /dev/null +++ b/deploy/instrumentation/files/go/init.go.example @@ -0,0 +1,34 @@ +package main + +import ( + "context" + "os" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.17.0" +) + +func InitTracing(serviceName string) (*sdktrace.TracerProvider, error) { + ctx := context.Background() + + exporter, err := otlptracehttp.New(ctx, + otlptracehttp.WithEndpoint(os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT")), + otlptracehttp.WithInsecure(), + ) + if err != nil { + return nil, err + } + + tp := sdktrace.NewTracerProvider( + sdktrace.WithBatcher(exporter), + sdktrace.WithResource(resource.NewWithAttributes( + semconv.SchemaURL, + semconv.ServiceName(serviceName), + )), + ) + otel.SetTracerProvider(tp) + return tp, nil +} diff --git a/deploy/instrumentation/files/nodejs/instrument.js b/deploy/instrumentation/files/nodejs/instrument.js new file mode 100644 index 0000000..d7e74e9 --- /dev/null +++ b/deploy/instrumentation/files/nodejs/instrument.js @@ -0,0 +1,25 @@ +const { NodeSDK } = require('@opentelemetry/sdk-node'); +const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node'); +const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http'); +const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-http'); +const { PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics'); + +const endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4318'; + +const sdk = new NodeSDK({ + traceExporter: new OTLPTraceExporter({ + url: endpoint + '/v1/traces', + }), + metricReader: new PeriodicExportingMetricReader({ + exporter: new OTLPMetricExporter({ + url: endpoint + '/v1/metrics', + }), + exportIntervalMillis: 30000, + }), + instrumentations: [getNodeAutoInstrumentations()], + serviceName: process.env.OTEL_SERVICE_NAME || 'nodejs-app', +}); + +sdk.start(); +process.on('SIGTERM', () => sdk.shutdown()); +console.log('[OPHION] OpenTelemetry auto-instrumentation enabled'); diff --git a/deploy/instrumentation/files/nodejs/package.json b/deploy/instrumentation/files/nodejs/package.json new file mode 100644 index 0000000..4233e48 --- /dev/null +++ b/deploy/instrumentation/files/nodejs/package.json @@ -0,0 +1,11 @@ +{ + "name": "otel-nodejs-agent", + "version": "1.0.0", + "dependencies": { + "@opentelemetry/api": "^1.7.0", + "@opentelemetry/auto-instrumentations-node": "^0.43.0", + "@opentelemetry/sdk-node": "^0.48.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.48.0", + "@opentelemetry/exporter-metrics-otlp-http": "^0.48.0" + } +} diff --git a/deploy/instrumentation/files/php/composer.json b/deploy/instrumentation/files/php/composer.json new file mode 100644 index 0000000..b37da78 --- /dev/null +++ b/deploy/instrumentation/files/php/composer.json @@ -0,0 +1,9 @@ +{ + "require": { + "open-telemetry/sdk": "^1.0", + "open-telemetry/exporter-otlp": "^1.0", + "open-telemetry/contrib-auto-slim": "^1.0", + "open-telemetry/contrib-auto-laravel": "^1.0", + "php-http/guzzle7-adapter": "^1.0" + } +} diff --git a/deploy/instrumentation/files/php/otel_init.php b/deploy/instrumentation/files/php/otel_init.php new file mode 100644 index 0000000..08816d4 --- /dev/null +++ b/deploy/instrumentation/files/php/otel_init.php @@ -0,0 +1,29 @@ +create($endpoint . '/v1/traces', 'application/json'); + $exporter = new SpanExporter($transport); + $tracerProvider = TracerProvider::builder() + ->addSpanProcessor(new SimpleSpanProcessor($exporter)) + ->setResource(ResourceInfo::create(Attributes::create(['service.name' => $serviceName]))) + ->build(); + Sdk::builder()->setTracerProvider($tracerProvider)->buildAndRegisterGlobal(); + error_log('[OPHION] OpenTelemetry initialized for PHP'); +} catch (Exception $e) { + error_log('[OPHION] Failed to initialize OpenTelemetry: ' . $e->getMessage()); +} diff --git a/deploy/instrumentation/files/python/bootstrap.sh b/deploy/instrumentation/files/python/bootstrap.sh new file mode 100644 index 0000000..97dcaae --- /dev/null +++ b/deploy/instrumentation/files/python/bootstrap.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# OPHION Python Auto-Instrumentation Bootstrap +pip install -q -r /otel/python/requirements.txt +opentelemetry-bootstrap -a install 2>/dev/null || true +echo "[OPHION] Python OpenTelemetry packages installed" diff --git a/deploy/instrumentation/files/python/requirements.txt b/deploy/instrumentation/files/python/requirements.txt new file mode 100644 index 0000000..05ccdc5 --- /dev/null +++ b/deploy/instrumentation/files/python/requirements.txt @@ -0,0 +1,3 @@ +opentelemetry-distro>=0.43b0 +opentelemetry-exporter-otlp>=1.22.0 +opentelemetry-instrumentation>=0.43b0 diff --git a/docker-compose.yml b/docker-compose.yml index 65ff9c7..d1195d1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,18 +1,38 @@ version: '3.8' # ═══════════════════════════════════════════════════════════ -# 🐍 OPHION - Docker Compose -# Observability Platform with ClickHouse, PostgreSQL, Redis +# 🐍 OPHION - Full Observability Stack +# Single docker compose up for complete observability platform # ═══════════════════════════════════════════════════════════ +x-ophion-common: &ophion-common + restart: unless-stopped + networks: + - ophion + services: # ───────────────────────────────────────────────────────── - # OPHION Server (Go API) + # 📦 INSTRUMENTATION INIT CONTAINER + # Downloads all OpenTelemetry agents for all languages + # ───────────────────────────────────────────────────────── + instrumentation: + build: + context: ./deploy/instrumentation + dockerfile: Dockerfile + container_name: ophion-instrumentation + volumes: + - otel_agents:/otel + command: ["echo", "Agents ready in /otel"] + <<: *ophion-common + + # ───────────────────────────────────────────────────────── + # 🐍 OPHION Server (Go API) # ───────────────────────────────────────────────────────── server: build: context: . dockerfile: deploy/docker/Dockerfile.server + container_name: ophion-server ports: - "8080:8080" environment: @@ -20,101 +40,40 @@ services: - DATABASE_URL=postgres://ophion:ophion@postgres:5432/ophion?sslmode=disable - CLICKHOUSE_URL=clickhouse://default:@clickhouse:9000/ophion - REDIS_URL=redis://redis:6379 + - AGENT_KEY=${AGENT_KEY:-ophion-secret-agent-key-2024} + - JWT_SECRET=${JWT_SECRET:-ophion-jwt-secret-change-in-production} depends_on: postgres: condition: service_healthy - clickhouse: - condition: service_healthy redis: condition: service_healthy - restart: unless-stopped - networks: - - ophion healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/health"] interval: 10s timeout: 5s retries: 3 + <<: *ophion-common # ───────────────────────────────────────────────────────── - # OPHION Dashboard (Next.js) + # 🖥️ OPHION Dashboard (Next.js) # ───────────────────────────────────────────────────────── dashboard: build: context: ./dashboard dockerfile: Dockerfile + container_name: ophion-dashboard ports: - "3000:3000" environment: - - NEXT_PUBLIC_API_URL=http://server:8080 + - NEXT_PUBLIC_API_URL=http://localhost:8080 - NODE_ENV=production depends_on: - server - restart: unless-stopped - networks: - - ophion + <<: *ophion-common # ───────────────────────────────────────────────────────── - # PostgreSQL (Metadata, Users, Alerts) - # ───────────────────────────────────────────────────────── - postgres: - image: postgres:16-alpine - environment: - POSTGRES_USER: ophion - POSTGRES_PASSWORD: ophion - POSTGRES_DB: ophion - volumes: - - postgres_data:/var/lib/postgresql/data - restart: unless-stopped - networks: - - ophion - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ophion"] - interval: 5s - timeout: 5s - retries: 5 - - # ───────────────────────────────────────────────────────── - # ClickHouse (Metrics, Traces, Logs) - # ───────────────────────────────────────────────────────── - clickhouse: - image: clickhouse/clickhouse-server:24.1 - ports: - - "9000:9000" # Native protocol - - "8123:8123" # HTTP interface - volumes: - - clickhouse_data:/var/lib/clickhouse - - ./configs/clickhouse:/etc/clickhouse-server/config.d - environment: - - CLICKHOUSE_DB=ophion - restart: unless-stopped - networks: - - ophion - healthcheck: - test: ["CMD", "clickhouse-client", "--query", "SELECT 1"] - interval: 5s - timeout: 5s - retries: 5 - - # ───────────────────────────────────────────────────────── - # Redis (Cache, Pub/Sub) - # ───────────────────────────────────────────────────────── - redis: - image: redis:7-alpine - command: redis-server --appendonly yes - volumes: - - redis_data:/data - restart: unless-stopped - networks: - - ophion - healthcheck: - test: ["CMD", "redis-cli", "ping"] - interval: 5s - timeout: 5s - retries: 5 - - # ───────────────────────────────────────────────────────── - # OpenTelemetry Collector (Traces, Metrics, Logs) + # 📊 OpenTelemetry Collector + # Central receiver for all instrumented applications # ───────────────────────────────────────────────────────── otel-collector: image: otel/opentelemetry-collector-contrib:0.96.0 @@ -123,17 +82,15 @@ services: volumes: - ./deploy/docker/otel-collector-config.yaml:/etc/otel-collector-config.yaml:ro ports: - - "4317:4317" # OTLP gRPC receiver - - "4318:4318" # OTLP HTTP receiver - - "8889:8889" # Prometheus exporter metrics - - "13133:13133" # Health check extension + - "4317:4317" # OTLP gRPC + - "4318:4318" # OTLP HTTP + - "8889:8889" # Prometheus metrics + - "13133:13133" # Health check environment: - - OTEL_RESOURCE_ATTRIBUTES=service.name=ophion-collector,service.version=1.0.0 + - OPHION_SERVER=http://server:8080 + - AGENT_KEY=${AGENT_KEY:-ophion-secret-agent-key-2024} depends_on: - server - restart: unless-stopped - networks: - - ophion healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:13133/health"] interval: 10s @@ -143,14 +100,92 @@ services: resources: limits: memory: 512M - reservations: - memory: 128M + <<: *ophion-common + + # ───────────────────────────────────────────────────────── + # 🐘 PostgreSQL (Metadata, Users, Alerts) + # ───────────────────────────────────────────────────────── + postgres: + image: postgres:16-alpine + container_name: ophion-postgres + environment: + POSTGRES_USER: ophion + POSTGRES_PASSWORD: ophion + POSTGRES_DB: ophion + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ophion"] + interval: 5s + timeout: 5s + retries: 5 + <<: *ophion-common + + # ───────────────────────────────────────────────────────── + # 📈 ClickHouse (Metrics, Traces, Logs - High Volume) + # ───────────────────────────────────────────────────────── + clickhouse: + image: clickhouse/clickhouse-server:24.1 + container_name: ophion-clickhouse + ports: + - "9000:9000" # Native protocol + - "8123:8123" # HTTP interface + volumes: + - clickhouse_data:/var/lib/clickhouse + environment: + - CLICKHOUSE_DB=ophion + healthcheck: + test: ["CMD", "clickhouse-client", "--query", "SELECT 1"] + interval: 5s + timeout: 5s + retries: 5 + <<: *ophion-common + + # ───────────────────────────────────────────────────────── + # 🔴 Redis (Cache, Pub/Sub, Rate Limiting) + # ───────────────────────────────────────────────────────── + redis: + image: redis:7-alpine + container_name: ophion-redis + command: redis-server --appendonly yes + volumes: + - redis_data:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 5s + retries: 5 + <<: *ophion-common + + # ───────────────────────────────────────────────────────── + # 🤖 OPHION Agent (System Metrics) + # Collect host metrics and send to server + # ───────────────────────────────────────────────────────── + agent: + build: + context: . + dockerfile: deploy/docker/Dockerfile.agent + container_name: ophion-agent + environment: + - OPHION_SERVER=http://server:8080 + - OPHION_API_KEY=${AGENT_KEY:-ophion-secret-agent-key-2024} + - OPHION_INTERVAL=30s + - OPHION_DOCKER=true + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + depends_on: + server: + condition: service_healthy + <<: *ophion-common networks: ophion: driver: bridge + name: ophion-network volumes: postgres_data: clickhouse_data: redis_data: + otel_agents: + name: ophion-otel-agents diff --git a/docs/QUICK_START.md b/docs/QUICK_START.md new file mode 100644 index 0000000..db10999 --- /dev/null +++ b/docs/QUICK_START.md @@ -0,0 +1,347 @@ +# 🐍 OPHION - Quick Start Guide + +Get full observability (traces, metrics, logs) for your applications in minutes. + +## 📋 Prerequisites + +- Docker & Docker Compose v2+ +- 4GB RAM minimum +- Ports available: 3000, 4317, 4318, 8080 + +--- + +## 🚀 1. Install Ophion (Single Command) + +```bash +# Clone and start +git clone https://github.com/bigtux/ophion.git +cd ophion +docker compose up -d +``` + +That's it! Wait ~2 minutes for all services to start. + +### Verify Installation + +```bash +# Check all services are running +docker compose ps + +# Should see: +# ophion-server running (healthy) +# ophion-dashboard running +# ophion-otel-collector running (healthy) +# ophion-postgres running (healthy) +# ophion-redis running (healthy) +``` + +### Access Points + +| Service | URL | Description | +|---------|-----|-------------| +| Dashboard | http://localhost:3000 | Web UI for traces, metrics, logs | +| API | http://localhost:8080 | REST API | +| OTLP gRPC | localhost:4317 | OpenTelemetry gRPC endpoint | +| OTLP HTTP | localhost:4318 | OpenTelemetry HTTP endpoint | + +--- + +## 🔧 2. Instrument Your Application + +### Quick Method: Use the Universal Script + +```bash +# Auto-detect language +./instrument.sh my-container + +# Or specify language +./instrument.sh my-container nodejs +./instrument.sh my-container python +./instrument.sh my-container java +./instrument.sh my-container dotnet +``` + +### Manual Configuration by Language + +#### Node.js + +```dockerfile +# Dockerfile +FROM node:20-alpine + +# Add OTel packages +RUN npm install @opentelemetry/auto-instrumentations-node @opentelemetry/sdk-node + +COPY . . + +# Run with auto-instrumentation +CMD ["node", "--require", "@opentelemetry/auto-instrumentations-node/register", "app.js"] +``` + +```yaml +# docker-compose.yml +services: + myapp: + environment: + - OTEL_EXPORTER_OTLP_ENDPOINT=http://ophion-otel-collector:4318 + - OTEL_SERVICE_NAME=my-nodejs-app + networks: + - ophion-network + +networks: + ophion-network: + external: true +``` + +#### Python + +```dockerfile +# Dockerfile +FROM python:3.11-slim + +RUN pip install opentelemetry-distro opentelemetry-exporter-otlp +RUN opentelemetry-bootstrap -a install + +COPY . . + +CMD ["opentelemetry-instrument", "python", "app.py"] +``` + +```yaml +# docker-compose.yml +services: + myapp: + environment: + - OTEL_EXPORTER_OTLP_ENDPOINT=http://ophion-otel-collector:4318 + - OTEL_SERVICE_NAME=my-python-app + - OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true + networks: + - ophion-network +``` + +#### Java + +```dockerfile +# Dockerfile +FROM eclipse-temurin:21-jre + +# Download OTel Java agent +ADD https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar /otel/agent.jar + +COPY target/app.jar /app.jar + +CMD ["java", "-javaagent:/otel/agent.jar", "-jar", "/app.jar"] +``` + +```yaml +# docker-compose.yml +services: + myapp: + environment: + - OTEL_EXPORTER_OTLP_ENDPOINT=http://ophion-otel-collector:4318 + - OTEL_SERVICE_NAME=my-java-app + - JAVA_TOOL_OPTIONS=-javaagent:/otel/agent.jar + networks: + - ophion-network +``` + +#### .NET + +```dockerfile +# Dockerfile +FROM mcr.microsoft.com/dotnet/aspnet:8.0 + +# Download OTel .NET instrumentation +ADD https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/latest/download/opentelemetry-dotnet-instrumentation-linux-glibc-x64.zip /tmp/otel.zip +RUN apt-get update && apt-get install -y unzip && \ + unzip /tmp/otel.zip -d /otel && rm /tmp/otel.zip + +COPY --from=build /app/publish . + +ENV CORECLR_ENABLE_PROFILING=1 +ENV CORECLR_PROFILER={918728DD-259F-4A6A-AC2B-B85E1B658571} +ENV CORECLR_PROFILER_PATH=/otel/linux-x64/OpenTelemetry.AutoInstrumentation.Native.so +ENV DOTNET_ADDITIONAL_DEPS=/otel/AdditionalDeps +ENV DOTNET_SHARED_STORE=/otel/store +ENV DOTNET_STARTUP_HOOKS=/otel/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll +ENV OTEL_DOTNET_AUTO_HOME=/otel + +CMD ["dotnet", "MyApp.dll"] +``` + +```yaml +# docker-compose.yml +services: + myapp: + environment: + - OTEL_EXPORTER_OTLP_ENDPOINT=http://ophion-otel-collector:4318 + - OTEL_SERVICE_NAME=my-dotnet-app + networks: + - ophion-network +``` + +#### Go + +Go requires code changes (compile-time instrumentation): + +```go +import ( + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" +) + +func main() { + // Initialize tracer + exporter, _ := otlptracehttp.New(context.Background()) + tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter)) + otel.SetTracerProvider(tp) + + // Wrap HTTP handlers + http.Handle("/", otelhttp.NewHandler(myHandler, "myHandler")) +} +``` + +--- + +## 📊 3. View Your Data + +### Dashboard + +Open http://localhost:3000 in your browser. + +**Default Login:** +- Email: `admin@ophion.io` +- Password: `OphionAdmin123!` + +### API Examples + +```bash +# Get traces +curl http://localhost:8080/api/v1/traces \ + -H "Authorization: Bearer " + +# Get metrics +curl "http://localhost:8080/api/v1/metrics?service=my-app&name=http.request.duration" \ + -H "Authorization: Bearer " + +# Get logs +curl "http://localhost:8080/api/v1/logs?service=my-app&level=error" \ + -H "Authorization: Bearer " +``` + +--- + +## 🔑 Authentication + +### For the Dashboard (Users) + +Register and login at http://localhost:3000 + +### For Applications (OTLP) + +Applications send telemetry to the **otel-collector** (ports 4317/4318) which doesn't require auth by default. + +### For the API (Agents) + +Use the `AGENT_KEY` environment variable: + +```bash +# Default key (change in production!) +AGENT_KEY=ophion-secret-agent-key-2024 + +# Custom key +export AGENT_KEY=my-super-secret-key +docker compose up -d +``` + +--- + +## 📁 Environment Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| `AGENT_KEY` | `ophion-secret-agent-key-2024` | Key for agent authentication | +| `JWT_SECRET` | `ophion-jwt-secret-...` | Secret for JWT tokens | +| `DATABASE_URL` | `postgres://...` | PostgreSQL connection | +| `REDIS_URL` | `redis://redis:6379` | Redis connection | + +Create a `.env` file in the project root: + +```env +AGENT_KEY=my-production-key-here +JWT_SECRET=my-production-jwt-secret +``` + +--- + +## 🐳 Docker Network + +Your instrumented applications need to be on the same network as Ophion: + +```yaml +# Your app's docker-compose.yml +networks: + ophion-network: + external: true +``` + +Or connect manually: + +```bash +docker network connect ophion-network my-container +``` + +--- + +## 🔍 Troubleshooting + +### No traces appearing? + +1. Check collector logs: + ```bash + docker logs ophion-otel-collector + ``` + +2. Verify network connectivity: + ```bash + docker exec my-container curl http://ophion-otel-collector:4318/v1/traces + ``` + +3. Check environment variables are set: + ```bash + docker exec my-container env | grep OTEL + ``` + +### Container can't reach collector? + +Make sure your container is on the `ophion-network`: + +```bash +docker network connect ophion-network my-container +``` + +### Server returns 401? + +Check `AGENT_KEY` matches in server and agent: + +```bash +docker exec ophion-server env | grep AGENT_KEY +docker exec ophion-agent env | grep OPHION_API_KEY +``` + +--- + +## 📚 Next Steps + +- Read [MANUAL_COMPLETO.md](./MANUAL_COMPLETO.md) for advanced configuration +- Set up alerts at `/alerts` in the dashboard +- Configure AI insights with your OpenAI key +- Deploy to production with proper secrets + +--- + +## 🆘 Support + +- Issues: https://github.com/bigtux/ophion/issues +- Docs: https://ophion.io/docs diff --git a/instrument.sh b/instrument.sh new file mode 100755 index 0000000..0c119b5 --- /dev/null +++ b/instrument.sh @@ -0,0 +1,405 @@ +#!/bin/bash + +# ═══════════════════════════════════════════════════════════ +# 🔧 OPHION Universal Instrumentation Script +# Auto-instrument any containerized application +# ═══════════════════════════════════════════════════════════ +# +# Usage: +# ./instrument.sh [language] [ophion_server] +# +# Examples: +# ./instrument.sh myapp # Auto-detect language +# ./instrument.sh myapp nodejs # Explicit Node.js +# ./instrument.sh myapp python http://ophion:4318 +# +# Supported languages: dotnet, nodejs, python, java, go, php +# ═══════════════════════════════════════════════════════════ + +set -e + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +print_banner() { + echo -e "${BLUE}" + echo "╔═══════════════════════════════════════════════════════════╗" + echo "║ 🐍 OPHION - Universal Instrumentation ║" + echo "╚═══════════════════════════════════════════════════════════╝" + echo -e "${NC}" +} + +log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } +log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; } +log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } +log_error() { echo -e "${RED}[ERROR]${NC} $1"; } + +# Configuration +CONTAINER_NAME="${1:-}" +LANGUAGE="${2:-auto}" +OPHION_SERVER="${3:-http://ophion-otel-collector:4318}" +OTEL_VOLUME="ophion-otel-agents" + +if [[ -z "$CONTAINER_NAME" ]]; then + print_banner + echo "Usage: $0 [language] [ophion_server]" + echo "" + echo "Arguments:" + echo " container_name Name or ID of the Docker container" + echo " language One of: dotnet, nodejs, python, java, go, php, auto (default)" + echo " ophion_server OTLP endpoint (default: http://ophion-otel-collector:4318)" + echo "" + echo "Examples:" + echo " $0 myapp" + echo " $0 myapp nodejs" + echo " $0 myapp python http://localhost:4318" + exit 1 +fi + +print_banner + +# Check if container exists +if ! docker inspect "$CONTAINER_NAME" &>/dev/null; then + log_error "Container '$CONTAINER_NAME' not found" + exit 1 +fi + +log_info "Container: $CONTAINER_NAME" + +# Detect language if auto +detect_language() { + local container="$1" + + log_info "Auto-detecting language..." + + # Check running processes + local processes + processes=$(docker exec "$container" ps aux 2>/dev/null || echo "") + + # Check for specific runtimes + if echo "$processes" | grep -qE "dotnet|aspnet"; then + echo "dotnet" + elif echo "$processes" | grep -qE "node|npm|yarn"; then + echo "nodejs" + elif echo "$processes" | grep -qE "python|gunicorn|uvicorn|flask|django"; then + echo "python" + elif echo "$processes" | grep -qE "java|jvm"; then + echo "java" + elif docker exec "$container" test -f /usr/local/bin/php 2>/dev/null; then + echo "php" + else + # Check for common files + if docker exec "$container" test -f package.json 2>/dev/null; then + echo "nodejs" + elif docker exec "$container" test -f requirements.txt 2>/dev/null || \ + docker exec "$container" test -f pyproject.toml 2>/dev/null; then + echo "python" + elif docker exec "$container" test -f pom.xml 2>/dev/null || \ + docker exec "$container" test -f build.gradle 2>/dev/null; then + echo "java" + elif docker exec "$container" find / -name "*.csproj" 2>/dev/null | head -1 | grep -q .; then + echo "dotnet" + elif docker exec "$container" test -f composer.json 2>/dev/null; then + echo "php" + elif docker exec "$container" test -f go.mod 2>/dev/null; then + echo "go" + else + echo "unknown" + fi + fi +} + +if [[ "$LANGUAGE" == "auto" ]]; then + LANGUAGE=$(detect_language "$CONTAINER_NAME") + if [[ "$LANGUAGE" == "unknown" ]]; then + log_error "Could not auto-detect language. Please specify: dotnet, nodejs, python, java, go, php" + exit 1 + fi + log_success "Detected language: $LANGUAGE" +fi + +# Ensure OTEL volume exists +if ! docker volume inspect "$OTEL_VOLUME" &>/dev/null; then + log_warn "OTEL agents volume not found. Creating..." + docker run --rm -v "$OTEL_VOLUME":/otel ophion-instrumentation 2>/dev/null || { + log_error "Failed to create OTEL agents volume. Run 'docker compose up instrumentation' first." + exit 1 + } +fi + +# Get container image to determine if it's Alpine (musl) or glibc +IS_ALPINE=false +if docker exec "$CONTAINER_NAME" cat /etc/os-release 2>/dev/null | grep -qi alpine; then + IS_ALPINE=true +fi + +# Service name from container name +SERVICE_NAME="${CONTAINER_NAME//-/_}" + +log_info "Language: $LANGUAGE" +log_info "OTLP Endpoint: $OPHION_SERVER" +log_info "Service Name: $SERVICE_NAME" + +# Common environment variables +COMMON_ENV=( + -e "OTEL_EXPORTER_OTLP_ENDPOINT=$OPHION_SERVER" + -e "OTEL_SERVICE_NAME=$SERVICE_NAME" + -e "OTEL_RESOURCE_ATTRIBUTES=deployment.environment=production,service.namespace=ophion" + -e "OTEL_TRACES_EXPORTER=otlp" + -e "OTEL_METRICS_EXPORTER=otlp" + -e "OTEL_LOGS_EXPORTER=otlp" +) + +generate_docker_compose() { + local lang="$1" + local output_file="docker-compose.instrumented.yml" + + cat > "$output_file" << EOF +# Auto-generated by OPHION instrument.sh +# Add these settings to your docker-compose.yml + +version: '3.8' + +services: + ${CONTAINER_NAME}: + # Add these environment variables: + environment: + - OTEL_EXPORTER_OTLP_ENDPOINT=${OPHION_SERVER} + - OTEL_SERVICE_NAME=${SERVICE_NAME} + - OTEL_RESOURCE_ATTRIBUTES=deployment.environment=production +EOF + + case "$lang" in + dotnet) + local dotnet_path="/otel/dotnet" + [[ "$IS_ALPINE" == true ]] && dotnet_path="/otel/dotnet-musl" + cat >> "$output_file" << EOF + - CORECLR_ENABLE_PROFILING=1 + - CORECLR_PROFILER={918728DD-259F-4A6A-AC2B-B85E1B658571} + - CORECLR_PROFILER_PATH=${dotnet_path}/linux-x64/OpenTelemetry.AutoInstrumentation.Native.so + - DOTNET_ADDITIONAL_DEPS=${dotnet_path}/AdditionalDeps + - DOTNET_SHARED_STORE=${dotnet_path}/store + - DOTNET_STARTUP_HOOKS=${dotnet_path}/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll + - OTEL_DOTNET_AUTO_HOME=${dotnet_path} + volumes: + - ophion-otel-agents:/otel:ro +EOF + ;; + nodejs) + cat >> "$output_file" << EOF + - NODE_OPTIONS=--require /otel/nodejs/instrument.js + volumes: + - ophion-otel-agents:/otel:ro + # Note: Run 'npm install' in /otel/nodejs first or copy package.json deps +EOF + ;; + python) + cat >> "$output_file" << EOF + # For Python, modify your entrypoint: + # command: opentelemetry-instrument python your-app.py + # Or use PYTHONPATH + volumes: + - ophion-otel-agents:/otel:ro + # Run: pip install opentelemetry-distro opentelemetry-exporter-otlp && opentelemetry-bootstrap -a install +EOF + ;; + java) + cat >> "$output_file" << EOF + - JAVA_TOOL_OPTIONS=-javaagent:/otel/java/opentelemetry-javaagent.jar + volumes: + - ophion-otel-agents:/otel:ro +EOF + ;; + php) + cat >> "$output_file" << EOF + # For PHP, add to your composer.json: + # "require": { "open-telemetry/sdk": "^1.0", "open-telemetry/exporter-otlp": "^1.0" } + # And include /otel/php/otel_init.php in your bootstrap + volumes: + - ophion-otel-agents:/otel:ro +EOF + ;; + go) + cat >> "$output_file" << EOF + # For Go, instrumentation is compile-time. + # See /otel/go/init.go.example for code to add to your application. + # No runtime volumes needed. +EOF + ;; + esac + + cat >> "$output_file" << EOF + +networks: + default: + external: true + name: ophion-network + +volumes: + ophion-otel-agents: + external: true +EOF + + log_success "Generated $output_file" +} + +# Apply instrumentation based on language +case "$LANGUAGE" in + dotnet) + log_info "Applying .NET auto-instrumentation..." + DOTNET_PATH="/otel/dotnet" + [[ "$IS_ALPINE" == true ]] && DOTNET_PATH="/otel/dotnet-musl" + + cat << EOF + +📋 Add these environment variables to your container: + +docker run \\ + -e CORECLR_ENABLE_PROFILING=1 \\ + -e CORECLR_PROFILER={918728DD-259F-4A6A-AC2B-B85E1B658571} \\ + -e CORECLR_PROFILER_PATH=${DOTNET_PATH}/linux-x64/OpenTelemetry.AutoInstrumentation.Native.so \\ + -e DOTNET_ADDITIONAL_DEPS=${DOTNET_PATH}/AdditionalDeps \\ + -e DOTNET_SHARED_STORE=${DOTNET_PATH}/store \\ + -e DOTNET_STARTUP_HOOKS=${DOTNET_PATH}/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll \\ + -e OTEL_DOTNET_AUTO_HOME=${DOTNET_PATH} \\ + -e OTEL_EXPORTER_OTLP_ENDPOINT=${OPHION_SERVER} \\ + -e OTEL_SERVICE_NAME=${SERVICE_NAME} \\ + -v ${OTEL_VOLUME}:/otel:ro \\ + --network ophion-network \\ + your-image + +EOF + ;; + + nodejs) + log_info "Applying Node.js auto-instrumentation..." + cat << EOF + +📋 Add these to your container: + +# Option 1: NODE_OPTIONS (recommended) +docker run \\ + -e NODE_OPTIONS="--require /otel/nodejs/instrument.js" \\ + -e OTEL_EXPORTER_OTLP_ENDPOINT=${OPHION_SERVER} \\ + -e OTEL_SERVICE_NAME=${SERVICE_NAME} \\ + -v ${OTEL_VOLUME}:/otel:ro \\ + --network ophion-network \\ + your-image + +# Option 2: Modify your package.json start script +# "start": "node -r /otel/nodejs/instrument.js your-app.js" + +# Note: First install deps: cd /otel/nodejs && npm install + +EOF + ;; + + python) + log_info "Applying Python auto-instrumentation..." + cat << EOF + +📋 Add these to your container: + +# First, install packages in your Dockerfile: +# RUN pip install opentelemetry-distro opentelemetry-exporter-otlp && \\ +# opentelemetry-bootstrap -a install + +# Then run with: +docker run \\ + -e OTEL_EXPORTER_OTLP_ENDPOINT=${OPHION_SERVER} \\ + -e OTEL_SERVICE_NAME=${SERVICE_NAME} \\ + --network ophion-network \\ + your-image \\ + opentelemetry-instrument python your-app.py + +# Or use OTEL_PYTHON_CONFIGURATOR=true in your Dockerfile + +EOF + ;; + + java) + log_info "Applying Java auto-instrumentation..." + cat << EOF + +📋 Add these to your container: + +docker run \\ + -e JAVA_TOOL_OPTIONS="-javaagent:/otel/java/opentelemetry-javaagent.jar" \\ + -e OTEL_EXPORTER_OTLP_ENDPOINT=${OPHION_SERVER} \\ + -e OTEL_SERVICE_NAME=${SERVICE_NAME} \\ + -v ${OTEL_VOLUME}:/otel:ro \\ + --network ophion-network \\ + your-image + +EOF + ;; + + go) + log_info "Go instrumentation requires code changes..." + cat << EOF + +📋 Go requires compile-time instrumentation. Add this code: + +1. Add dependencies: + go get go.opentelemetry.io/otel + go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp + go get go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp + +2. See example code: /otel/go/init.go.example + +3. Set environment: + OTEL_EXPORTER_OTLP_ENDPOINT=${OPHION_SERVER} + OTEL_SERVICE_NAME=${SERVICE_NAME} + +EOF + ;; + + php) + log_info "Applying PHP auto-instrumentation..." + cat << EOF + +📋 Add to your PHP application: + +1. Add to composer.json: + { + "require": { + "open-telemetry/sdk": "^1.0", + "open-telemetry/exporter-otlp": "^1.0", + "php-http/guzzle7-adapter": "^1.0" + } + } + +2. Run: composer require open-telemetry/sdk open-telemetry/exporter-otlp + +3. Include in bootstrap: + require_once '/otel/php/otel_init.php'; + +4. Set environment: + OTEL_EXPORTER_OTLP_ENDPOINT=${OPHION_SERVER} + OTEL_SERVICE_NAME=${SERVICE_NAME} + +EOF + ;; + + *) + log_error "Unsupported language: $LANGUAGE" + exit 1 + ;; +esac + +# Generate docker-compose snippet +generate_docker_compose "$LANGUAGE" + +echo "" +log_success "Instrumentation configuration generated!" +log_info "See docker-compose.instrumented.yml for complete configuration" +echo "" +echo -e "${GREEN}Next steps:${NC}" +echo "1. Apply the environment variables to your container" +echo "2. Ensure container is on the 'ophion-network' network" +echo "3. Restart your container" +echo "4. Check traces at http://localhost:3000 (Ophion Dashboard)"