Skip to content

Commit 3075b83

Browse files
feat: better logging
1 parent d723fb9 commit 3075b83

File tree

8 files changed

+99
-22
lines changed

8 files changed

+99
-22
lines changed

jtd_codebuild/cli.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
1+
from typing import Callable
12
import click
23
from click.core import Context
34
from .commands import BuildCommand, InitCommand
5+
from .logger import Logger, ClickLogger
46

57

68
@click.group(invoke_without_command=True)
79
@click.argument("path", type=click.Path(), required=False)
10+
@click.option("--verbose", "-v", is_flag=True)
811
@click.pass_context
9-
def cli(ctx: Context, path: str):
12+
def cli(ctx: Context, path: str, verbose: bool):
1013
# If no subcommand is provided, run the build command
1114
if ctx.invoked_subcommand is None:
12-
BuildCommand().run(path or ".")
15+
logger = _create_logger(verbose)
16+
command = BuildCommand(logger=logger)
17+
_error_boundary(lambda: command.run(path or "."), logger)
1318
else:
14-
ctx.obj = {"path": path or "."}
19+
ctx.obj = {
20+
"path": path or ".",
21+
"verbose": verbose,
22+
}
1523

1624

1725
@cli.command("init")
@@ -24,4 +32,21 @@ def cli(ctx: Context, path: str):
2432
)
2533
def init(ctx: Context, preset: str):
2634
path = ctx.obj["path"]
27-
InitCommand().run(path, preset)
35+
verbose = ctx.obj["verbose"]
36+
37+
logger = _create_logger(verbose)
38+
command = InitCommand(logger=logger)
39+
_error_boundary(lambda: command.run(path, preset), logger)
40+
41+
42+
def _create_logger(verbose: bool) -> ClickLogger:
43+
return ClickLogger(level=1 if verbose else 2)
44+
45+
46+
def _error_boundary(func: Callable, logger: Logger):
47+
try:
48+
func()
49+
except Exception as e:
50+
for line in str(e).split("\n"):
51+
logger.error(line)
52+
exit(1)

jtd_codebuild/codebuild.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from os import getcwd
2-
from os.path import basename
2+
from os.path import relpath
33
from typing import Callable, Type
44
from toolz import pipe
55
from toolz.curried import map
@@ -45,7 +45,7 @@ def run( # noqa: C901
4545
target_path = resolve(cwd, path)
4646
config = get_project_config(target_path)
4747

48-
self.logger.info(f"Start building: {basename(target_path)}")
48+
self.logger.info(f"Start building: {path}")
4949

5050
self.logger.info("Bundling IDL files...")
5151
bundler = Bundler(logger=self.logger)
@@ -55,11 +55,10 @@ def run( # noqa: C901
5555
inheritance.resolve,
5656
)
5757

58-
self.logger.info("Writing bundled IDL file...")
5958
schema_path = resolve(target_path, config.jtdBundlePath)
6059
write_json(schema_path, bundled_jtd_schema)
6160

62-
self.logger.success("Wrote bundled IDL file...")
61+
self.logger.success(f"Wrote bundled IDL file at: {relpath(schema_path, cwd)}")
6362

6463
self.logger.info("Generating targets...")
6564

jtd_codebuild/generators/_generator.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from jtd_codebuild.logger import Logger
55
from jtd_codebuild.config.project.model import Target
66
from jtd_codebuild.utils.fs import safe_mkdir, resolve
7+
from jtd_codebuild.utils.subprocess import stream_logs
78

89

910
class JTDCodeGenerator(Component, metaclass=abc.ABCMeta):
@@ -60,6 +61,7 @@ def generate(self, target: Target) -> None:
6061
stdout=subprocess.PIPE,
6162
stderr=subprocess.PIPE,
6263
)
64+
stream_logs(process, logger=self.logger, level="debug")
6365
process.wait()
6466

6567
def get_schema_path(self) -> str:

jtd_codebuild/logger/_click_logger.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,35 @@
44

