- Python 95.9%
- Nix 2.3%
- Dockerfile 1.8%
| .forgejo/workflows | ||
| .dockerignore | ||
| .gitignore | ||
| Dockerfile | ||
| flake.nix | ||
| LICENSE | ||
| mlflow_prometheus_exporter.py | ||
| pyproject.toml | ||
| README.md | ||
| requirements.txt | ||
MLflow Prometheus Exporter
A simple Python server that emulates the MLflow REST API and exposes MLflow metrics and projects as Prometheus metrics for scraping and visualization in Grafana.
Features
- MLflow REST API Emulation: Provides a subset of MLflow REST API endpoints for experiments, runs, metrics, and projects
- Prometheus Metrics Export: Exposes MLflow data as Prometheus metrics at
/metrics - Dual Mode Operation:
- Standalone Mode: Uses in-memory storage for testing and development
- Proxy Mode: Connects to a real MLflow server and exports its metrics
- Periodic Updates: Automatically refreshes Prometheus metrics at configurable intervals
Quick Start
Prerequisites
- Python 3.7+
- pip
Installation
# Clone and navigate to the project
cd mlprom
# Install dependencies
pip install -r requirements.txt
Running in Standalone Mode (Testing)
python mlflow_prometheus_exporter.py --port 8000
This starts the server with in-memory storage. You can create experiments, runs, and log metrics via the API.
Running in Proxy Mode (Production)
python mlflow_prometheus_exporter.py \
--mlflow-url http://your-mlflow-server:5000 \
--port 8000 \
--update-interval 30
This connects to your existing MLflow server and exports its metrics.
Usage
API Endpoints
MLflow REST API (Compatibility Layer)
GET /api/2.0/mlflow/experiments/list- List all experimentsGET /api/2.0/mlflow/experiments/get?experiment_id={id}- Get specific experimentPOST /api/2.0/mlflow/experiments/create- Create experiment (body:{name, artifact_location?, tags?})POST /api/2.0/mlflow/experiments/search- Search experiments (body:{filter?, view_type?, max_results?, page_token?})GET /api/2.0/mlflow/runs/list- List all runsGET /api/2.0/mlflow/runs/get- Get specific run (query:run_idorrun_uuid)POST /api/2.0/mlflow/runs/create- Create run (body:{experiment_id, run_name?, user_id?, start_time?, tags?})POST /api/2.0/mlflow/runs/update- Update run status (body:{run_id, status?, end_time?, run_name?})POST /api/2.0/mlflow/runs/search- Search runs (body:{experiment_ids?, filter?, run_view_type?, max_results?, order_by?, page_token?})POST /api/2.0/mlflow/runs/log-metric- Log metric (body:{run_id, key, value, timestamp?, step?})POST /api/2.0/mlflow/runs/log-parameter- Log parameter (body:{run_id, key, value})POST /api/2.0/mlflow/runs/log-batch- Log batch (body:{run_id, metrics?, params?, tags?})GET /api/2.0/mlflow/metrics/get?run_id={id}- Get metrics for runGET /api/2.0/mlflow/projects/list- List all projectsGET /api/2.0/mlflow/projects/get?project_id={id}- Get specific projectPOST /api/2.0/mlflow/projects/create- Create project (body:{name, source?})
Prometheus Metrics
GET /metrics- All Prometheus metrics in text format
Health Check
GET /health- Health check endpoint
Prometheus Configuration
Add the following to your prometheus.yml:
scrape_configs:
- job_name: 'mlflow-exporter'
static_configs:
- targets: ['localhost:8000']
scrape_interval: 30s
Grafana Visualization
Import a dashboard or create panels using these metrics:
Metric Types
-
Gauge: mlflow_metric_value - Current value of MLflow metrics
- Labels:
experiment_id,run_id,metric_name
- Labels:
-
Gauge: mlflow_metric_timestamp - Timestamp of the metric
- Labels:
experiment_id,run_id,metric_name
- Labels:
-
Gauge: mlflow_metric_step - Step number of the metric
- Labels:
experiment_id,run_id,metric_name
- Labels:
-
Gauge: mlflow_param_value - Parameter values (numeric params stored directly, string params hashed)
- Labels:
experiment_id,run_id,param_name
- Labels:
-
Gauge: mlflow_run_status - Run status as numeric (1=RUNNING, 2=SCHEDULED, 3=FINISHED, 4=FAILED)
- Labels:
experiment_id,run_id,run_name,status
- Labels:
-
Gauge: mlflow_run_start_time - Run start time (Unix timestamp)
- Labels:
experiment_id,run_id,run_name
- Labels:
-
Gauge: mlflow_run_end_time - Run end time (Unix timestamp)
- Labels:
experiment_id,run_id,run_name
- Labels:
-
Gauge: mlflow_experiment_info - Experiment metadata (always 1)
- Labels:
experiment_id,experiment_name,artifact_location
- Labels:
-
Gauge: mlflow_project_info - Project metadata (always 1)
- Labels:
project_name,project_id
- Labels:
-
Counter: mlflow_exporter_requests_total - Total API requests
- Labels:
endpoint,method,status_code
- Labels:
-
Summary: mlflow_exporter_request_duration_seconds - Request duration
- Labels:
endpoint,method
- Labels:
-
Counter: mlflow_exporter_api_errors_total - API error count
- Labels:
api_endpoint,error_type
- Labels:
Example Usage
Create an Experiment and Run (Standalone Mode)
# Create an experiment
curl -X POST "http://localhost:8000/api/2.0/mlflow/experiments/create?name=my-experiment"
# Create a run
curl -X POST "http://localhost:8000/api/2.0/mlflow/runs/create?experiment_id=0&run_name=test-run-1"
# Log a metric
curl -X POST "http://localhost:8000/api/2.0/mlflow/metrics/log?run_id=0&key=accuracy&value=0.95"
# Update run status
curl -X POST "http://localhost:8000/api/2.0/mlflow/runs/update?run_id=0&status=FINISHED"
# Check Prometheus metrics
curl http://localhost:8000/metrics
Query Prometheus Metrics
# Get all mlflow metrics
curl http://localhost:8000/metrics | grep mlflow
# Query specific metric (via Prometheus)
# HELP mlflow_metric_value MLflow metric value
# TYPE mlflow_metric_value gauge
mlflow_metric_value{experiment_id="0",metric_name="accuracy",run_id="0"} 0.95
Command Line Options
--mlflow-url URL URL of the MLflow server to connect to (optional)
--port PORT Port to serve the exporter on (default: 8000)
--host HOST Host to bind to (default: 0.0.0.0)
--update-interval SEC Interval in seconds for periodic metrics updates (default: 60)
--log-level LEVEL Logging level: DEBUG, INFO, WARNING, ERROR, CRITICAL (default: INFO)
Project Structure
mlprom/
├── mlflow_prometheus_exporter.py # Main server application
├── requirements.txt # Python dependencies
├── Dockerfile # Docker/Podman container
├── .dockerignore # Docker ignore rules
└── README.md # This file
Development
# Install development dependencies
pip install -r requirements.txt
# Run the server
python mlflow_prometheus_exporter.py --log-level DEBUG
# Run tests (if available)
python -m pytest
Docker / Podman Container
Build the Image
# Using Podman
podman build -t mlflow-prometheus-exporter .
# Using Docker
docker build -t mlflow-prometheus-exporter .
Run the Container
# Using Podman (standalone mode)
podman run -p 8000:8000 mlflow-prometheus-exporter
# Using Podman (proxy mode - connect to real MLflow server)
podman run -p 8000:8000 -e MLFLOW_URL=http://host.docker.internal:5000 mlflow-prometheus-exporter
# Using Docker (standalone mode)
docker run -p 8000:8000 mlflow-prometheus-exporter
# Using Docker (proxy mode)
docker run -p 8000:8000 -e MLFLOW_URL=http://host.docker.internal:5000 mlflow-prometheus-exporter
Environment Variables
| Variable | Description | Default |
|---|---|---|
MLFLOW_URL |
URL of the MLflow server to connect to (proxy mode) | None (standalone mode) |
PORT |
Port to serve the exporter on | 8000 |
HOST |
Host to bind to | 0.0.0.0 |
UPDATE_INTERVAL |
Interval in seconds for periodic metrics updates | 60 |
LOG_LEVEL |
Logging level: DEBUG, INFO, WARNING, ERROR, CRITICAL | INFO |
License
ISC License
Copyright (c) 2026, Damien
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.