Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix duplicate logs in run_simulation #3354

Merged
merged 17 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/py/flwr/common/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,29 @@ def warn_deprecated_feature(name: str) -> None:
""",
name,
)


def set_logger_propagation(
child_logger: logging.Logger, value: bool = True
) -> logging.Logger:
"""Set the logger propagation attribute.

Parameters
----------
child_logger : logging.Logger
Child logger object
value : bool
Boolean setting for propagation. If True, both parent and child logger
display messages. Otherwise, only the child logger displays a message.
This False setting prevents duplicate logs in Colab notebooks.
Reference: https://stackoverflow.com/a/19561320

Returns
-------
logging.Logger
Child logger object with updated propagation setting
"""
child_logger.propagate = value
if not child_logger.propagate:
child_logger.log(logging.DEBUG, "Logger propagate set to False")
return child_logger
17 changes: 16 additions & 1 deletion src/py/flwr/simulation/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
"""Flower simulation app."""


import asyncio
import logging
import sys
import threading
import traceback
Expand All @@ -27,7 +29,7 @@

from flwr.client import ClientFn
from flwr.common import EventType, event
from flwr.common.logger import log
from flwr.common.logger import log, set_logger_propagation
from flwr.server.client_manager import ClientManager
from flwr.server.history import History
from flwr.server.server import Server, init_defaults, run_fl
Expand Down Expand Up @@ -156,6 +158,7 @@ def start_simulation(
is an advanced feature. For all details, please refer to the Ray documentation:
https://docs.ray.io/en/latest/ray-core/scheduling/index.html


Returns
-------
hist : flwr.server.history.History
Expand All @@ -167,6 +170,18 @@ def start_simulation(
{"num_clients": len(clients_ids) if clients_ids is not None else num_clients},
)

# Set logger propagation
loop: Optional[asyncio.AbstractEventLoop] = None
try:
loop = asyncio.get_running_loop()
except RuntimeError:
loop = None
finally:
if loop and loop.is_running():
# Set logger propagation to False to prevent duplicated log output in Colab.
logger = logging.getLogger("flwr")
_ = set_logger_propagation(logger, False)

# Initialize server and server config
initialized_server, initialized_config = init_defaults(
server=server,
Expand Down
3 changes: 3 additions & 0 deletions src/py/flwr/simulation/run_simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

from flwr.client import ClientApp
from flwr.common import EventType, event, log
from flwr.common.logger import set_logger_propagation
from flwr.common.typing import ConfigsRecordValues
from flwr.server.driver import Driver, GrpcDriver
from flwr.server.run_serverapp import run
Expand Down Expand Up @@ -364,6 +365,8 @@ def _run_simulation(

finally:
if run_in_thread:
# Set logger propagation to False to prevent duplicated log output in Colab.
logger = set_logger_propagation(logger, False)
log(DEBUG, "Starting Simulation Engine on a new thread.")
simulation_engine_th = threading.Thread(target=_main_loop, args=args)
simulation_engine_th.start()
Expand Down