Repository: evidentlyai/evidently
Issue: Database Connection Failures Due to Password Masking in Migration
Root cause: Algorithmic Error

Evidently fails to connect to databases during migration because the password is masked as `***` in the database URL, resulting in authentication errors.

**Environment**
- Affected file: `src/evidently/ui/service/storage/sql/utils.py`
- Function: `create_engine_and_migrate()`
- Impact: All database types (PostgreSQL, MySQL, etc.)

Database connections fail during the migration step with authentication errors because the password in the connection string is replaced with `***`. Line 26 currently uses `str(engine.url)`, which masks the password value as `***`. This causes the migration to attempt connection with a literal `***` password, resulting in authentication failures.

**Proposed Solution**
Change line 26 from:
```python
migrate_database(str(engine.url))
```

To:
```python
migrate_database(engine.url.render_as_string(hide_password=False))
```

@adrianAzoitei

## Reproducing example
### Simple postgres database
```yaml
# docker-compose.yaml
services:
  postgres:
    image: postgres:16-alpine
    container_name: evidently-postgres
    environment:
      POSTGRES_DB: evidently
      POSTGRES_USER: evidently_user
      POSTGRES_PASSWORD: evidently_password
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U evidently_user -d evidently"]
      interval: 5s
      timeout: 5s
      retries: 5
```

```yaml
# config.yaml
storage:
  type: sql

database:
  url: postgresql://evidently_user:evidently_password@localhost:5432/evidently
```

```txt
# requirements.txt
psycopg[binary]
s3fs
sniffio
evidently[sql]==0.7.17
```

### Error stack trace
**NOTE:** Actually load the web page to trigger the migration function once the uvicorn server is listening.
```
evidently ui --conf-path config.yaml \
  --port 8080 \
  --host 0.0.0.0

INFO:     Started server process [53092]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
INFO:     127.0.0.1:58715 - "GET / HTTP/1.1" 200 OK
INFO:     127.0.0.1:58715 - "GET /api/version HTTP/1.1" 200 OK
INFO - 2025-12-16 15:28:14,458 - evidently.ui.service.storage.sql.utils - utils - Running database migrations...
ERROR - 2025-12-16 15:28:14,506 - evidently.ui.service.storage.sql.utils - utils - Migration error: (psycopg2.OperationalError) connection to server at "localhost" (::1), port 5432 failed: FATAL:  password authentication failed for user "evidently_user"

(Background on this error at: https://sqlalche.me/e/20/e3q8)
Traceback (most recent call last):
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 143, in __init__
    self._dbapi_connection = engine.raw_connection()
                             ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 3309, in raw_connection
    return self.pool.connect()
           ^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/base.py", line 447, in connect
    return _ConnectionFairy._checkout(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/base.py", line 1264, in _checkout
    fairy = _ConnectionRecord.checkout(pool)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/base.py", line 711, in checkout
    rec = pool._do_get()
          ^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/impl.py", line 177, in _do_get
    with util.safe_reraise():
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__
    raise exc_value.with_traceback(exc_tb)
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/impl.py", line 175, in _do_get
    return self._create_connection()
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/base.py", line 388, in _create_connection
    return _ConnectionRecord(self)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/base.py", line 673, in __init__
    self.__connect()
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/base.py", line 899, in __connect
    with util.safe_reraise():
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__
    raise exc_value.with_traceback(exc_tb)
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/base.py", line 895, in __connect
    self.dbapi_connection = connection = pool._invoke_creator(self)
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/engine/create.py", line 661, in connect
    return dialect.connect(*cargs, **cparams)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/engine/default.py", line 630, in connect
    return self.loaded_dbapi.connect(*cargs, **cparams)  # type: ignore[no-any-return]  # NOQA: E501
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/psycopg2/__init__.py", line 122, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
psycopg2.OperationalError: connection to server at "localhost" (::1), port 5432 failed: FATAL:  password authentication failed for user "evidently_user"


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/evidently/ui/service/storage/sql/utils.py", line 26, in create_engine_and_migrate
    migrate_database(str(engine.url))
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/evidently/ui/service/storage/sql/utils.py", line 89, in migrate_database
    run_migrations(database_url=database_url, revision=revision)
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/evidently/ui/service/storage/sql/utils.py", line 138, in run_migrations
    command.upgrade(config, revision)
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/alembic/command.py", line 483, in upgrade
    script.run_env()
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/alembic/script/base.py", line 545, in run_env
    util.load_python_file(self.dir, "env.py")
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/alembic/util/pyfiles.py", line 116, in load_python_file
    module = load_module_py(module_id, path)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/alembic/util/pyfiles.py", line 136, in load_module_py
    spec.loader.exec_module(module)  # type: ignore
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/evidently/ui/service/storage/sql/migrations/env.py", line 129, in <module>
    run_migrations_online()
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/evidently/ui/service/storage/sql/migrations/env.py", line 116, in run_migrations_online
    with connectable.connect() as connection:
         ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 3285, in connect
    return self._connection_cls(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 145, in __init__
    Connection._handle_dbapi_exception_noconnection(
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 2448, in _handle_dbapi_exception_noconnection
    raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 143, in __init__
    self._dbapi_connection = engine.raw_connection()
                             ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 3309, in raw_connection
    return self.pool.connect()
           ^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/base.py", line 447, in connect
    return _ConnectionFairy._checkout(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/base.py", line 1264, in _checkout
    fairy = _ConnectionRecord.checkout(pool)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/base.py", line 711, in checkout
    rec = pool._do_get()
          ^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/impl.py", line 177, in _do_get
    with util.safe_reraise():
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__
    raise exc_value.with_traceback(exc_tb)
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/impl.py", line 175, in _do_get
    return self._create_connection()
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/base.py", line 388, in _create_connection
    return _ConnectionRecord(self)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/base.py", line 673, in __init__
    self.__connect()
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/base.py", line 899, in __connect
    with util.safe_reraise():
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__
    raise exc_value.with_traceback(exc_tb)
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/pool/base.py", line 895, in __connect
    self.dbapi_connection = connection = pool._invoke_creator(self)
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/engine/create.py", line 661, in connect
    return dialect.connect(*cargs, **cparams)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/sqlalchemy/engine/default.py", line 630, in connect
    return self.loaded_dbapi.connect(*cargs, **cparams)  # type: ignore[no-any-return]  # NOQA: E501
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adrian.azoitei/dev/model-monitoring-webserver/.venv/lib/python3.11/site-packages/psycopg2/__init__.py", line 122, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) connection to server at "localhost" (::1), port 5432 failed: FATAL:  password authentication failed for user "evidently_user"

(Background on this error at: https://sqlalche.me/e/20/e3q8)
```

Can confirm @jasperbruin 's proposed change fixes this.