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 <container> [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
This commit is contained in:
74
deploy/instrumentation/Dockerfile
Normal file
74
deploy/instrumentation/Dockerfile
Normal file
@@ -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"]
|
||||
51
deploy/instrumentation/files/README.md
Normal file
51
deploy/instrumentation/files/README.md
Normal file
@@ -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
|
||||
```
|
||||
5
deploy/instrumentation/files/go/go.mod.example
Normal file
5
deploy/instrumentation/files/go/go.mod.example
Normal file
@@ -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
|
||||
34
deploy/instrumentation/files/go/init.go.example
Normal file
34
deploy/instrumentation/files/go/init.go.example
Normal file
@@ -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
|
||||
}
|
||||
25
deploy/instrumentation/files/nodejs/instrument.js
Normal file
25
deploy/instrumentation/files/nodejs/instrument.js
Normal file
@@ -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');
|
||||
11
deploy/instrumentation/files/nodejs/package.json
Normal file
11
deploy/instrumentation/files/nodejs/package.json
Normal file
@@ -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"
|
||||
}
|
||||
}
|
||||
9
deploy/instrumentation/files/php/composer.json
Normal file
9
deploy/instrumentation/files/php/composer.json
Normal file
@@ -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"
|
||||
}
|
||||
}
|
||||
29
deploy/instrumentation/files/php/otel_init.php
Normal file
29
deploy/instrumentation/files/php/otel_init.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* OPHION PHP OpenTelemetry Initialization
|
||||
* Include this file in your application bootstrap
|
||||
*/
|
||||
|
||||
use OpenTelemetry\SDK\Sdk;
|
||||
use OpenTelemetry\SDK\Trace\TracerProvider;
|
||||
use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
|
||||
use OpenTelemetry\Contrib\Otlp\SpanExporter;
|
||||
use OpenTelemetry\SDK\Common\Export\Http\PsrTransportFactory;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfo;
|
||||
use OpenTelemetry\SDK\Common\Attribute\Attributes;
|
||||
|
||||
$endpoint = getenv('OTEL_EXPORTER_OTLP_ENDPOINT') ?: 'http://localhost:4318';
|
||||
$serviceName = getenv('OTEL_SERVICE_NAME') ?: 'php-app';
|
||||
|
||||
try {
|
||||
$transport = (new PsrTransportFactory())->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());
|
||||
}
|
||||
5
deploy/instrumentation/files/python/bootstrap.sh
Normal file
5
deploy/instrumentation/files/python/bootstrap.sh
Normal file
@@ -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"
|
||||
3
deploy/instrumentation/files/python/requirements.txt
Normal file
3
deploy/instrumentation/files/python/requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
opentelemetry-distro>=0.43b0
|
||||
opentelemetry-exporter-otlp>=1.22.0
|
||||
opentelemetry-instrumentation>=0.43b0
|
||||
Reference in New Issue
Block a user