Skip to content

Commit 3bd76e9

Browse files
Add OTel configuration
1 parent 603bf72 commit 3bd76e9

File tree

4 files changed

+135
-7
lines changed

4 files changed

+135
-7
lines changed

Dockerfile.server

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ COPY examples/ ./examples/
1414
COPY chat-ui/ ./chat-ui/
1515
COPY scripts/provider-list.yaml ./scripts/
1616
COPY scripts/filter_guardrails.py ./scripts/
17+
COPY scripts/setup_otel.py ./scripts/
1718
COPY scripts/entrypoint.sh ./scripts/
1819
RUN chmod +x ./scripts/entrypoint.sh
1920

@@ -24,7 +25,11 @@ ENV POETRY_VIRTUALENVS_IN_PROJECT=1 \
2425
POETRY_NO_INTERACTION=1
2526

2627
RUN poetry install --no-ansi --extras="sdd jailbreak openai nvidia tracing" && \
27-
poetry run pip install "spacy>=3.4.4,<4.0.0" && \
28+
poetry run pip install \
29+
"spacy>=3.4.4,<4.0.0" \
30+
"opentelemetry-api>=1.27.0,<2.0.0" \
31+
"opentelemetry-sdk>=1.27.0,<2.0.0" \
32+
"opentelemetry-exporter-otlp>=1.27.0,<2.0.0" && \
2833
poetry run python -m spacy download en_core_web_lg
2934

3035
FROM registry.access.redhat.com/ubi9/python-312

poetry.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/entrypoint.sh

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,54 @@ if [[ ! -f "$CONFIG_DIR/rails.co" ]]; then
1919
exit 1
2020
fi
2121

22+
# Setup OpenTelemetry
23+
ENABLE_OTEL=$(echo "$ENABLE_OTEL" | tr '[:upper:]' '[:lower:]')
24+
if [[ "$ENABLE_OTEL" == "true" ]]; then
25+
echo "🔧 Configuring OpenTelemetry:"
26+
export OTEL_SERVICE_NAME="${OTEL_SERVICE_NAME:-guardrails}"
27+
export OTEL_SERVICE_VERSION="${OTEL_SERVICE_VERSION:-1.0.0}"
28+
export OTEL_ENVIRONMENT="${OTEL_ENVIRONMENT:-production}"
29+
export OTEL_ENABLE_CONSOLE="${OTEL_ENABLE_CONSOLE:-false}"
30+
export OTEL_EXPORTER_OTLP_INSECURE="${OTEL_EXPORTER_OTLP_INSECURE:-true}"
31+
export OTEL_EXPORTER_OTLP_ENDPOINT="${OTEL_EXPORTER_OTLP_ENDPOINT:-http://jaeger:4317}"
32+
33+
else
34+
echo "📝 OpenTelemetry disabled - starting without tracing"
35+
fi
36+
37+
echo ""
2238
echo "✅ Configuration validated. Starting server..."
23-
exec /app/.venv/bin/nemoguardrails server \
24-
--config "/app/config" \
25-
--port "$PORT" \
26-
--default-config-id "$CONFIG_ID" \
27-
--disable-chat-ui
39+
40+
exec /app/.venv/bin/python3 -c "
41+
import os
42+
import sys
43+
44+
# Setup OpenTelemetry if enabled
45+
if os.getenv('ENABLE_OTEL', '').lower() == 'true':
46+
print('🔍 Setting up OpenTelemetry within server process...')
47+
try:
48+
import logging
49+
logging.basicConfig(level=logging.INFO)
50+
sys.path.insert(0, '/app/scripts')
51+
from setup_otel import setup_opentelemetry
52+
setup_opentelemetry()
53+
print("✅ OpenTelemetry configured successfully. Starting server...")
54+
except (ImportError, ModuleNotFoundError) as e:
55+
print(f"❌ OpenTelemetry dependencies missing: {e}. Starting server without tracing.")
56+
except Exception as e:
57+
print(f"❌ OpenTelemetry setup failed: {e}. Starting server without tracing.")
58+
import traceback
59+
traceback.print_exc()
60+
61+
# Start the NeMo Guardrails server
62+
import uvicorn
63+
from nemoguardrails.server import api
64+
65+
# Set up the server configuration
66+
api.app.rails_config_path = '/app/config'
67+
api.app.disable_chat_ui = True
68+
api.set_default_config_id('${CONFIG_ID}')
69+
70+
# Start the server using uvicorn
71+
uvicorn.run(api.app, port=${PORT}, log_level='info', host='0.0.0.0')
72+
"

