Lev Zemlyanov
09/09/2025, 10:37 PMPREFECT_LOGGING_SETTINGS_PATH ennvar is not being respected and not being loaded any idea why? this is in GKE
appuser@nifty-rat-h2z6h-6w6kn:~/workspace$ python - <<'PY'
from prefect.settings import PREFECT_LOGGING_SETTINGS_PATH
from prefect.logging.configuration import load_logging_config
from pathlib import Path
p = Path(PREFECT_LOGGING_SETTINGS_PATH.value() or "")
print("Prefect sees path:", p)
print("Exists:", p.exists())
if p.exists():
cfg = load_logging_config(p)
print("Formatter class for json:",
cfg.get("formatters", {}).get("json", {}).get("()", "<missing>"))
PY
Prefect sees path: /opt/prefect/logging.yml
Exists: False
appuser@nifty-rat-h2z6h-6w6kn:~/workspace$ echo $PREFECT_LOGGING_SETTINGS_PATH
/app/config/logging/gcp.ymlMarvin
09/09/2025, 10:37 PMMarvin
09/09/2025, 10:46 PMlogging.config_path, which maps to the environment variable PREFECT_LOGGING__CONFIG_PATH (note the double underscore for nested settings). The PREFECT_LOGGING_SETTINGS_PATH object you’re printing is the default/internal path used by Prefect’s base images (/opt/prefect/logging.yml) and isn’t the user-facing override.
Why your snippet shows /opt/prefect/logging.yml
- PREFECT_LOGGING_SETTINGS_PATH.value() returns the package default path, not the nested logging setting.
- Your shell has PREFECT_LOGGING_SETTINGS_PATH=/app/config/logging/gcp.yml, but Prefect doesn’t read that to override logging in 3.x.
What to do instead
1) Set the correct env var and make sure the file exists in the container:
- Env var:
export PREFECT_LOGGING__CONFIG_PATH=/app/config/logging/gcp.yml
- Verify in Python:
from prefect.settings import get_current_settings
s = get_current_settings()
print("Prefect config_path:", s.logging.config_path)
- Confirm the file exists:
ls -l /app/config/logging/gcp.yml
2) If you’re on GKE/Kubernetes:
- The env var must be present in the flow-run pod (not just the worker process). Add it to your Kubernetes work pool base job template or deployment’s job variables so it’s injected into the flow-run container.
- Also mount the YAML into the flow-run container (via ConfigMap/volume or bake it into your image) at the same path you set above.
Example snippet for a Kubernetes work pool base job template env entry:
"env": [
{"name": "PREFECT_LOGGING__CONFIG_PATH", "value": "/app/config/logging/gcp.yml"}
]
…and mount your ConfigMap/volume so /app/config/logging/gcp.yml exists.
3) Optional: set via profile instead of env
- In a prefect.toml baked into your image:
[logging]
config_path = "/app/config/logging/gcp.yml"
- Ensure the profile is active in the container (e.g., PREFECT_PROFILE set appropriately).
Quick sanity check you can run now
python - <<'PY'
import os
from pathlib import Path
from prefect.settings import get_current_settings
print("PREFECT_LOGGING__CONFIG_PATH:", os.getenv("PREFECT_LOGGING__CONFIG_PATH"))
s = get_current_settings()
print("settings.logging.config_path:", s.logging.config_path)
p = Path(s.logging.config_path or "")
print("File exists:", p.exists(), "->", p)
PY
Docs for reference:
- Logging customization: Customize logging
- Settings and profiles: Settings and profiles
If you share how you’re injecting env and mounting the file in your GKE setup (work pool template vs deployment job variables), I can suggest the exact configuration snippet.Lev Zemlyanov
09/09/2025, 10:50 PMSpecify a custom path to yourfile using thelogging.ymlsetting.PREFECT_LOGGING_SETTINGS_PATH
Marvin
09/09/2025, 10:51 PMMarvin
09/09/2025, 10:54 PMlogging.config_path (a Path field on LoggingSettings)
- Source: src/prefect/settings/models/logging.py
- The base image default path is /opt/prefect/logging.yml, exposed as DEFAULT_LOGGING_SETTINGS_PATH
- Source: src/prefect/logging/configuration.py
About the environment variable name
- Prefect settings are nested; environment variables target nested fields using a delimiter. In practice, this maps logging.config_path to PREFECT_LOGGING__CONFIG_PATH (double underscore).
- You can verify at runtime:
from prefect.settings import get_current_settings
print(get_current_settings().logging.config_path)
Why PREFECT_LOGGING_SETTINGS_PATH doesn’t work
- PREFECT_LOGGING_SETTINGS_PATH is not the setting used to override the path in 3.x. It’s a default path constant used by the base image (hence why printing it shows /opt/prefect/logging.yml), but it is not the env var that the settings system reads to override logging.
- To override, set PREFECT_LOGGING__CONFIG_PATH=/app/config/logging/gcp.yml and ensure the file exists in the container.
If you can link the docs page you quoted, I’ll open a PR to correct it (or reconcile if there’s a nuance I’m missing). In the meantime, the GitHub sources above reflect the behavior you’re bumping into.Lev Zemlyanov
09/10/2025, 1:13 AMMarvin
09/10/2025, 1:14 AMMarvin
09/10/2025, 1:16 AMversion: 1
formatters:
plain:
format: "%(asctime)s | %(levelname)s | %(name)s - %(message)s"
datefmt: "%Y-%m-%d %H:%M:%S"
class: logging.Formatter
json:
"()": prefect.logging.formatters.JsonFormatter
fmt: default # or 'pretty'
handlers:
console:
class: prefect.logging.handlers.PrefectConsoleHandler
level: INFO
formatter: json # keep JSON for stdout/stderr
api:
"()": prefect.logging.handlers.APILogHandler
level: INFO
formatter: plain # IMPORTANT: plain for the API/UI
loggers:
prefect:
level: INFO
handlers: [console, api]
propagate: False
root:
level: INFO
handlers: [console, api]
Key classes in Prefect you’re touching
- APILogHandler (sends logs to the Prefect API): handlers.py
- JsonFormatter (JSON output): formatters.py
Docs
- Logging customization: Customize logging
If you share your current handler/formatter blocks, I can suggest the exact edits to split “JSON to stdout” from “plain to Prefect API.”Bring your towel and join one of the fastest growing data communities. Welcome to our second-generation open source orchestration platform, a completely rethought approach to dataflow automation.
Powered by