Logging¶
phēnix features a centralized logging system that aggregates logs from the core daemon, internal Go services, and external user applications.
Architecture¶
The logging architecture is designed to be centralized. The phēnix core acts as the aggregator, capturing stderr from all running applications, parsing the output as JSON, and ingesting it into the centralized logging system.
graph TD
subgraph "phēnix core"
Core[phēnix Daemon]
Plog[plog Package]
FileLog[File Logger]
ConsoleLog[Console Logger]
UILog[UI Logger]
Config[Viper Config]
end
subgraph "Go Apps"
GoApp[Go Application]
GoSlog[slog JSON Handler]
end
subgraph "Python Apps"
PyApp[Python Application]
PyLog[Python Logger]
PySink[phēnix Stderr Sink]
end
Config -->|Watches config.yaml| Plog
Core -->|Uses| Plog
Plog -->|Write JSON/Text| FileLog
Plog -->|Write Text| ConsoleLog
Plog -->|Publish| UILog
GoApp -->|Log| GoSlog
GoSlog -->|JSON via Stderr| Core
PyApp -->|Log| PyLog
PyLog -->|Log| PySink
PySink -->|JSON via Stderr| Core
Core -->|ProcessStderrLogs| Plog
CLI Verbosity (--log.level)¶
You can temporarily increase or decrease log verbosity for any command by using the global --log.level flag.
This is useful when troubleshooting because it only affects that command invocation.
Available Levels¶
phēnix supports the following log levels for --log.level:
debug: Most verbose output for troubleshooting.info: Default level. Normal operational messages.warn: Warnings and errors.error: Errors only.none: Suppress all standard log output.
Note
Level names are case-insensitive (for example, DEBUG and debug are equivalent).
Examples¶
Use higher verbosity to inspect behavior while running a command:
# Run the UI with debug logging for this invocation
phenix ui --log.level=debug
# Show only warnings and errors while listing experiments
phenix exp list --log.level=warn
# Keep command output quiet unless an error occurs
phenix config get --log.level=error Role/vm-admin
To change the default level for all future commands, use settings:
To revert and use the configured default again for subsequent commands:
The App Contract¶
All applications (Go or Python) running under phēnix must adhere to the following contract to ensure their logs are correctly parsed and displayed in the UI:
- Output: Logs must be written to
stderr. - Format: Logs must be single-line JSON objects.
- Required Fields:
level:DEBUG,INFO,WARN,ERRORmsg: The log message string.time: Timestamp (RFC3339 or similar).
- Optional Fields:
traceback: For exceptions/panics (string).
Tip
Check out the Example Applications for complete, runnable reference implementations in Go and Python.
Python Apps¶
Use the phenix_apps.common.logger. It is pre-configured to output JSON to stderr.
Important
For fatal errors, raise an exception (e.g., ValueError, RuntimeError) instead of calling sys.exit(1). The AppBase class wraps execution in a try/except block and will automatically catch the exception, log the traceback as structured JSON, and exit cleanly.
from phenix_apps.common.logger import logger
def my_func():
try:
logger.bind(custom_field="value").info("Starting operation")
# ... code ...
except Exception:
# Automatically captures traceback and formats as JSON
logger.exception("Operation failed")
Go Apps¶
Use log/slog with a JSON handler.
import (
"log/slog"
"os"
)
func main() {
logger := slog.New(slog.NewJSONHandler(os.Stderr, nil))
slog.SetDefault(logger)
slog.Info("Application started", "app", "my-app")
}
phēnix Core¶
Use the phenix/util/plog package for logging within the core application.
import "phenix/util/plog"
func MyFunc() {
// Always provide a LogType enum for UI filtering
plog.Info(plog.TypeSystem, "System initialized", "version", "1.0")
}
HTTP Request Logging¶
To view detailed HTTP request logs (method, path, status, duration), start the UI with the --log-requests flag.
Troubleshooting
For common logging issues and solutions, please see the Troubleshooting page.