Skip to content
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
15 changes: 13 additions & 2 deletions sentry_sdk/integrations/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,32 +356,43 @@ def _capture_log_from_record(self, client, record):
record.levelno, SEVERITY_TO_OTEL_SEVERITY
)
project_root = client.options["project_root"]

attrs = self._extra_from_record(record) # type: Any
attrs["sentry.origin"] = "auto.logger.log"
if isinstance(record.msg, str):
attrs["sentry.message.template"] = record.msg

parameters_set = False
if record.args is not None:
if isinstance(record.args, tuple):
parameters_set = bool(record.args)
for i, arg in enumerate(record.args):
attrs[f"sentry.message.parameter.{i}"] = (
arg
if isinstance(arg, (str, float, int, bool))
else safe_repr(arg)
)
elif isinstance(record.args, dict):
parameters_set = bool(record.args)
for key, value in record.args.items():
attrs[f"sentry.message.parameter.{key}"] = (
value
if isinstance(value, (str, float, int, bool))
else safe_repr(value)
)

if parameters_set and isinstance(record.msg, str):
# only include template if there is at least one
# sentry.message.parameter.X set
attrs["sentry.message.template"] = record.msg

if record.lineno:
attrs["code.line.number"] = record.lineno

if record.pathname:
if project_root is not None and record.pathname.startswith(project_root):
attrs["code.file.path"] = record.pathname[len(project_root) + 1 :]
else:
attrs["code.file.path"] = record.pathname

if record.funcName:
attrs["code.function.name"] = record.funcName

Expand Down
7 changes: 4 additions & 3 deletions sentry_sdk/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ def _capture_log(severity_text, severity_number, template, **kwargs):
# type: (str, int, str, **Any) -> None
client = get_client()

attrs = {
"sentry.message.template": template,
} # type: dict[str, str | bool | float | int]
attrs = {} # type: dict[str, str | bool | float | int]
if "attributes" in kwargs:
attrs.update(kwargs.pop("attributes"))
for k, v in kwargs.items():
attrs[f"sentry.message.parameter.{k}"] = v
if kwargs:
# only attach template if there are parameters
attrs["sentry.message.template"] = template

attrs = {
k: (
Expand Down
19 changes: 19 additions & 0 deletions tests/integrations/logging/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,3 +571,22 @@ def test_sentry_logs_named_parameters_complex_values(sentry_init, capture_envelo
assert isinstance(complex_param, str)
assert "nested" in complex_param
assert "data" in complex_param


def test_sentry_logs_no_parameters_no_template(sentry_init, capture_envelopes):
"""
There shouldn't be a template if there are no parameters.
"""
sentry_init(enable_logs=True)
envelopes = capture_envelopes()

python_logger = logging.Logger("test-logger")
python_logger.warning("Warning about something without any parameters.")

get_client().flush()
logs = envelopes_to_logs(envelopes)

assert len(logs) == 1

attrs = logs[0]["attributes"]
assert "sentry.message.template" not in attrs
18 changes: 18 additions & 0 deletions tests/integrations/loguru/test_loguru.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,3 +467,21 @@ def test_logger_with_all_attributes(
"sentry.severity_number": 13,
"sentry.severity_text": "warn",
}


def test_no_parameters_no_template(
sentry_init, capture_envelopes, uninstall_integration, request
):
uninstall_integration("loguru")
request.addfinalizer(logger.remove)

sentry_init(enable_logs=True)
envelopes = capture_envelopes()

logger.warning("Logging a hardcoded warning")
sentry_sdk.get_client().flush()

logs = envelopes_to_logs(envelopes)

attributes = logs[0]["attributes"]
assert "sentry.message.template" not in attributes
24 changes: 24 additions & 0 deletions tests/test_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,30 +254,54 @@ def test_logs_message_params(sentry_init, capture_envelopes):
sentry_sdk.logger.error(
"The recorded error was '{error}'", error=Exception("some error")
)
sentry_sdk.logger.warning("The recorded value was hardcoded.")

get_client().flush()
logs = envelopes_to_logs(envelopes)

assert logs[0]["body"] == "The recorded value was '1'"
assert logs[0]["attributes"]["sentry.message.parameter.int_var"] == 1
assert (
logs[0]["attributes"]["sentry.message.template"]
== "The recorded value was '{int_var}'"
)

assert logs[1]["body"] == "The recorded value was '2.0'"
assert logs[1]["attributes"]["sentry.message.parameter.float_var"] == 2.0
assert (
logs[1]["attributes"]["sentry.message.template"]
== "The recorded value was '{float_var}'"
)

assert logs[2]["body"] == "The recorded value was 'False'"
assert logs[2]["attributes"]["sentry.message.parameter.bool_var"] is False
assert (
logs[2]["attributes"]["sentry.message.template"]
== "The recorded value was '{bool_var}'"
)

assert logs[3]["body"] == "The recorded value was 'some string value'"
assert (
logs[3]["attributes"]["sentry.message.parameter.string_var"]
== "some string value"
)
assert (
logs[3]["attributes"]["sentry.message.template"]
== "The recorded value was '{string_var}'"
)

assert logs[4]["body"] == "The recorded error was 'some error'"
assert (
logs[4]["attributes"]["sentry.message.parameter.error"]
== "Exception('some error')"
)
assert (
logs[4]["attributes"]["sentry.message.template"]
== "The recorded error was '{error}'"
)

assert logs[5]["body"] == "The recorded value was hardcoded."
assert "sentry.message.template" not in logs[5]["attributes"]


@minimum_python_37
Expand Down