scripts/setup_otel.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import logging
2+
import os
3+
4+
from opentelemetry import trace
5+
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
6+
from opentelemetry.sdk.resources import Resource
7+
from opentelemetry.sdk.trace import TracerProvider
8+
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
9+
10+
logger = logging.getLogger(__name__)
11+
12+
13+
def setup_opentelemetry():
14+
try:
15+
# Get configuration from environment variables
16+
service_name = os.getenv("OTEL_SERVICE_NAME", "guardrails")
17+
service_version = os.getenv("OTEL_SERVICE_VERSION", "1.0.0")
18+
environment = os.getenv("OTEL_ENVIRONMENT", "production")
19+
otlp_endpoint = os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT")
20+
enable_console = os.getenv("OTEL_ENABLE_CONSOLE", "false").lower() == "true"
21+
22+
# Configure resource (metadata about the service)
23+
resource = Resource.create(
24+
{
25+
"service.name": service_name,
26+
"service.version": service_version,
27+
"deployment.environment": environment,
28+
"service.namespace": "nemo-guardrails",
29+
}
30+
)
31+
32+
# Set up the tracer provider
33+
tracer_provider = TracerProvider(resource=resource)
34+
trace.set_tracer_provider(tracer_provider)
35+
36+
exporters_configured = []
37+
38+
# Configure OTLP exporter if endpoint is provided
39+
if otlp_endpoint:
40+
logger.info(f"📝 Configuring OTLP exporter for endpoint: {otlp_endpoint}")
41+
try:
42+
otlp_exporter = OTLPSpanExporter(
43+
endpoint=otlp_endpoint,
44+
insecure=os.getenv("OTEL_EXPORTER_OTLP_INSECURE", "true").lower()
45+
== "true",
46+
)
47+
tracer_provider.add_span_processor(BatchSpanProcessor(otlp_exporter))
48+
exporters_configured.append("OTLP")
49+
logger.info("✅ OTLP exporter configured successfully")
50+
except Exception as e:
51+
logger.error(f"❌ Failed to configure OTLP exporter: {e}")
52+
logger.debug("OTLP exporter error details:", exc_info=True)
53+
54+
# Configure console exporter for debugging
55+
if enable_console:
56+
logger.info("📝 Enabling console exporter for debugging")
57+
try:
58+
console_exporter = ConsoleSpanExporter()
59+
tracer_provider.add_span_processor(BatchSpanProcessor(console_exporter))
60+
exporters_configured.append("Console")
61+
logger.info("✅ Console exporter configured successfully")
62+
except Exception as e:
63+
logger.error(f"❌ Failed to configure console exporter: {e}")
64+
logger.debug("Console exporter error details:", exc_info=True)
65+
66+
if exporters_configured:
67+
logger.info(
68+
f"✅ OpenTelemetry configured with {', '.join(exporters_configured)} exporter(s)"
69+
)
70+
return True
71+
else:
72+
logger.warning("⚠️ No exporters configured. Tracing will not be exported.")
73+
return False
74+
75+
except Exception as e:
76+
logger.error(f"❌ OpenTelemetry setup failed with unexpected error: {e}")
77+
logger.debug("OpenTelemetry setup error details:", exc_info=True)
78+
return False

0 commit comments

Comments
 (0)