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

Add min_log_level to console options #95

Merged
merged 5 commits into from
May 3, 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
10 changes: 10 additions & 0 deletions logfire/_internal/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
OTLP_MAX_BODY_SIZE,
RESOURCE_ATTRIBUTES_PACKAGE_VERSIONS,
SUPPRESS_INSTRUMENTATION_CONTEXT_KEY,
LevelName,
)
from .exporters.console import (
ConsoleColorsValues,
Expand Down Expand Up @@ -101,7 +102,14 @@ class ConsoleOptions:
span_style: Literal['simple', 'indented', 'show-parents'] = 'show-parents'
"""How spans are shown in the console."""
include_timestamps: bool = True
"""Whether to include timestamps in the console output."""
verbose: bool = False
"""Whether to show verbose output.

It includes the filename, log level, and line number.
Kludex marked this conversation as resolved.
Show resolved Hide resolved
"""
min_log_level: LevelName = 'info'
"""The minimum log level to show in the console."""


@dataclass
Expand Down Expand Up @@ -368,6 +376,7 @@ def _load_configuration(
span_style=param_manager.load_param('console_span_style'),
include_timestamps=param_manager.load_param('console_include_timestamp'),
verbose=param_manager.load_param('console_verbose'),
min_log_level=param_manager.load_param('console_min_log_level'),
)

if isinstance(pydantic_plugin, dict):
Expand Down Expand Up @@ -586,6 +595,7 @@ def add_span_processor(span_processor: SpanProcessor) -> None:
colors=self.console.colors,
include_timestamp=self.console.include_timestamps,
verbose=self.console.verbose,
min_log_level=self.console.min_log_level,
),
)
)
Expand Down
5 changes: 4 additions & 1 deletion logfire/_internal/config_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from logfire.exceptions import LogfireConfigError

from . import config
from .constants import LOGFIRE_BASE_URL
from .constants import LOGFIRE_BASE_URL, LevelName
from .exporters.console import ConsoleColorsValues
from .utils import read_toml_file

Expand Down Expand Up @@ -81,6 +81,8 @@ class ConfigParam:
"""Whether to include the timestamp in the console."""
CONSOLE_VERBOSE = ConfigParam(env_vars=['LOGFIRE_CONSOLE_VERBOSE'], allow_file_config=True, default=False, tp=bool)
"""Whether to log in verbose mode in the console."""
CONSOLE_MIN_LOG_LEVEL = ConfigParam(env_vars=['LOGFIRE_CONSOLE_MIN_LOG_LEVEL'], allow_file_config=True, default='info', tp=LevelName)
"""Minimum log level to show in the console."""
PYDANTIC_PLUGIN_RECORD = ConfigParam(env_vars=['LOGFIRE_PYDANTIC_PLUGIN_RECORD'], allow_file_config=True, default='off', tp=PydanticPluginRecordValues)
"""Whether instrument Pydantic validation.."""
PYDANTIC_PLUGIN_INCLUDE = ConfigParam(env_vars=['LOGFIRE_PYDANTIC_PLUGIN_INCLUDE'], allow_file_config=True, default=set(), tp=Set[str])
Expand All @@ -107,6 +109,7 @@ class ConfigParam:
'console_span_style': CONSOLE_SPAN_STYLE,
'console_include_timestamp': CONSOLE_INCLUDE_TIMESTAMP,
'console_verbose': CONSOLE_VERBOSE,
'console_min_log_level': CONSOLE_MIN_LOG_LEVEL,
'pydantic_plugin_record': PYDANTIC_PLUGIN_RECORD,
'pydantic_plugin_include': PYDANTIC_PLUGIN_INCLUDE,
'pydantic_plugin_exclude': PYDANTIC_PLUGIN_EXCLUDE,
Expand Down
14 changes: 12 additions & 2 deletions logfire/_internal/exporters/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
LEVEL_NUMBERS,
NUMBER_TO_LEVEL,
ONE_SECOND_IN_NANOSECONDS,
LevelName,
)
from ..json_formatter import json_args_value_formatter

ConsoleColorsValues = Literal['auto', 'always', 'never']
_INFO_LEVEL = LEVEL_NUMBERS['info']
_WARN_LEVEL = LEVEL_NUMBERS['warn']
_ERROR_LEVEL = LEVEL_NUMBERS['error']

