Conversation
| from scaler.utility.exceptions import ClientCancelledException, ClientQuitException, ClientShutdownException | ||
| from scaler.utility.identifiers import ClientID | ||
|
|
||
| logger = logging.getLogger(__name__) |
There was a problem hiding this comment.
__name__ will varies based on different name, are you sure they will use same named logger "scaler" every time?
I think better solution to getLogger each time is define the logger as module variable in utility, then import it
e.g.:
from scaler.utility.logging.logger import logger
logger.info()There was a problem hiding this comment.
I think __name__ is the name of the current module, so logging calls from processor.py will use the name processor for example
There was a problem hiding this comment.
@magniloquency is right. We want to print out components' name:
2026-04-20 09:13:34+0800 INFO scheduler[2340581]: VanillaInformationController: exited
2026-04-20 09:13:34+0800 INFO object_storage_server[2340577]: ObjectStorageServer: stopped by userThere was a problem hiding this comment.
This to be honest, I would like that logger to have some process_name passing to setup_logger, to show it's scheduler or object_storage_server, like
setup_logger(process_name="scheduler", logging_level=...)all files that have logger = logging.getLogger(__name__) is not very elegant
There was a problem hiding this comment.
- The existing implementation follows what official document recommends.
setup_loggeris called for each process already and it must be called only once. This, andgetLoggerare orthogonal.
Change log output from `[INFO]2026-04-08 09:58:52-0400: ...` to `2026-04-08 09:58:52-0400 INFO scheduler[23451]: ...` so operators can identify which subprocess (scheduler / worker_manager / object_storage_server / gui) emitted each line via the `<process_name>[<pid>]` prefix. Python side: `setup_logger` now takes `process_name` and bakes it into the formatter; all 6 CLI entry points pass their component name. C++ side: `scaler::ymq::Logger` gains a `name` constructor arg and supports `%(name)s` / `%(process)d` tokens so in-house C++ daemons (ymq, object_storage) emit the same format. Signed-off-by: gxu <georgexu420@163.com>
Library code should not reconfigure the root logger — host applications
(or third-party SDKs such as ORB) may configure root independently and
would silently override or suppress scaler output.
Key changes:
- `scaler/__init__.py` attaches a `NullHandler` to the "scaler" logger so
library imports (e.g. `from scaler import Client`) don't emit "no handler"
warnings or touch root.
- `setup_logger` now configures the "scaler" logger with `propagate=False`
(instead of root). Daemon entry points still get consistent formatting;
submodule loggers inherit via the `scaler.*` namespace.
- Every module uses `logger = logging.getLogger(__name__)` and emits through
that logger. `logging.<method>()` module-level calls were all migrated.
- `get_logger_info(logging.getLogger("scaler"))` reads scaler's effective
format/level/paths for the C++ object storage server.
- Removed the ORB "setup_logger after __aenter__" workaround: ORB can no
longer clobber scaler's logging now that we no longer share the root
logger.
Signed-off-by: gxu <georgexu420@163.com>
READY FOR REVIEW.
<time> <level> <process_name>[<pid>]: <msg>across Python and C++ (Better logging #691) — makes it easy to tell which subprocess emitted which line underscaler_all.scalerlogger withpropagate=False+NullHandler(Scaler log output can be silently suppressed by third-party libraries that reconfigure the root logger #653) — third-party code (e.g. ORB) can no longer suppress scaler output.LOGGING MIGRATION GUIDE FOR PRIVATE WORKER MANAGERS (FOR HUMAN):
loggingis no longer being used, please use a named logger instead. Consult orb worker manager for the usage.logger = logging.getLogger(f"scaler.external.{__name__}")— otherwise your logs will silently go nowhere.HUMAN SHOULD STOP READING HERE
LOGGING MIGRATION GUIDE FOR PRIVATE WORKER MANAGERS (FOR AI):
Context
Two recent changes in
opengris-scaler(PRs #691 and #653) affect everyworker-manager adapter that logs output. Internal / out-of-repo adapters
must be updated to match, or their log output will either (a) not appear,
or (b) drift from the unified scaler format.
What changed upstream
Unified log format (Better logging #691) — all scaler processes emit:
<timestamp> <level> <process_name>[<pid>]: <message>The
<process_name>is set bysetup_logger(..., process_name=...),called once in
scaler.entry_points.scaler._run_worker_managerbeforeyour adapter's
run()executes. You do NOT callsetup_loggeryourself.Named loggers, off the root logger (Scaler log output can be silently suppressed by third-party libraries that reconfigure the root logger #653) — scaler no longer
configures the root logger. It configures the named logger
"scaler"with
propagate=False. Any logger whose dotted name starts withscaler.inherits scaler's handlers and format; anything outside thattree does not.
ORB workaround removed. Calls like:
setup_logger(self._logging_paths, self._logging_config_file, self._logging_level)
inside
__aenter__(or anywhere inside an adapter) are now dead. Thereason the workaround existed — third-party SDKs mutating root after
scaler configured it — is no longer relevant because scaler no longer
uses root.
Required changes for an internal worker-manager adapter
Step 1 — Add a module-level named logger
At the top of every
.pyfile in the adapter that currently useslogging.<method>(...)module-level calls, add:The
scaler.external.prefix places the logger under thescalertreeso it inherits scaler's handlers, format, and level automatically. If
your adapter is already under the
scaler.namespace (unlikely forout-of-repo code), use
logging.getLogger(__name__)directly.Step 2 — Replace module-level logging calls
Mechanical substitution across every
.pyin the adapter:Leave
import logging— it's still needed for thelogging.getLoggercall and any
logging.INFO-level constants.Step 3 — Remove dead logging-setup code
Delete the following patterns wherever they appear in the adapter:
Step 4 — Do not call
setup_loggerfrom the adapter_run_worker_managerinscaler.entry_points.scalercallssetup_logger(..., process_name=config._tag)as the first statement ofthe subprocess. Adapters MUST NOT call it again — doing so resets the
format with the wrong
process_name.Step 5 — Verify
Run the adapter and confirm:
<time> <level> <process_name>[<pid>]: <message>with
<process_name>equal toconfig._tag.logging.basicConfig(...)from withinthe subprocess does NOT change scaler's log output.
Verification checklist
.pyin the adapter haslogger = logging.getLogger("scaler.external." + __name__)(or equivalent scaler-prefixed name).grep -rn 'logging\.\(info\|warning\|error\|exception\|debug\)(' <adapter>returns zero matches.setup_loggercall remains in adapter code.self._logging_paths/_logging_level/_logging_config_filefield storage in adapter classes.scaler_allproduces log lines whose process-name prefix matches the configured_tag.What NOT to change
logging.INFO,logging.WARNING, etc. constants — only the method calls.loggervariable — stick to this convention for grep-ability.scalerlogger already has them; propagation handles the rest.
logger.propagate = Falseon the adapter's logger. You wantit to propagate up to the
scalerparent logger.