55
class ClickLogger(Logger):
66
def debug(self, message: str, *args, **kwargs) -> None:
7-
kwargs.setdefault("color", "blue")
8-
message = f"[jtd-codebuild] | DEBUG | {message}"
9-
click.echo(message, *args, **kwargs)
7+
if self.level > 1:
8+
return
9+
kwargs.setdefault("fg", "blue")
10+
message = f"[jtd-codebuild] | DEBUG | {message}"
11+
click.echo(click.style(message, *args, **kwargs))
1012

1113
def info(self, message: str, *args, **kwargs) -> None:
12-
message = f"[jtd-codebuild] | INFO | {message}"
13-
click.echo(message, *args, **kwargs)
14+
if self.level > 2:
15+
return
16+
message = f"[jtd-codebuild] | INFO | {message}"
17+
click.echo(click.style(message, *args, **kwargs))
1418

1519
def success(self, message: str, *args, **kwargs) -> None:
20+
if self.level > 3:
21+
return
1622
message = f"[jtd-codebuild] | SUCCESS | {message}"
17-
kwargs.setdefault("color", "green")
18-
click.echo(message, *args, **kwargs)
23+
kwargs.setdefault("fg", "green")
24+
click.echo(click.style(message, *args, **kwargs))
1925

2026
def warning(self, message: str, *args, **kwargs) -> None:
27+
if self.level > 4:
28+
return
2129
message = f"[jtd-codebuild] | WARNING | {message}"
22-
kwargs.setdefault("color", "yellow")
23-
click.echo(message, *args, **kwargs)
30+
kwargs.setdefault("fg", "yellow")
31+
click.echo(click.style(message, *args, **kwargs))
2432

2533
def error(self, message: str, *args, **kwargs) -> None:
26-
message = f"[jtd-codebuild] | ERROR | {message}"
27-
kwargs.setdefault("color", "red")
28-
click.echo(message, *args, **kwargs)
34+
if self.level > 5:
35+
return
36+
message = f"[jtd-codebuild] | ERROR | {message}"
37+
kwargs.setdefault("fg", "red")
38+
click.echo(click.style(message, *args, **kwargs))

jtd_codebuild/logger/_logger.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
11
import abc
2+
from typing import Literal, TypeAlias
3+
from jtd_codebuild.utils.mapping import Subscriptable
24

5+
Level: TypeAlias = Literal[
6+
1, # DEBUG
7+
2, # INFO
8+
3, # SUCCESS
9+
4, # WARNING
10+
5, # ERROR
11+
]
12+
13+
14+
class Logger(Subscriptable, metaclass=abc.ABCMeta):
15+
16+
def __init__(self, level: Level = 2) -> None:
17+
self.level = level
318

4-
class Logger(metaclass=abc.ABCMeta):
519
@abc.abstractmethod
620
def debug(self, message: str, *args, **kwargs) -> None:
721
pass

jtd_codebuild/utils/subprocess.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import subprocess
2+
from jtd_codebuild.logger import Logger
3+
4+
5+
def flush_streams_to_logs(
6+
process: subprocess.Popen,
7+
*,
8+
logger: Logger,
9+
level: str = "info",
10+
):
11+
pipe_data = process.communicate()
12+
for data in pipe_data:
13+
if data:
14+
for line in data.decode().split("\n"):
15+
logger[level](line)
16+
17+
18+
def stream_logs(
19+
process: subprocess.Popen,
20+
*,
21+
logger: Logger,
22+
level: str = "info",
23+
):
24+
while process.returncode is None:
25+
flush_streams_to_logs(process, logger=logger, level=level)
26+
flush_streams_to_logs(process, logger=logger, level=level)

poetry.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ toolz = "^0.12.1"
3535
deepmerge = "^1.1.1"
3636
joblib = "^1.4.0"
3737
pydantic = "^2.7.1"
38+
colorama = "^0.4.6"
3839

3940
[tool.poetry.group.dev.dependencies]
4041
flake8 = "^6.1.0"

0 commit comments

Comments
 (0)