Expand All @@ -56,6 +58,7 @@ def __init__(
colors: ConsoleColorsValues = 'auto',
include_timestamp: bool = True,
verbose: bool = False,
min_log_level: LevelName = 'info',
) -> None:
self._output = output or sys.stdout
if colors == 'auto':
Expand All @@ -78,10 +81,15 @@ def __init__(
# timestamp len('12:34:56.789') 12 + space (1)
self._timestamp_indent = 13 if include_timestamp else 0
self._verbose = verbose
self._min_log_level_num = LEVEL_NUMBERS[min_log_level]

def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
"""Export the spans to the console."""
for span in spans:
if span.attributes: # pragma: no branch
log_level: int = span.attributes.get(ATTRIBUTES_LOG_LEVEL_NUM_KEY, _INFO_LEVEL) # type: ignore
if log_level < self._min_log_level_num:
continue
self._log_span(span)

return SpanExportResult.SUCCESS
Expand Down Expand Up @@ -265,8 +273,9 @@ def __init__(
colors: ConsoleColorsValues = 'auto',
include_timestamp: bool = True,
verbose: bool = False,
min_log_level: LevelName = 'info',
) -> None:
super().__init__(output, colors, include_timestamp, verbose)
super().__init__(output, colors, include_timestamp, verbose, min_log_level)
# lookup from span ID to indent level
self._indent_level: dict[int, int] = {}

Expand Down Expand Up @@ -312,8 +321,9 @@ def __init__(
colors: ConsoleColorsValues = 'auto',
include_timestamp: bool = True,
verbose: bool = False,
min_log_level: LevelName = 'info',
) -> None:
super().__init__(output, colors, include_timestamp, verbose)
super().__init__(output, colors, include_timestamp, verbose, min_log_level)

# lookup from span_id to `(indent, span message, parent id)`
self._span_history: dict[int, tuple[int, str, int]] = {}
Expand Down
20 changes: 17 additions & 3 deletions tests/test_console_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io

import pytest
from inline_snapshot import snapshot
from opentelemetry import trace
from opentelemetry.sdk.trace import ReadableSpan

Expand Down Expand Up @@ -598,7 +599,7 @@ def test_levels(exporter: TestExporter):
]

out = io.StringIO()
SimpleConsoleSpanExporter(output=out, colors='never').export(spans) # type: ignore
SimpleConsoleSpanExporter(output=out, colors='never', min_log_level='trace').export(spans) # type: ignore
# insert_assert(out.getvalue().splitlines())
assert out.getvalue().splitlines() == [
'00:00:01.000 trace message',
Expand All @@ -611,7 +612,7 @@ def test_levels(exporter: TestExporter):
]

out = io.StringIO()
SimpleConsoleSpanExporter(output=out, colors='never', verbose=True).export(spans) # type: ignore
SimpleConsoleSpanExporter(output=out, colors='never', verbose=True, min_log_level='trace').export(spans) # type: ignore
# insert_assert(out.getvalue().splitlines())
assert out.getvalue().splitlines() == [
'00:00:01.000 trace message',
Expand All @@ -631,7 +632,7 @@ def test_levels(exporter: TestExporter):
]

out = io.StringIO()
SimpleConsoleSpanExporter(output=out, colors='always').export(spans) # type: ignore
SimpleConsoleSpanExporter(output=out, colors='always', min_log_level='trace').export(spans) # type: ignore
# insert_assert(out.getvalue().splitlines())
assert out.getvalue().splitlines() == [
'\x1b[32m00:00:01.000\x1b[0m trace message',
Expand All @@ -643,6 +644,19 @@ def test_levels(exporter: TestExporter):
'\x1b[32m00:00:07.000\x1b[0m \x1b[31mfatal message\x1b[0m',
]

out = io.StringIO()
# The `min_log_level` is set to 'info' by default, so only 'info' and higher levels are logged.
SimpleConsoleSpanExporter(output=out).export(spans) # type: ignore
assert out.getvalue().splitlines() == snapshot(
[
'00:00:03.000 info message',
'00:00:04.000 notice message',
'00:00:05.000 warn message',
'00:00:06.000 error message',
'00:00:07.000 fatal message',
]
)


def test_console_logging_to_stdout(capsys: pytest.CaptureFixture[str]):
# This is essentially a basic integration test, the other tests using an exporter
Expand Down