Skip to content

Commit 95819ab

Browse files
authored
print debug logs in the user directory under logs (#5388)
* print debug logs in the user directory under logs * make it if instead of elif * remove unused var
1 parent ac43955 commit 95819ab

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

reflex/config.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,12 @@ class EnvironmentVariables:
766766
# Whether to run Granian in a spawn process. This enables Reflex to pick up on environment variable changes between hot reloads.
767767
REFLEX_STRICT_HOT_RELOAD: EnvVar[bool] = env_var(False)
768768

769+
# The path to the reflex log file. If not set, the log file will be stored in the reflex user directory.
770+
REFLEX_LOG_FILE: EnvVar[Path | None] = env_var(None)
771+
772+
# Enable full logging of debug messages to reflex user directory.
773+
REFLEX_ENABLE_FULL_LOGGING: EnvVar[bool] = env_var(False)
774+
769775

770776
environment = EnvironmentVariables()
771777

reflex/utils/console.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from rich.prompt import Prompt
1616

1717
from reflex.constants import LogLevel
18+
from reflex.constants.base import Reflex
19+
from reflex.utils.decorator import once
1820

1921
# Console for pretty printing.
2022
_console = Console()
@@ -92,6 +94,51 @@ def print(msg: str, dedupe: bool = False, **kwargs):
9294
_console.print(msg, **kwargs)
9395

9496

97+
@once
98+
def log_file_console():
99+
"""Create a console that logs to a file.
100+
101+
Returns:
102+
A Console object that logs to a file.
103+
"""
104+
from reflex.config import environment
105+
106+
if not (env_log_file := environment.REFLEX_LOG_FILE.get()):
107+
subseconds = int((time.time() % 1) * 1000)
108+
timestamp = time.strftime("%Y-%m-%d_%H-%M-%S") + f"_{subseconds:03d}"
109+
log_file = Reflex.DIR / "logs" / (timestamp + ".log")
110+
log_file.parent.mkdir(parents=True, exist_ok=True)
111+
else:
112+
log_file = env_log_file
113+
if log_file.exists():
114+
log_file.unlink()
115+
log_file.touch()
116+
return Console(file=log_file.open("a", encoding="utf-8"))
117+
118+
119+
@once
120+
def should_use_log_file_console() -> bool:
121+
"""Check if the log file console should be used.
122+
123+
Returns:
124+
True if the log file console should be used, False otherwise.
125+
"""
126+
from reflex.config import environment
127+
128+
return environment.REFLEX_ENABLE_FULL_LOGGING.get()
129+
130+
131+
def print_to_log_file(msg: str, dedupe: bool = False, **kwargs):
132+
"""Print a message to the log file.
133+
134+
Args:
135+
msg: The message to print.
136+
dedupe: If True, suppress multiple console logs of print message.
137+
kwargs: Keyword arguments to pass to the print function.
138+
"""
139+
log_file_console().print(msg, **kwargs)
140+
141+
95142
def debug(msg: str, dedupe: bool = False, **kwargs):
96143
"""Print a debug message.
97144
@@ -110,6 +157,8 @@ def debug(msg: str, dedupe: bool = False, **kwargs):
110157
progress.console.print(msg_, **kwargs)
111158
else:
112159
print(msg_, **kwargs)
160+
if should_use_log_file_console():
161+
print_to_log_file(f"[purple]Debug: {msg}[/purple]", **kwargs)
113162

114163

115164
def info(msg: str, dedupe: bool = False, **kwargs):
@@ -126,6 +175,8 @@ def info(msg: str, dedupe: bool = False, **kwargs):
126175
return
127176
_EMITTED_INFO.add(msg)
128177
print(f"[cyan]Info: {msg}[/cyan]", **kwargs)
178+
if should_use_log_file_console():
179+
print_to_log_file(f"[cyan]Info: {msg}[/cyan]", **kwargs)
129180

130181

131182
def success(msg: str, dedupe: bool = False, **kwargs):
@@ -142,6 +193,8 @@ def success(msg: str, dedupe: bool = False, **kwargs):
142193
return
143194
_EMITTED_SUCCESS.add(msg)
144195
print(f"[green]Success: {msg}[/green]", **kwargs)
196+
if should_use_log_file_console():
197+
print_to_log_file(f"[green]Success: {msg}[/green]", **kwargs)
145198

146199

147200
def log(msg: str, dedupe: bool = False, **kwargs):
@@ -158,6 +211,8 @@ def log(msg: str, dedupe: bool = False, **kwargs):
158211
return
159212
_EMITTED_LOGS.add(msg)
160213
_console.log(msg, **kwargs)
214+
if should_use_log_file_console():
215+
print_to_log_file(msg, **kwargs)
161216

162217

163218
def rule(title: str, **kwargs):
@@ -184,6 +239,8 @@ def warn(msg: str, dedupe: bool = False, **kwargs):
184239
return
185240
_EMIITED_WARNINGS.add(msg)
186241
print(f"[orange1]Warning: {msg}[/orange1]", **kwargs)
242+
if should_use_log_file_console():
243+
print_to_log_file(f"[orange1]Warning: {msg}[/orange1]", **kwargs)
187244

188245

189246
def _get_first_non_framework_frame() -> FrameType | None:
@@ -248,6 +305,8 @@ def deprecate(
248305
)
249306
if _LOG_LEVEL <= LogLevel.WARNING:
250307
print(f"[yellow]DeprecationWarning: {msg}[/yellow]", **kwargs)
308+
if should_use_log_file_console():
309+
print_to_log_file(f"[yellow]DeprecationWarning: {msg}[/yellow]", **kwargs)
251310
if dedupe:
252311
_EMITTED_DEPRECATION_WARNINGS.add(dedupe_key)
253312

@@ -266,6 +325,8 @@ def error(msg: str, dedupe: bool = False, **kwargs):
266325
return
267326
_EMITTED_ERRORS.add(msg)
268327
print(f"[red]{msg}[/red]", **kwargs)
328+
if should_use_log_file_console():
329+
print_to_log_file(f"[red]{msg}[/red]", **kwargs)
269330

270331

271332
def ask(

0 commit comments

Comments
 (0)