Commit f2c33a6
authored
fix(dynamic-instrumentation): rebind FastAPI Depends() sub-dependencies (#785)
## Description
A **function-level** Dynamic Instrumentation breakpoint set on a
function that is used as a FastAPI `Depends()` **sub-dependency**
silently never fires. The instrumentation status stays `READY` (no
`ERROR`) and **zero snapshots** are produced, even though the dependency
callable executes on every request.
## Root cause
When DI instruments a module-level function it replaces it with a
wrapper and then calls `_patch_framework_references` →
`_patch_single_fastapi_app` to fix up framework-held references. That
patcher rebinds:
- `route.endpoint`, and
- the top-level `route.dependant.call`
…but the per-request dependency solver invokes sub-dependency callables
via `route.dependant.dependencies[*].call` (recursively). Those
references were **never** rebound, so FastAPI kept calling the original,
unwrapped function object and the DI wrapper never ran.
This is distinct from the inherited-method / nested-class silent-failure
cases: here the code-object identity is exactly correct
(`route.dependant.dependencies[0].call is original_func`); the only
problem is that the patcher didn't reach the sub-dependency reference.
```python
async def square_dependency(value: int = 7) -> int: # used only via Depends()
return value * value
@app.get("/dep")
async def decorators_dependency(dep: int = Depends(square_dependency)):
return {"result": dep}
```
A breakpoint on `square_dependency` (function-level) produced 0
snapshots; the same function with a **line-level** breakpoint fired
correctly (the line engine binds the code object directly), which
isolates the defect to the function-level FastAPI-patch path.
## Fix
Walk the whole `Dependant` tree (`endpoint` + `dependant` + nested
`dependencies`) and rebind only the references that match the target
function. Restricting rebinding to matches — rather than the previous
unconditional `route.endpoint = new_func` — prevents clobbering an
unrelated endpoint on a route that matched solely via one of its
sub-dependencies. The same recursive walk is applied in both the
identity-match pass and the name+module fallback, so the fallback now
also reaches sub-dependencies.
## Testing
- Added two regression tests in `test_function_wrapper_fastapi.py`:
- `test_patch_fastapi_routes_sub_dependency` — a `Depends()`
sub-dependency is rebound on `dependant.dependencies[*].call`, the
original is no longer referenced, and the route's own endpoint is not
clobbered.
- `test_patch_fastapi_routes_only_target_sub_dependency_rebound` — with
two `Depends()` on one route, only the targeted sub-dependency is
rebound; the other is left intact.
- Full debugger test suite passes locally: **547 passed, 43 skipped**
(the FastAPI file: 11 passed, 9 pre-existing + 2 new).
- Verified end-to-end on the live Application Signals pipeline (FastAPI
app → CloudWatch Agent → CloudWatch Logs): the function-level breakpoint
on the `Depends()` sub-dependency now reaches status `ACTIVE`
("breakpoint is being hit") and produces a snapshot capturing the
argument (`value=7`) and return (`49`); a sibling route-handler
breakpoint passed as a same-app control, and the endpoint response was
unchanged.
## By submitting this pull request, I confirm that my contribution is
made under the terms of the Apache 2.0 license.1 parent 0d1bda1 commit f2c33a6
2 files changed
Lines changed: 147 additions & 31 deletions
File tree
- aws-opentelemetry-distro
- src/amazon/opentelemetry/distro/debugger
- tests/amazon/opentelemetry/distro/debugger
Lines changed: 67 additions & 31 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1170 | 1170 | | |
1171 | 1171 | | |
1172 | 1172 | | |
1173 | | - | |
1174 | | - | |
1175 | | - | |
1176 | | - | |
1177 | | - | |
| 1173 | + | |
| 1174 | + | |
| 1175 | + | |
| 1176 | + | |
| 1177 | + | |
| 1178 | + | |
| 1179 | + | |
| 1180 | + | |
| 1181 | + | |
| 1182 | + | |
1178 | 1183 | | |
1179 | 1184 | | |
1180 | 1185 | | |
1181 | 1186 | | |
1182 | 1187 | | |
1183 | 1188 | | |
1184 | 1189 | | |
1185 | | - | |
1186 | | - | |
1187 | | - | |
1188 | | - | |
| 1190 | + | |
| 1191 | + | |
| 1192 | + | |
| 1193 | + | |
| 1194 | + | |
| 1195 | + | |
| 1196 | + | |
| 1197 | + | |
| 1198 | + | |
| 1199 | + | |
| 1200 | + | |
| 1201 | + | |
| 1202 | + | |
| 1203 | + | |
| 1204 | + | |
| 1205 | + | |
1189 | 1206 | | |
1190 | | - | |
1191 | | - | |
1192 | | - | |
1193 | | - | |
1194 | | - | |
1195 | | - | |
| 1207 | + | |
| 1208 | + | |
| 1209 | + | |
| 1210 | + | |
| 1211 | + | |
| 1212 | + | |
| 1213 | + | |
| 1214 | + | |
| 1215 | + | |
| 1216 | + | |
| 1217 | + | |
| 1218 | + | |
| 1219 | + | |
| 1220 | + | |
| 1221 | + | |
| 1222 | + | |
| 1223 | + | |
| 1224 | + | |
1196 | 1225 | | |
1197 | 1226 | | |
1198 | 1227 | | |
| |||
1201 | 1230 | | |
1202 | 1231 | | |
1203 | 1232 | | |
1204 | | - | |
1205 | | - | |
1206 | | - | |
| 1233 | + | |
| 1234 | + | |
| 1235 | + | |
1207 | 1236 | | |
1208 | 1237 | | |
1209 | 1238 | | |
1210 | 1239 | | |
1211 | 1240 | | |
1212 | 1241 | | |
1213 | 1242 | | |
1214 | | - | |
| 1243 | + | |
1215 | 1244 | | |
1216 | 1245 | | |
1217 | 1246 | | |
| |||
1223 | 1252 | | |
1224 | 1253 | | |
1225 | 1254 | | |
| 1255 | + | |
| 1256 | + | |
1226 | 1257 | | |
1227 | 1258 | | |
1228 | 1259 | | |
1229 | 1260 | | |
1230 | 1261 | | |
1231 | 1262 | | |
1232 | | - | |
1233 | | - | |
| 1263 | + | |
| 1264 | + | |
| 1265 | + | |
| 1266 | + | |
| 1267 | + | |
| 1268 | + | |
| 1269 | + | |
| 1270 | + | |
| 1271 | + | |
| 1272 | + | |
| 1273 | + | |
| 1274 | + | |
| 1275 | + | |
| 1276 | + | |
1234 | 1277 | | |
1235 | | - | |
1236 | | - | |
| 1278 | + | |
| 1279 | + | |
1237 | 1280 | | |
1238 | | - | |
| 1281 | + | |
1239 | 1282 | | |
1240 | 1283 | | |
1241 | 1284 | | |
1242 | | - | |
1243 | | - | |
1244 | | - | |
1245 | | - | |
1246 | | - | |
1247 | | - | |
1248 | | - | |
1249 | 1285 | | |
1250 | 1286 | | |
1251 | 1287 | | |
| |||
Lines changed: 80 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
164 | 164 | | |
165 | 165 | | |
166 | 166 | | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
167 | 247 | | |
168 | 248 | | |
169 | 249 | | |
| |||
0 commit comments