maciejpolanczyk opened a new issue, #69464:
URL: https://github.com/apache/airflow/issues/69464
### Under which category would you file this issue?
Task SDK
### Apache Airflow version
3.2.2 (also reproduced, unchanged, on 3.3.0rc2)
### What happened and how to reproduce it?
When `[sentry] before_send` (e.g.
`AIRFLOW__SENTRY__BEFORE_SEND=<dotted.path>`) is configured,
`ConfiguredSentry.prepare_to_enrich_errors()` in
`task-sdk/src/airflow/sdk/execution_time/sentry/configured.py` never
resolves it into an
actual callable — it gets passed to `sentry_sdk.init()` as the raw string:
```python
sentry_config_opts: dict[str, Any] = conf.getsection("sentry") or {}
if sentry_config_opts:
sentry_config_opts.pop("sentry_on")
old_way_dsn = sentry_config_opts.pop("sentry_dsn", None)
new_way_dsn = sentry_config_opts.pop("dsn", None)
dsn = old_way_dsn or new_way_dsn
...
else:
dsn = None
if before_send := conf.getimport("sentry", "before_send", fallback=None):
sentry_config_opts["before_send"] = before_send
if transport := conf.getimport("sentry", "transport", fallback=None):
sentry_config_opts["transport"] = transport
if dsn:
sentry_sdk.init(dsn=dsn, integrations=integrations, **sentry_config_opts)
```
`conf.getsection("sentry")` always returns a non-empty dict — it starts from
the section's
schema defaults (`sentry_on`, `sentry_dsn` both have non-None defaults) — so
the
`if sentry_config_opts:` branch is *always* taken, and the `else` branch
(the only place
`before_send`/`transport` get resolved via `conf.getimport()`) is
unreachable dead code.
As a result, `sentry_sdk.init(before_send="my.dotted.path", ...)` receives a
plain string.
At event-capture time, `sentry_sdk`'s `Client._prepare_event` calls
`before_send(event, hint)`,
raising `TypeError: 'str' object is not callable`. This is swallowed
internally by
`capture_internal_exceptions()` (logged only via the internal
`sentry_sdk.errors` logger) —
the event is silently dropped with no error surfaced and nothing delivered
to Sentry.
Same issue applies to `transport`.
This is a regression from Airflow 2.x's `airflow/sentry.py`, where the
equivalent
`conf.getimport(...)` calls ran unconditionally:
```python
sentry_config_opts["before_send"] = conf.getimport("sentry", "before_send",
fallback=None)
sentry_config_opts["transport"] = conf.getimport("sentry", "transport",
fallback=None)
```
(see 2.11.0's `airflow/sentry.py`). This logic appears to have been ported
into the Task SDK
reimplementation in #57032, but the branching structure changed such that
the resolution
path became unreachable.
**Steps to reproduce:**
```
AIRFLOW__SENTRY__SENTRY_ON=True
AIRFLOW__SENTRY__SENTRY_DSN=<any DSN>
AIRFLOW__SENTRY__BEFORE_SEND=path.to.a.real.before_send.function
```
```python
from airflow.sdk.execution_time.sentry.configured import ConfiguredSentry
cs = ConfiguredSentry()
cs.prepare_to_enrich_errors(executor_integration="")
import sentry_sdk
print(type(sentry_sdk.get_client().options.get("before_send")))
# prints <class 'str'> instead of the resolved function
```
Any subsequent `sentry_sdk.capture_exception()` / `capture_message()` call
will silently
fail to deliver its event.
### What you think should happen instead?
`before_send`/`transport` dotted paths configured via `[sentry]` should
always be resolved
into real callables via `conf.getimport()`, regardless of what else is set
in the `[sentry]`
section — matching 2.x behavior, e.g.:
```python
sentry_config_opts: dict[str, Any] = conf.getsection("sentry") or {}
sentry_config_opts.pop("sentry_on", None)
old_way_dsn = sentry_config_opts.pop("sentry_dsn", None)
new_way_dsn = sentry_config_opts.pop("dsn", None)
dsn = old_way_dsn or new_way_dsn
if before_send := conf.getimport("sentry", "before_send", fallback=None):
sentry_config_opts["before_send"] = before_send
if transport := conf.getimport("sentry", "transport", fallback=None):
sentry_config_opts["transport"] = transport
```
### Operating System
N/A — reproduced via the official `apache/airflow:3.2.2-python3.12` and
`apache/airflow:3.3.0rc2-python3.12` images.
### Deployment
Other Docker-based deployment
### Apache Airflow Provider(s)
_No response_
### Versions of Apache Airflow Providers
_No response_
### Official Helm Chart version
Not Applicable
### Kubernetes Version
Not Applicable
### Helm Chart configuration
Not Applicable
### Docker Image customizations
Not Applicable — reproduced against the unmodified official images.
### Anything else?
This is separate from #52368 / #65136 / #65161 (uncaught task exceptions not
captured by
Sentry), which is fixed in 3.3.0. This `before_send`/`transport` resolution
bug is a
different issue, still present unchanged in 3.3.0rc2.
### Are you willing to submit PR?
- [ ] Yes I am willing to submit a PR!
### Code of Conduct
- [x] I agree to follow this project's Code of Conduct
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]