Skip to content

[TEST] feat: add MLflow tracing integration via OpenTelemetry bridge#330

Draft
IlonaShishov wants to merge 5 commits into
RHEcosystemAppEng:mainfrom
IlonaShishov:worktree-mlflow
Draft

[TEST] feat: add MLflow tracing integration via OpenTelemetry bridge#330
IlonaShishov wants to merge 5 commits into
RHEcosystemAppEng:mainfrom
IlonaShishov:worktree-mlflow

Conversation

@IlonaShishov

Copy link
Copy Markdown
Collaborator

Summary

  • Adds MLflow tracing integration via OTel bridge — ADK's native OTel traces are exported to MLflow's OTLP endpoint (/v1/traces)
  • MLflow operates independently of the existing OTel tracing (MLFLOW_ENABLED works without OTEL_ENABLED)
  • Includes OpenShift Helm templates for self-hosted MLflow Tracking Server with dedicated PostgreSQL backend
  • Cloud Run deployment connects to an external MLflow instance (no new service deployed)

Changes

  • config/settings.py — 6 new Pydantic settings (MLFLOW_ENABLED, MLFLOW_TRACKING_URI, etc.)
  • telemetry/setup.py_add_mlflow_processor() adds a second BatchSpanProcessor for MLflow
  • OpenShift Helm: MLflow Deployment, PostgreSQL, PVCs, Service, Route, NetworkPolicy
  • Cloud Run: env vars in service.yaml
  • Tests: 529 lines, 12 test classes covering all settings, headers, and edge cases

Test plan

  • python -m pytest tests/test_mlflow.py -v — unit tests pass
  • Deploy to OpenShift dev namespace with MLflow enabled
  • Verify traces arrive in MLflow UI
  • Verify span attributes (prompts, responses, tool calls) are queryable

🤖 Generated with Claude Code

luis5tb and others added 5 commits July 15, 2026 12:50
Add MLflow LLM observability support. Google ADK natively generates
OTel traces; MLflow (>= 3.6.0) accepts them at its /v1/traces OTLP
endpoint. The agent adds a second BatchSpanProcessor targeting MLflow
alongside existing exporters.

- config/settings.py: 6 new MLflow settings (enabled, tracking_uri,
  experiment_name, experiment_id, log_prompts, run_tags)
- telemetry/setup.py: _add_mlflow_processor() sends all settings as
  OTLP headers; setup_telemetry() restructured so MLflow works
  independently of otel_enabled
- pyproject.toml: mlflow optional dep group (otlp-proto-http exporter)
- requirements-mlflow.txt: lock file with hashes
- .env.example, Makefile: env var docs + lock-mlflow target
- tests/test_mlflow.py: 26 test cases covering defaults, env loading,
  enabled/disabled paths, independent MLflow, headers, trailing slash
  handling, and ImportError

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On Cloud Run the agent connects to an external MLflow instance (Red Hat
infrastructure) — no new GCP services deployed.

- service.yaml: MLFLOW_ENABLED, MLFLOW_TRACKING_URI, MLFLOW_EXPERIMENT_NAME,
  MLFLOW_EXPERIMENT_ID, MLFLOW_LOG_PROMPTS, MLFLOW_RUN_TAGS env vars
- README.md: MLflow Tracing section with configuration table, enabling
  instructions, networking/auth notes, and dependency info

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deploy MLflow Tracking Server as an optional Helm component with
dedicated PostgreSQL, artifact PVC, NetworkPolicy, and optional Route.

New templates:
- mlflow-deployment.yaml: MLflow server with security contexts,
  readiness probe (/api/2.0/mlflow/experiments/search), liveness
  probe (tcpSocket), artifact PVC + tmp emptyDir mounts
- mlflow-service.yaml: ClusterIP service
- mlflow-route.yaml: optional OpenShift Route
- mlflow-pvc.yaml: artifact storage (10Gi default)
- mlflow-postgresql-deployment.yaml: dedicated PostgreSQL + Service
- mlflow-postgresql-pvc.yaml: PostgreSQL data (5Gi default)
- networkpolicy-mlflow.yaml: restricts ingress to agent pods only

Modified:
- _helpers.tpl: MLflow + PostgreSQL service name and selector helpers
- configmap.yaml: MLflow env vars with auto-resolved trackingUri
  pointing to the ClusterIP Service
- secret.yaml: MLFLOW_DB_PASSWORD for dedicated PostgreSQL
- values.yaml: mlflow section with pinned image (v3.14.0), resource
  defaults, storage, route, auth, and postgresql config
- README.md: MLflow Tracking section with value table and usage docs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add Helm fail guard when mlflow.postgresql.mode != 'dedicated' to
  prevent silent OTLP trace ingestion failure (file-based backends
  silently drop traces per MLflow docs)
- Replace incorrect mlflow-tracing package references in Cloud Run and
  OpenShift READMEs with the actual dependency
  (opentelemetry-exporter-otlp-proto-http, already in the container)
- Document that MLFLOW_EXPERIMENT_ID requires the experiment to already
  exist on the server (use MLFLOW_EXPERIMENT_NAME for auto-creation)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add _resolve_mlflow_experiment_id() to create-or-get experiment by name
  via MLflow REST API, so OTLP traces include the required x-mlflow-experiment-id
  header without needing a pre-existing experiment ID
- Fall back to Default experiment (ID 0) when neither name nor ID is configured
- Add --allowed-hosts and --cors-allowed-origins to MLflow deployment to fix
  403 on /ajax-api/* routes and DNS rebinding rejection
- Update values.yaml comments for experimentName/experimentId clarity
- Use v3.14.0-full image tag (includes psycopg2-binary for PostgreSQL)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants