|
12 | 12 | # See the License for the specific language governing permissions and |
13 | 13 | # limitations under the License. |
14 | 14 |
|
| 15 | +import fnmatch |
15 | 16 | import os |
16 | 17 | import sys |
17 | 18 | import logging |
@@ -1267,19 +1268,50 @@ def _process_module_configuration(): |
1267 | 1268 | _raise_configuration_error(section) |
1268 | 1269 |
|
1269 | 1270 |
|
| 1271 | +def _module_function_glob(module, object_path): |
| 1272 | + """Match functions and class methods in a module to file globbing syntax.""" |
| 1273 | + if not any([c in object_path for c in {"*", "?", "["}]): # Identify globbing patterns |
| 1274 | + return (object_path,) # Returned value must be iterable |
| 1275 | + else: |
| 1276 | + # Gather module functions |
| 1277 | + try: |
| 1278 | + available_functions = {k: v for k, v in module.__dict__.items() if callable(v) and not isinstance(v, type)} |
| 1279 | + except Exception: |
| 1280 | + # Default to empty dict if no functions available |
| 1281 | + available_functions = dict() |
| 1282 | + |
| 1283 | + # Gather module classes and methods |
| 1284 | + try: |
| 1285 | + available_classes = {k: v for k, v in module.__dict__.items() if isinstance(v, type)} |
| 1286 | + for cls in available_classes: |
| 1287 | + try: |
| 1288 | + # Skip adding individual class's methods on failure |
| 1289 | + available_functions.update({"%s.%s" % (cls, k): v for k, v in available_classes.get(cls).__dict__.items() if callable(v) and not isinstance(v, type)}) |
| 1290 | + except Exception: |
| 1291 | + pass |
| 1292 | + except Exception: |
| 1293 | + # Skip adding all class methods on failure |
| 1294 | + pass |
| 1295 | + |
| 1296 | + # Under the hood uses fnmatch, which uses os.path.normcase |
| 1297 | + # On windows this would cause issues with case insensitivity, |
| 1298 | + # but on all other operating systems there should be no issues. |
| 1299 | + return fnmatch.filter(available_functions, object_path) |
| 1300 | + |
| 1301 | + |
1270 | 1302 | # Setup wsgi application wrapper defined in configuration file. |
1271 | 1303 |
|
1272 | 1304 |
|
1273 | 1305 | def _wsgi_application_import_hook(object_path, application): |
1274 | 1306 | def _instrument(target): |
1275 | | - _logger.debug( |
1276 | | - "wrap wsgi-application %s" % ((target, object_path, application),) |
1277 | | - ) |
1278 | | - |
1279 | 1307 | try: |
1280 | | - newrelic.api.wsgi_application.wrap_wsgi_application( |
1281 | | - target, object_path, application |
1282 | | - ) |
| 1308 | + for func in _module_function_glob(target, object_path): |
| 1309 | + _logger.debug( |
| 1310 | + "wrap wsgi-application %s" % ((target, func, application),) |
| 1311 | + ) |
| 1312 | + newrelic.api.wsgi_application.wrap_wsgi_application( |
| 1313 | + target, func, application |
| 1314 | + ) |
1283 | 1315 | except Exception: |
1284 | 1316 | _raise_instrumentation_error("wsgi-application", locals()) |
1285 | 1317 |
|
@@ -1327,15 +1359,15 @@ def _process_wsgi_application_configuration(): |
1327 | 1359 |
|
1328 | 1360 | def _background_task_import_hook(object_path, application, name, group): |
1329 | 1361 | def _instrument(target): |
1330 | | - _logger.debug( |
1331 | | - "wrap background-task %s" |
1332 | | - % ((target, object_path, application, name, group),) |
1333 | | - ) |
1334 | | - |
1335 | 1362 | try: |
1336 | | - newrelic.api.background_task.wrap_background_task( |
1337 | | - target, object_path, application, name, group |
1338 | | - ) |
| 1363 | + for func in _module_function_glob(target, object_path): |
| 1364 | + _logger.debug( |
| 1365 | + "wrap background-task %s" |
| 1366 | + % ((target, func, application, name, group),) |
| 1367 | + ) |
| 1368 | + newrelic.api.background_task.wrap_background_task( |
| 1369 | + target, func, application, name, group |
| 1370 | + ) |
1339 | 1371 | except Exception: |
1340 | 1372 | _raise_instrumentation_error("background-task", locals()) |
1341 | 1373 |
|
@@ -1394,10 +1426,10 @@ def _process_background_task_configuration(): |
1394 | 1426 |
|
1395 | 1427 | def _database_trace_import_hook(object_path, sql): |
1396 | 1428 | def _instrument(target): |
1397 | | - _logger.debug("wrap database-trace %s" % ((target, object_path, sql),)) |
1398 | | - |
1399 | 1429 | try: |
1400 | | - newrelic.api.database_trace.wrap_database_trace(target, object_path, sql) |
| 1430 | + for func in _module_function_glob(target, object_path): |
| 1431 | + _logger.debug("wrap database-trace %s" % ((target, func, sql),)) |
| 1432 | + newrelic.api.database_trace.wrap_database_trace(target, func, sql) |
1401 | 1433 | except Exception: |
1402 | 1434 | _raise_instrumentation_error("database-trace", locals()) |
1403 | 1435 |
|
@@ -1444,14 +1476,14 @@ def _process_database_trace_configuration(): |
1444 | 1476 |
|
1445 | 1477 | def _external_trace_import_hook(object_path, library, url, method): |
1446 | 1478 | def _instrument(target): |
1447 | | - _logger.debug( |
1448 | | - "wrap external-trace %s" % ((target, object_path, library, url, method),) |
1449 | | - ) |
1450 | | - |
1451 | 1479 | try: |
1452 | | - newrelic.api.external_trace.wrap_external_trace( |
1453 | | - target, object_path, library, url, method |
1454 | | - ) |
| 1480 | + for func in _module_function_glob(target, object_path): |
| 1481 | + _logger.debug( |
| 1482 | + "wrap external-trace %s" % ((target, func, library, url, method),) |
| 1483 | + ) |
| 1484 | + newrelic.api.external_trace.wrap_external_trace( |
| 1485 | + target, func, library, url, method |
| 1486 | + ) |
1455 | 1487 | except Exception: |
1456 | 1488 | _raise_instrumentation_error("external-trace", locals()) |
1457 | 1489 |
|
@@ -1512,15 +1544,15 @@ def _function_trace_import_hook( |
1512 | 1544 | object_path, name, group, label, params, terminal, rollup |
1513 | 1545 | ): |
1514 | 1546 | def _instrument(target): |
1515 | | - _logger.debug( |
1516 | | - "wrap function-trace %s" |
1517 | | - % ((target, object_path, name, group, label, params, terminal, rollup),) |
1518 | | - ) |
1519 | | - |
1520 | 1547 | try: |
1521 | | - newrelic.api.function_trace.wrap_function_trace( |
1522 | | - target, object_path, name, group, label, params, terminal, rollup |
1523 | | - ) |
| 1548 | + for func in _module_function_glob(target, object_path): |
| 1549 | + _logger.debug( |
| 1550 | + "wrap function-trace %s" |
| 1551 | + % ((target, func, name, group, label, params, terminal, rollup),) |
| 1552 | + ) |
| 1553 | + newrelic.api.function_trace.wrap_function_trace( |
| 1554 | + target, func, name, group, label, params, terminal, rollup |
| 1555 | + ) |
1524 | 1556 | except Exception: |
1525 | 1557 | _raise_instrumentation_error("function-trace", locals()) |
1526 | 1558 |
|
@@ -1588,12 +1620,12 @@ def _process_function_trace_configuration(): |
1588 | 1620 |
|
1589 | 1621 | def _generator_trace_import_hook(object_path, name, group): |
1590 | 1622 | def _instrument(target): |
1591 | | - _logger.debug("wrap generator-trace %s" % ((target, object_path, name, group),)) |
1592 | | - |
1593 | 1623 | try: |
1594 | | - newrelic.api.generator_trace.wrap_generator_trace( |
1595 | | - target, object_path, name, group |
1596 | | - ) |
| 1624 | + for func in _module_function_glob(target, object_path): |
| 1625 | + _logger.debug("wrap generator-trace %s" % ((target, func, name, group),)) |
| 1626 | + newrelic.api.generator_trace.wrap_generator_trace( |
| 1627 | + target, func, name, group |
| 1628 | + ) |
1597 | 1629 | except Exception: |
1598 | 1630 | _raise_instrumentation_error("generator-trace", locals()) |
1599 | 1631 |
|
@@ -1648,14 +1680,14 @@ def _process_generator_trace_configuration(): |
1648 | 1680 |
|
1649 | 1681 | def _profile_trace_import_hook(object_path, name, group, depth): |
1650 | 1682 | def _instrument(target): |
1651 | | - _logger.debug( |
1652 | | - "wrap profile-trace %s" % ((target, object_path, name, group, depth),) |
1653 | | - ) |
1654 | | - |
1655 | 1683 | try: |
1656 | | - newrelic.api.profile_trace.wrap_profile_trace( |
1657 | | - target, object_path, name, group, depth=depth |
1658 | | - ) |
| 1684 | + for func in _module_function_glob(target, object_path): |
| 1685 | + _logger.debug( |
| 1686 | + "wrap profile-trace %s" % ((target, func, name, group, depth),) |
| 1687 | + ) |
| 1688 | + newrelic.api.profile_trace.wrap_profile_trace( |
| 1689 | + target, func, name, group, depth=depth |
| 1690 | + ) |
1659 | 1691 | except Exception: |
1660 | 1692 | _raise_instrumentation_error("profile-trace", locals()) |
1661 | 1693 |
|
@@ -1714,12 +1746,12 @@ def _process_profile_trace_configuration(): |
1714 | 1746 |
|
1715 | 1747 | def _memcache_trace_import_hook(object_path, command): |
1716 | 1748 | def _instrument(target): |
1717 | | - _logger.debug("wrap memcache-trace %s" % ((target, object_path, command),)) |
1718 | | - |
1719 | 1749 | try: |
1720 | | - newrelic.api.memcache_trace.wrap_memcache_trace( |
1721 | | - target, object_path, command |
1722 | | - ) |
| 1750 | + for func in _module_function_glob(target, object_path): |
| 1751 | + _logger.debug("wrap memcache-trace %s" % ((target, func, command),)) |
| 1752 | + newrelic.api.memcache_trace.wrap_memcache_trace( |
| 1753 | + target, func, command |
| 1754 | + ) |
1723 | 1755 | except Exception: |
1724 | 1756 | _raise_instrumentation_error("memcache-trace", locals()) |
1725 | 1757 |
|
@@ -1768,14 +1800,14 @@ def _process_memcache_trace_configuration(): |
1768 | 1800 |
|
1769 | 1801 | def _transaction_name_import_hook(object_path, name, group, priority): |
1770 | 1802 | def _instrument(target): |
1771 | | - _logger.debug( |
1772 | | - "wrap transaction-name %s" % ((target, object_path, name, group, priority),) |
1773 | | - ) |
1774 | | - |
1775 | 1803 | try: |
1776 | | - newrelic.api.transaction_name.wrap_transaction_name( |
1777 | | - target, object_path, name, group, priority |
1778 | | - ) |
| 1804 | + for func in _module_function_glob(target, object_path): |
| 1805 | + _logger.debug( |
| 1806 | + "wrap transaction-name %s" % ((target, func, name, group, priority),) |
| 1807 | + ) |
| 1808 | + newrelic.api.transaction_name.wrap_transaction_name( |
| 1809 | + target, func, name, group, priority |
| 1810 | + ) |
1779 | 1811 | except Exception: |
1780 | 1812 | _raise_instrumentation_error("transaction-name", locals()) |
1781 | 1813 |
|
@@ -1837,12 +1869,12 @@ def _process_transaction_name_configuration(): |
1837 | 1869 |
|
1838 | 1870 | def _error_trace_import_hook(object_path, ignore, expected): |
1839 | 1871 | def _instrument(target): |
1840 | | - _logger.debug("wrap error-trace %s" % ((target, object_path, ignore, expected),)) |
1841 | | - |
1842 | 1872 | try: |
1843 | | - newrelic.api.error_trace.wrap_error_trace( |
1844 | | - target, object_path, ignore, expected, None |
1845 | | - ) |
| 1873 | + for func in _module_function_glob(target, object_path): |
| 1874 | + _logger.debug("wrap error-trace %s" % ((target, func, ignore, expected),)) |
| 1875 | + newrelic.api.error_trace.wrap_error_trace( |
| 1876 | + target, func, ignore, expected, None |
| 1877 | + ) |
1846 | 1878 | except Exception: |
1847 | 1879 | _raise_instrumentation_error("error-trace", locals()) |
1848 | 1880 |
|
@@ -2009,15 +2041,15 @@ def _setup_data_source(): |
2009 | 2041 |
|
2010 | 2042 | def _function_profile_import_hook(object_path, filename, delay, checkpoint): |
2011 | 2043 | def _instrument(target): |
2012 | | - _logger.debug( |
2013 | | - "wrap function-profile %s" |
2014 | | - % ((target, object_path, filename, delay, checkpoint),) |
2015 | | - ) |
2016 | | - |
2017 | 2044 | try: |
2018 | | - newrelic.api.function_profile.wrap_function_profile( |
2019 | | - target, object_path, filename, delay, checkpoint |
2020 | | - ) |
| 2045 | + for func in _module_function_glob(target, object_path): |
| 2046 | + _logger.debug( |
| 2047 | + "wrap function-profile %s" |
| 2048 | + % ((target, func, filename, delay, checkpoint),) |
| 2049 | + ) |
| 2050 | + newrelic.api.function_profile.wrap_function_profile( |
| 2051 | + target, func, filename, delay, checkpoint |
| 2052 | + ) |
2021 | 2053 | except Exception: |
2022 | 2054 | _raise_instrumentation_error("function-profile", locals()) |
2023 | 2055 |
|
|
0 commit comments