From d8a7255f12fc35e397ec81ec249f0d0fd72837cd Mon Sep 17 00:00:00 2001 From: ali Date: Fri, 5 Sep 2025 18:03:47 +0300 Subject: [PATCH 1/2] lsp silent logs --- codeflash/cli_cmds/cli.py | 2 +- codeflash/cli_cmds/console.py | 7 +++++++ codeflash/lsp/helpers.py | 8 ++++++++ codeflash/lsp/server_entry.py | 6 ++---- codeflash/optimization/function_optimizer.py | 10 ++++++---- 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/codeflash/cli_cmds/cli.py b/codeflash/cli_cmds/cli.py index 3f8f8767a..f95403c6b 100644 --- a/codeflash/cli_cmds/cli.py +++ b/codeflash/cli_cmds/cli.py @@ -111,7 +111,7 @@ def process_and_validate_cmd_args(args: Namespace) -> Namespace: from codeflash.code_utils.github_utils import require_github_app_or_exit is_init: bool = args.command.startswith("init") if args.command else False - if args.verbose: + if args.verbose or is_LSP_enabled(): logging_config.set_level(logging.DEBUG, echo_setting=not is_init) else: logging_config.set_level(logging.INFO, echo_setting=not is_init) diff --git a/codeflash/cli_cmds/console.py b/codeflash/cli_cmds/console.py index ca8e29e26..2d55cdc41 100644 --- a/codeflash/cli_cmds/console.py +++ b/codeflash/cli_cmds/console.py @@ -20,6 +20,7 @@ from codeflash.cli_cmds.console_constants import SPINNER_TYPES from codeflash.cli_cmds.logging_config import BARE_LOGGING_FORMAT +from codeflash.lsp.helpers import lsp_log if TYPE_CHECKING: from collections.abc import Generator @@ -42,6 +43,12 @@ logger = logging.getLogger("rich") logging.getLogger("parso").setLevel(logging.WARNING) +real_info_log_fn = logger.info +logger.info = lambda msg, *args, **kwargs: lsp_log(msg, real_info_log_fn, *args, **kwargs) + +real_debug_log_fn = logger.debug +logger.debug = lambda msg, *args, **kwargs: lsp_log(msg, real_debug_log_fn, *args, **kwargs) + def paneled_text( text: str, panel_args: dict[str, str | bool] | None = None, text_args: dict[str, str] | None = None diff --git a/codeflash/lsp/helpers.py b/codeflash/lsp/helpers.py index dc8f8c5d6..db7aee34e 100644 --- a/codeflash/lsp/helpers.py +++ b/codeflash/lsp/helpers.py @@ -1,7 +1,15 @@ import os from functools import lru_cache +from typing import Any, Callable @lru_cache(maxsize=1) def is_LSP_enabled() -> bool: return os.getenv("CODEFLASH_LSP", default="false").lower() == "true" + + +def lsp_log(msg: str, actual_log_fn: Callable[[str, Any, Any], None], *args: Any, **kwargs: Any) -> None: # noqa: ANN401 + if is_LSP_enabled(): + actual_log_fn(f"::::{msg}", *args, **kwargs) + else: + actual_log_fn(msg, *args, **kwargs) diff --git a/codeflash/lsp/server_entry.py b/codeflash/lsp/server_entry.py index 5ea30cde8..a905ab0b8 100644 --- a/codeflash/lsp/server_entry.py +++ b/codeflash/lsp/server_entry.py @@ -16,17 +16,15 @@ # Configure logging to stderr for VS Code output channel def setup_logging() -> logging.Logger: # Clear any existing handlers to prevent conflicts - root_logger = logging.getLogger() + root_logger = logging.getLogger("rich") root_logger.handlers.clear() # Set up stderr handler for VS Code output channel with [LSP-Server] prefix handler = logging.StreamHandler(sys.stderr) - # adding the :::: here for the client to easily extract the message from the log - handler.setFormatter(logging.Formatter("[LSP-Server] %(asctime)s [%(levelname)s]::::%(message)s")) + handler.setLevel(logging.DEBUG) # Configure root logger root_logger.addHandler(handler) - root_logger.setLevel(logging.INFO) # Also configure the pygls logger specifically pygls_logger = logging.getLogger("pygls") diff --git a/codeflash/optimization/function_optimizer.py b/codeflash/optimization/function_optimizer.py index c523dcbce..3fbf6463c 100644 --- a/codeflash/optimization/function_optimizer.py +++ b/codeflash/optimization/function_optimizer.py @@ -169,10 +169,12 @@ def _process_refinement_results(self) -> OptimizedCandidate | None: for candidate in refinement_response: self.candidate_queue.put(candidate) - self.candidate_len += len(refinement_response) - logger.info( - f"Added {len(refinement_response)} candidates from refinement, total candidates now: {self.candidate_len}" - ) + if len(refinement_response) > 0: + self.candidate_len += len(refinement_response) + logger.info( + f"Added {len(refinement_response)} candidates from refinement, total candidates now: {self.candidate_len}" + ) + self.refinement_done = True return self.get_next_candidate() From 9f8b1004f2c5b64f84e38cc51b720da90e5468fe Mon Sep 17 00:00:00 2001 From: ali Date: Sat, 6 Sep 2025 05:09:53 +0300 Subject: [PATCH 2/2] override other log methods and log serialized lsp messages --- codeflash/cli_cmds/console.py | 29 ++++++++++++++++++++--------- codeflash/lsp/helpers.py | 20 ++++++++++++++++---- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/codeflash/cli_cmds/console.py b/codeflash/cli_cmds/console.py index 2d55cdc41..61877971f 100644 --- a/codeflash/cli_cmds/console.py +++ b/codeflash/cli_cmds/console.py @@ -1,10 +1,10 @@ from __future__ import annotations +import json import logging -import os from contextlib import contextmanager from itertools import cycle -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any from rich.console import Console from rich.logging import RichHandler @@ -20,7 +20,7 @@ from codeflash.cli_cmds.console_constants import SPINNER_TYPES from codeflash.cli_cmds.logging_config import BARE_LOGGING_FORMAT -from codeflash.lsp.helpers import lsp_log +from codeflash.lsp.helpers import enhanced_log, is_LSP_enabled if TYPE_CHECKING: from collections.abc import Generator @@ -31,7 +31,7 @@ console = Console() -if os.getenv("CODEFLASH_LSP"): +if is_LSP_enabled(): console.quiet = True logging.basicConfig( @@ -43,11 +43,17 @@ logger = logging.getLogger("rich") logging.getLogger("parso").setLevel(logging.WARNING) -real_info_log_fn = logger.info -logger.info = lambda msg, *args, **kwargs: lsp_log(msg, real_info_log_fn, *args, **kwargs) +# override the logger to reformat the messages for the lsp +for level in ("info", "debug", "warning", "error"): + real_fn = getattr(logger, level) + setattr(logger, level, lambda msg, *args, _real_fn=real_fn, **kwargs: enhanced_log(msg, _real_fn, *args, **kwargs)) -real_debug_log_fn = logger.debug -logger.debug = lambda msg, *args, **kwargs: lsp_log(msg, real_debug_log_fn, *args, **kwargs) + +def lsp_log(serializable: dict[str, Any], *args: Any, **kwargs: Any) -> None: # noqa: ANN401 + if not is_LSP_enabled(): + return + msg_str = json.dumps(serializable) + logger.info(msg_str, *args, **kwargs) def paneled_text( @@ -69,8 +75,13 @@ def code_print(code_str: str) -> None: """Print code with syntax highlighting.""" from rich.syntax import Syntax + formatted_code = Syntax(code_str, "python", line_numbers=True, theme="github-dark") + # if is_LSP_enabled(): + # logger.debug(formatted_code.__str__()) + # return + console.rule() - console.print(Syntax(code_str, "python", line_numbers=True, theme="github-dark")) + console.print(formatted_code) console.rule() diff --git a/codeflash/lsp/helpers.py b/codeflash/lsp/helpers.py index db7aee34e..27f105658 100644 --- a/codeflash/lsp/helpers.py +++ b/codeflash/lsp/helpers.py @@ -8,8 +8,20 @@ def is_LSP_enabled() -> bool: return os.getenv("CODEFLASH_LSP", default="false").lower() == "true" -def lsp_log(msg: str, actual_log_fn: Callable[[str, Any, Any], None], *args: Any, **kwargs: Any) -> None: # noqa: ANN401 - if is_LSP_enabled(): - actual_log_fn(f"::::{msg}", *args, **kwargs) - else: +def enhanced_log(msg: str, actual_log_fn: Callable[[str, Any, Any], None], *args: Any, **kwargs: Any) -> None: # noqa: ANN401 + lsp_enabled = is_LSP_enabled() + + # normal cli moded + if not lsp_enabled: actual_log_fn(msg, *args, **kwargs) + return + + #### LSP mode #### + if type(msg) != str: # noqa: E721 + return + + if msg.startswith("Nonzero return code"): + # skip logging the failed tests msg to the client + return + + actual_log_fn(f"::::{msg}", *args, **kwargs)