Skip to content

Commit 65e56e7

Browse files
committed
clean up a bit, add some tests
1 parent 2e2f94d commit 65e56e7

File tree

4 files changed

+88
-60
lines changed

4 files changed

+88
-60
lines changed

sentry_sdk/_experimental_logger.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# NOTE: this is the logger sentry exposes to users, not some generic logger.
22
import functools
3+
from time import time_ns
34
from typing import Any
45

56
from sentry_sdk import get_client, get_current_scope
@@ -9,9 +10,24 @@ def _capture_log(severity_text, severity_number, template, **kwargs):
910
# type: (str, int, str, **Any) -> None
1011
client = get_client()
1112
scope = get_current_scope()
12-
kwargs["sentry.message.template"] = template
13-
client.capture_log(
14-
scope, severity_text, severity_number, template.format(**kwargs), **kwargs
13+
14+
attrs = {
15+
"sentry.message.template": template,
16+
}
17+
for k, v in kwargs.items():
18+
attrs[f"sentry.message.parameters.{k}"] = v
19+
20+
# noinspection PyProtectedMember
21+
client._capture_experimental_log(
22+
scope,
23+
{
24+
"severity_text": severity_text,
25+
"severity_number": severity_number,
26+
"attributes": attrs,
27+
"body": template.format(**kwargs),
28+
"time_unix_nano": time_ns(),
29+
"trace_id": None,
30+
},
1531
)
1632

1733

sentry_sdk/client.py

Lines changed: 16 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import json
22
import os
3-
import time
43
import uuid
54
import random
65
import socket
@@ -209,10 +208,8 @@ def capture_event(self, *args, **kwargs):
209208
# type: (*Any, **Any) -> Optional[str]
210209
return None
211210

212-
def _capture_experimental_log(
213-
self, scope, severity_text, severity_number, body, time_unix_nano=None, **kwargs
214-
):
215-
# type: (Scope, str, int, str, Optional[int], **Any) -> None
211+
def _capture_experimental_log(self, scope, log):
212+
# type: (Scope, Log) -> None
216213
pass
217214

218215
def capture_session(self, *args, **kwargs):
@@ -856,50 +853,33 @@ def capture_event(
856853

857854
return return_value
858855

859-
def _capture_experimental_log(
860-
self, scope, severity_text, severity_number, body, time_unix_nano=None, **kwargs
861-
):
862-
# type: (Scope, str, int, str, Optional[int], **Any) -> None
856+
def _capture_experimental_log(self, scope, log):
857+
# type: (Scope, Log) -> None
863858
logs_enabled = self.options["_experiments"].get("enable_sentry_logs", False)
864859
if not logs_enabled:
865860
return
866861

867-
if time_unix_nano is None:
868-
time_unix_nano = time.time_ns()
869-
870862
headers = {
871863
"sent_at": format_timestamp(datetime.now(timezone.utc)),
872864
} # type: dict[str, object]
873865

874-
attrs = {} # type: dict[str, str | bool | float | int]
875-
876-
kwargs_attributes = kwargs.get("attributes")
877-
if kwargs_attributes is not None:
878-
attrs.update(kwargs_attributes)
879-
880866
environment = self.options.get("environment")
881-
if environment is not None:
882-
attrs["sentry.environment"] = environment
867+
if environment is not None and "sentry.environment" not in log["attributes"]:
868+
log["attributes"]["sentry.environment"] = environment
883869

884870
release = self.options.get("release")
885-
if release is not None:
886-
attrs["sentry.release"] = release
871+
if release is not None and "sentry.release" not in log["attributes"]:
872+
log["attributes"]["sentry.release"] = release
887873

888874
span = scope.span
889-
if span is not None:
890-
attrs["sentry.trace.parent_span_id"] = span.span_id
891-
892-
for k, v in kwargs.items():
893-
attrs[f"sentry.message.parameters.{k}"] = v
875+
if span is not None and "sentry.trace.parent_span_id" not in log["attributes"]:
876+
log["attributes"]["sentry.trace.parent_span_id"] = span.span_id
894877

895-
log = {
896-
"severity_text": severity_text,
897-
"severity_number": severity_number,
898-
"body": body,
899-
"attributes": attrs,
900-
"time_unix_nano": time_unix_nano,
901-
"trace_id": None,
902-
} # type: Log
878+
propagation_context = scope.get_active_propagation_context()
879+
if propagation_context is not None:
880+
headers["trace_id"] = propagation_context.trace_id
881+
if log["trace_id"] is None:
882+
log["trace_id"] = propagation_context.trace_id
903883

904884
# If debug is enabled, log the log to the console
905885
debug = self.options.get("debug", False)
@@ -914,15 +894,10 @@ def _capture_experimental_log(
914894
}
915895
# Be careful editing this line, you can add infinite logging loops with the logger integration
916896
logger.log(
917-
severity_text_to_logging_level.get(severity_text, logging.DEBUG),
897+
severity_text_to_logging_level.get(log["severity_text"], logging.DEBUG),
918898
f'[Sentry Logs] {log["body"]}',
919899
)
920900

921-
propagation_context = scope.get_active_propagation_context()
922-
if propagation_context is not None:
923-
headers["trace_id"] = propagation_context.trace_id
924-
log["trace_id"] = propagation_context.trace_id
925-
926901
envelope = Envelope(headers=headers)
927902

928903
before_emit_log = self.options["_experiments"].get("before_emit_log")

sentry_sdk/integrations/logging.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -354,43 +354,45 @@ def _capture_log_from_record(client, record):
354354
# type: (BaseClient, LogRecord) -> None
355355
scope = sentry_sdk.get_current_scope()
356356
otel_severity_number, otel_severity_text = _python_level_to_otel(record.levelno)
357-
kwargs = {
357+
attrs = {
358358
"sentry.message.template": (
359359
record.msg if isinstance(record.msg, str) else json.dumps(record.msg)
360360
),
361361
}
362362
if record.args is not None:
363363
if isinstance(record.args, tuple):
364364
for i, arg in enumerate(record.args):
365-
kwargs[f"sentry.message.parameters.{i}"] = (
365+
attrs[f"sentry.message.parameters.{i}"] = (
366366
arg if isinstance(arg, str) else json.dumps(arg)
367367
)
368368
if record.lineno:
369-
kwargs["code.line.number"] = record.lineno
369+
attrs["code.line.number"] = record.lineno
370370
if record.pathname:
371-
kwargs["code.file.path"] = record.pathname
371+
attrs["code.file.path"] = record.pathname
372372
if record.funcName:
373-
kwargs["code.function.name"] = record.funcName
373+
attrs["code.function.name"] = record.funcName
374374

375375
if record.thread:
376-
kwargs["thread.id"] = record.thread
376+
attrs["thread.id"] = record.thread
377377
if record.threadName:
378-
kwargs["thread.name"] = record.threadName
378+
attrs["thread.name"] = record.threadName
379379

380380
if record.process:
381-
kwargs["process.pid"] = record.process
381+
attrs["process.pid"] = record.process
382382
if record.processName:
383-
kwargs["process.executable.name"] = record.processName
383+
attrs["process.executable.name"] = record.processName
384384
if record.name:
385-
kwargs["logger.name"] = record.name
386-
if record.created:
387-
kwargs["time_unix_nano"] = int(record.created * 1e9)
385+
attrs["logger.name"] = record.name
388386

389387
# noinspection PyProtectedMember
390388
client._capture_experimental_log(
391389
scope,
392-
otel_severity_text,
393-
otel_severity_number,
394-
record.getMessage(),
395-
**kwargs,
390+
{
391+
"severity_text": otel_severity_text,
392+
"severity_number": otel_severity_number,
393+
"body": record.message,
394+
"attributes": attrs,
395+
"time_unix_nano": int(record.created * 1e9),
396+
"trace_id": None,
397+
},
396398
)

tests/test_logs.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
import sys
23
from unittest import mock
34
import pytest
@@ -240,3 +241,37 @@ def test_logs_tied_to_spans(sentry_init, capture_envelopes):
240241
"key": "sentry.trace.parent_span_id",
241242
"value": {"stringValue": span.span_id},
242243
}
244+
245+
246+
@minimum_python_37
247+
def test_logger_integration_warning(sentry_init, capture_envelopes):
248+
"""
249+
The python logger module should create 'warn' sentry logs if the flag is on.
250+
"""
251+
sentry_init(_experiments={"enable_sentry_logs": True})
252+
envelopes = capture_envelopes()
253+
254+
python_logger = logging.Logger("test-logger")
255+
python_logger.warning("this is %s a template %s", "1", "2")
256+
257+
log_entry = envelopes[0].items[0].payload.json
258+
assert log_entry["attributes"][0] == {
259+
"key": "sentry.message.template",
260+
"value": {"stringValue": "this is %s a template %s"},
261+
}
262+
assert log_entry["severityNumber"] == 13
263+
assert log_entry["severityText"] == "warn"
264+
265+
266+
@minimum_python_37
267+
def test_logger_integration_debug(sentry_init, capture_envelopes):
268+
"""
269+
The python logger module should not create 'debug' sentry logs if the flag is on by default
270+
"""
271+
sentry_init(_experiments={"enable_sentry_logs": True})
272+
envelopes = capture_envelopes()
273+
274+
python_logger = logging.Logger("test-logger")
275+
python_logger.debug("this is %s a template %s", "1", "2")
276+
277+
assert len(envelopes) == 0

0 commit comments

Comments
 (0)