Repository: kiwicom/structlog-sentry

Issue:
Logger not set when recording events
The Sentry SDK sets a `logger` key at the root level of the `event`: https://github.com/getsentry/sentry-python/blob/718f61b892398c1156ab8952f41494768175da6f/sentry_sdk/integrations/logging.py#L206. structlog-sentry does not do that: https://github.com/kiwicom/structlog-sentry/blob/00ba79ef470ed81f4e396fde134f6612aa34551d/structlog_sentry/__init__.py#L53-L54

I'd like to suggest to add the logger when present in the `event_dict` and document to use structlog's built-in `add_logger_name` processor.

Comments:

Patch:
diff --git a/README.md b/README.md
index 7d67e81..e02f2f1 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,7 @@ sentry_sdk.init()  # pass dsn in argument or via SENTRY_DSN env variable
 
 structlog.configure(
     processors=[
+        structlog.stdlib.add_logger_name,  # optional, but before SentryProcessor()
         structlog.stdlib.add_log_level,  # required before SentryProcessor()
         SentryProcessor(level=logging.ERROR),
     ],
@@ -42,8 +43,9 @@ structlog.configure(
 log = structlog.get_logger()
 ```
 
-Do not forget to add the `structlog.stdlib.add_log_level` processor before
-`SentryProcessor`. The `SentryProcessor` class takes the following arguments:
+Do not forget to add the `structlog.stdlib.add_log_level` and optionally the
+`structlog.stdlib.add_logger_name` processors before `SentryProcessor`. The
+`SentryProcessor` class takes the following arguments:
 
 - `level` - events of this or higher levels will be reported to Sentry,
   default is `WARNING`
@@ -95,6 +97,7 @@ You can set some or all of key/value pairs of structlog `event_dict` as sentry `
 ```python
 structlog.configure(
     processors=[
+        structlog.stdlib.add_logger_name,
         structlog.stdlib.add_log_level,
         SentryProcessor(level=logging.ERROR, tag_keys=["city", "timezone"]),
     ],...
@@ -109,6 +112,7 @@ If you want to have all event data as tags, create the `SentryProcessor` with `t
 ```python
 structlog.configure(
     processors=[
+        structlog.stdlib.add_logger_name,
         structlog.stdlib.add_log_level,
         SentryProcessor(level=logging.ERROR, tag_keys="__all__"),
     ],...
@@ -123,6 +127,7 @@ Sometimes you may want to skip this, specially when sending the `event_dict` as
 ```python
 structlog.configure(
     processors=[
+        structlog.stdlib.add_logger_name,
         structlog.stdlib.add_log_level,
         SentryProcessor(level=logging.ERROR, as_extra=False, tag_keys="__all__"),
     ],...
diff --git a/structlog_sentry/__init__.py b/structlog_sentry/__init__.py
index d175653..f63ce6b 100644
--- a/structlog_sentry/__init__.py
+++ b/structlog_sentry/__init__.py
@@ -52,6 +52,8 @@ class SentryProcessor:
 
         event["message"] = event_dict.get("event")
         event["level"] = event_dict.get("level")
+        if "logger" in event_dict:
+            event["logger"] = event_dict["logger"]
 
         if self._as_extra:
             event["extra"] = self._original_event_dict


Test patch:
diff --git a/test/test_sentry_processor.py b/test/test_sentry_processor.py
index 39f69f3..a9d70e8 100644
--- a/test/test_sentry_processor.py
+++ b/test/test_sentry_processor.py
@@ -98,6 +98,30 @@ def test_sentry_log_failure_exc_info_true(mocker, level):
     assert kwargs["hint"]["exc_info"][0] == ZeroDivisionError
 
 
+absent = object()
+
+
+@pytest.mark.parametrize("logger", ["some.logger.name", absent])
+def test_sentry_add_logger_name(mocker, logger):
+    m_capture_event = mocker.patch("structlog_sentry.capture_event")
+
+    event_data = {"level": "warning", "event": "some.event"}
+    if logger is not absent:
+        event_data["logger"] = logger
+
+    processor = SentryProcessor(as_extra=False)
+    processor(None, None, event_data)
+
+    if logger is absent:
+        m_capture_event.assert_called_once_with(
+            {"level": "warning", "message": "some.event"}, hint=None
+        )
+    else:
+        m_capture_event.assert_called_once_with(
+            {"level": "warning", "message": "some.event", "logger": logger}, hint=None
+        )
+
+
 def test_sentry_log_leave_exc_info_untouched(mocker):
     """Make sure exc_info remains in event_data at the end of the processor.