openmodule 14.0.1__tar.gz → 14.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. {openmodule-14.0.1 → openmodule-14.0.2}/ChangeLog +5 -7
  2. {openmodule-14.0.1/openmodule.egg-info → openmodule-14.0.2}/PKG-INFO +1 -1
  3. {openmodule-14.0.1 → openmodule-14.0.2}/docs/sentry.md +6 -0
  4. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/dispatcher.py +6 -4
  5. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/rpc/server.py +14 -11
  6. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/sentry.py +56 -8
  7. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/io.py +17 -16
  8. {openmodule-14.0.1 → openmodule-14.0.2/openmodule.egg-info}/PKG-INFO +1 -1
  9. openmodule-14.0.2/openmodule.egg-info/pbr.json +1 -0
  10. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule.egg-info/requires.txt +1 -1
  11. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/sentry.py +12 -10
  12. {openmodule-14.0.1 → openmodule-14.0.2}/requirements.txt +1 -1
  13. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_sentry.py +121 -9
  14. openmodule-14.0.1/openmodule.egg-info/pbr.json +0 -1
  15. {openmodule-14.0.1 → openmodule-14.0.2}/.gitlab-ci.yml +0 -0
  16. {openmodule-14.0.1 → openmodule-14.0.2}/AUTHORS +0 -0
  17. {openmodule-14.0.1 → openmodule-14.0.2}/LICENSE +0 -0
  18. {openmodule-14.0.1 → openmodule-14.0.2}/README.md +0 -0
  19. {openmodule-14.0.1 → openmodule-14.0.2}/docs/access_service.md +0 -0
  20. {openmodule-14.0.1 → openmodule-14.0.2}/docs/anonymization.md +0 -0
  21. {openmodule-14.0.1 → openmodule-14.0.2}/docs/cleanup.md +0 -0
  22. {openmodule-14.0.1 → openmodule-14.0.2}/docs/coding_standard.md +0 -0
  23. {openmodule-14.0.1 → openmodule-14.0.2}/docs/commands.md +0 -0
  24. {openmodule-14.0.1 → openmodule-14.0.2}/docs/connection_status_listener.md +0 -0
  25. {openmodule-14.0.1 → openmodule-14.0.2}/docs/csv_export.md +0 -0
  26. {openmodule-14.0.1 → openmodule-14.0.2}/docs/database.md +0 -0
  27. {openmodule-14.0.1 → openmodule-14.0.2}/docs/deprecated.md +0 -0
  28. {openmodule-14.0.1 → openmodule-14.0.2}/docs/deprecated_code/README.md +0 -0
  29. {openmodule-14.0.1 → openmodule-14.0.2}/docs/deprecated_code/access_service/openmodule/models/access_service.py +0 -0
  30. {openmodule-14.0.1 → openmodule-14.0.2}/docs/deprecated_code/access_service/openmodule/utils/access_service.py +0 -0
  31. {openmodule-14.0.1 → openmodule-14.0.2}/docs/deprecated_code/access_service/openmodule_test/access_service.py +0 -0
  32. {openmodule-14.0.1 → openmodule-14.0.2}/docs/deprecated_code/access_service/tests/test_utils_access_service.py +0 -0
  33. {openmodule-14.0.1 → openmodule-14.0.2}/docs/deprecated_code/api/openmodule/utils/api.py +0 -0
  34. {openmodule-14.0.1 → openmodule-14.0.2}/docs/deprecated_code/api/openmodule_test/api.py +0 -0
  35. {openmodule-14.0.1 → openmodule-14.0.2}/docs/deprecated_code/api/tests/test_utils_api.py +0 -0
  36. {openmodule-14.0.1 → openmodule-14.0.2}/docs/deprecated_code/package_reader/openmodule/utils/package_reader.py +0 -0
  37. {openmodule-14.0.1 → openmodule-14.0.2}/docs/deprecated_code/package_reader/openmodule_test/fake_package_creator.py +0 -0
  38. {openmodule-14.0.1 → openmodule-14.0.2}/docs/deprecated_code/package_reader/tests/test_package_reader.py +0 -0
  39. {openmodule-14.0.1 → openmodule-14.0.2}/docs/event_sending.md +0 -0
  40. {openmodule-14.0.1 → openmodule-14.0.2}/docs/getting_started.md +0 -0
  41. {openmodule-14.0.1 → openmodule-14.0.2}/docs/health.md +0 -0
  42. {openmodule-14.0.1 → openmodule-14.0.2}/docs/images/broker.drawio.png +0 -0
  43. {openmodule-14.0.1 → openmodule-14.0.2}/docs/known_issues.md +0 -0
  44. {openmodule-14.0.1 → openmodule-14.0.2}/docs/migrations.md +0 -0
  45. {openmodule-14.0.1 → openmodule-14.0.2}/docs/package_reader.md +0 -0
  46. {openmodule-14.0.1 → openmodule-14.0.2}/docs/rpc.md +0 -0
  47. {openmodule-14.0.1 → openmodule-14.0.2}/docs/settings.md +0 -0
  48. {openmodule-14.0.1 → openmodule-14.0.2}/docs/settings_provider.md +0 -0
  49. {openmodule-14.0.1 → openmodule-14.0.2}/docs/testing.md +0 -0
  50. {openmodule-14.0.1 → openmodule-14.0.2}/docs/translation.md +0 -0
  51. {openmodule-14.0.1 → openmodule-14.0.2}/docs/utils.md +0 -0
  52. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/__init__.py +0 -0
  53. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/alert.py +0 -0
  54. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/config.py +0 -0
  55. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/connection_status.py +0 -0
  56. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/core.py +0 -0
  57. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/database/custom_types.py +0 -0
  58. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/database/database.py +0 -0
  59. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/database/env.py +0 -0
  60. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/database/migration.py +0 -0
  61. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/health.py +0 -0
  62. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/logging.py +0 -0
  63. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/messaging.py +0 -0
  64. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/models/__init__.py +0 -0
  65. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/models/access_service.py +0 -0
  66. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/models/alert.py +0 -0
  67. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/models/base.py +0 -0
  68. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/models/io.py +0 -0
  69. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/models/kv_store.py +0 -0
  70. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/models/presence.py +0 -0
  71. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/models/privacy.py +0 -0
  72. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/models/rpc.py +0 -0
  73. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/models/settings.py +0 -0
  74. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/models/validation.py +0 -0
  75. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/models/vehicle.py +0 -0
  76. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/rpc/__init__.py +0 -0
  77. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/rpc/client.py +0 -0
  78. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/rpc/common.py +0 -0
  79. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/threading.py +0 -0
  80. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/__init__.py +0 -0
  81. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/access_service.py +0 -0
  82. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/charset.py +0 -0
  83. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/cleanup.py +0 -0
  84. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/csv_export.py +0 -0
  85. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/databox.py +0 -0
  86. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/db_helper.py +0 -0
  87. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/eventlog.py +0 -0
  88. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/kv_store.py +0 -0
  89. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/matching.py +0 -0
  90. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/misc_functions.py +0 -0
  91. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/package_reader.py +0 -0
  92. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/presence.py +0 -0
  93. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/schema.py +0 -0
  94. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/settings.py +0 -0
  95. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/translation.py +0 -0
  96. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule/utils/validation.py +0 -0
  97. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule.egg-info/SOURCES.txt +0 -0
  98. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule.egg-info/dependency_links.txt +0 -0
  99. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule.egg-info/not-zip-safe +0 -0
  100. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule.egg-info/top_level.txt +0 -0
  101. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_commands/__init__.py +0 -0
  102. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_commands/setup.cfg +0 -0
  103. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_commands/setup.py +0 -0
  104. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_commands/translate.py +0 -0
  105. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/__init__.py +0 -0
  106. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/alert.py +0 -0
  107. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/connection_status.py +0 -0
  108. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/core.py +0 -0
  109. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/database.py +0 -0
  110. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/eventlistener.py +0 -0
  111. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/files.py +0 -0
  112. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/gate.py +0 -0
  113. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/health.py +0 -0
  114. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/interrupt.py +0 -0
  115. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/io_simulator.py +0 -0
  116. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/package_reader.py +0 -0
  117. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/presence.py +0 -0
  118. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/requirements.txt +0 -0
  119. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/rpc.py +0 -0
  120. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/settings.py +0 -0
  121. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/setup.cfg +0 -0
  122. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/setup.py +0 -0
  123. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/utils.py +0 -0
  124. {openmodule-14.0.1 → openmodule-14.0.2}/openmodule_test/zeromq.py +0 -0
  125. {openmodule-14.0.1 → openmodule-14.0.2}/setup.cfg +0 -0
  126. {openmodule-14.0.1 → openmodule-14.0.2}/setup.py +0 -0
  127. {openmodule-14.0.1 → openmodule-14.0.2}/test-requirements.txt +0 -0
  128. {openmodule-14.0.1 → openmodule-14.0.2}/tests/__init__.py +0 -0
  129. {openmodule-14.0.1 → openmodule-14.0.2}/tests/config.py +0 -0
  130. {openmodule-14.0.1 → openmodule-14.0.2}/tests/database_models_migration.py +0 -0
  131. {openmodule-14.0.1 → openmodule-14.0.2}/tests/database_models_test.py +0 -0
  132. {openmodule-14.0.1 → openmodule-14.0.2}/tests/invalid_database/alembic/README +0 -0
  133. {openmodule-14.0.1 → openmodule-14.0.2}/tests/invalid_database/alembic/__init__.py +0 -0
  134. {openmodule-14.0.1 → openmodule-14.0.2}/tests/invalid_database/alembic/env.py +0 -0
  135. {openmodule-14.0.1 → openmodule-14.0.2}/tests/invalid_database/alembic/script.py.mako +0 -0
  136. {openmodule-14.0.1 → openmodule-14.0.2}/tests/invalid_database/alembic/versions/ff26e54332f9_datetime_models.py +0 -0
  137. {openmodule-14.0.1 → openmodule-14.0.2}/tests/invalid_database/alembic.ini +0 -0
  138. {openmodule-14.0.1 → openmodule-14.0.2}/tests/invalid_database/makemigration.sh +0 -0
  139. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_double_column_delete_error/alembic/__init__.py +0 -0
  140. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_double_column_delete_error/alembic/env.py +0 -0
  141. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_double_column_delete_error/alembic/script.py.mako +0 -0
  142. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_double_column_delete_error/alembic/versions/812a3e5b8517_initial.py +0 -0
  143. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_double_column_delete_error/alembic/versions/a7ea100a784f_key_error.py +0 -0
  144. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_double_column_delete_error/alembic.ini +0 -0
  145. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_double_column_delete_error/makemigration.sh +0 -0
  146. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_no_such_table_error/alembic/__init__.py +0 -0
  147. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_no_such_table_error/alembic/env.py +0 -0
  148. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_no_such_table_error/alembic/script.py.mako +0 -0
  149. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_no_such_table_error/alembic/versions/812a3e5b8517_initial.py +0 -0
  150. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_no_such_table_error/alembic/versions/a7ea100a784f_no_such_table_error.py +0 -0
  151. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_no_such_table_error/alembic.ini +0 -0
  152. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_no_such_table_error/makemigration.sh +0 -0
  153. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_test_database/__init__.py +0 -0
  154. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_test_database/alembic/__init__.py +0 -0
  155. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_test_database/alembic/env.py +0 -0
  156. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_test_database/alembic/script.py.mako +0 -0
  157. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_test_database/alembic/versions/19789aa5361c_initial.py +0 -0
  158. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_test_database/alembic/versions/19d887929ae7_alter.py +0 -0
  159. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_test_database/alembic/versions/__init__.py +0 -0
  160. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_test_database/alembic.ini +0 -0
  161. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_test_database/alembic_migration_test_database.sqlite3 +0 -0
  162. {openmodule-14.0.1 → openmodule-14.0.2}/tests/migration_test_database/makemigration.sh +0 -0
  163. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/configs/config.py +0 -0
  164. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/configs/test_config.py +0 -0
  165. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/configs/test_config_1.py +0 -0
  166. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/standard_schemes/DEFAULT-10.yml +0 -0
  167. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/standard_schemes/DEFAULT-20.yml +0 -0
  168. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/standard_schemes/LEGACY-0.yml +0 -0
  169. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/translation/locale/de/LC_MESSAGES/translation.mo +0 -0
  170. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/translation/locale/de/LC_MESSAGES/translation.po +0 -0
  171. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/translation/locale/en/LC_MESSAGES/translation.mo +0 -0
  172. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/translation/locale/en/LC_MESSAGES/translation.po +0 -0
  173. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/translation/locale/translation.pot +0 -0
  174. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/translation/translate.sh +0 -0
  175. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/utils_matching/A-10.yml +0 -0
  176. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/utils_matching/A-20.yml +0 -0
  177. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/utils_matching/DEFAULT-10.yml +0 -0
  178. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/utils_matching/DEFAULT-20.yml +0 -0
  179. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/utils_matching/DEFAULT-30.yml +0 -0
  180. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/utils_matching/LEGACY-0.yml +0 -0
  181. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/utils_matching/TEST-10.yml +0 -0
  182. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/utils_matching/TEST-20.yml +0 -0
  183. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/utils_matching/TEST-30.yml +0 -0
  184. {openmodule-14.0.1 → openmodule-14.0.2}/tests/resources/utils_matching/TEST-40.yml +0 -0
  185. {openmodule-14.0.1 → openmodule-14.0.2}/tests/sentry_main.py +0 -0
  186. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_access_service_database/alembic/__init__.py +0 -0
  187. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_access_service_database/alembic/env.py +0 -0
  188. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_access_service_database/alembic/script.py.mako +0 -0
  189. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_access_service_database/alembic/versions/7bd4fcd38fde_removed_nfc_and_pin.py +0 -0
  190. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_access_service_database/alembic/versions/9ca98a2e5674_added_parksettings_id.py +0 -0
  191. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_access_service_database/alembic/versions/c821971f9230_initial.py +0 -0
  192. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_access_service_database/alembic.ini +0 -0
  193. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_access_service_database/makemigration.sh +0 -0
  194. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_alembic_migrations.py +0 -0
  195. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_alert.py +0 -0
  196. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_checks.py +0 -0
  197. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_config.py +0 -0
  198. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_connection_status.py +0 -0
  199. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_core.py +0 -0
  200. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_database/alembic/__init__.py +0 -0
  201. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_database/alembic/env.py +0 -0
  202. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_database/alembic/script.py.mako +0 -0
  203. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_database/alembic/versions/32b8c728abbf_initial.py +0 -0
  204. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_database/alembic.ini +0 -0
  205. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_database/makemigration.sh +0 -0
  206. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_database.py +0 -0
  207. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_dispatcher.py +0 -0
  208. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_health.py +0 -0
  209. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_interrupt.py +0 -0
  210. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_io_listen.py +0 -0
  211. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_kv_store_database/alembic/__init__.py +0 -0
  212. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_kv_store_database/alembic/env.py +0 -0
  213. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_kv_store_database/alembic/script.py.mako +0 -0
  214. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_kv_store_database/alembic/versions/9c5c944221f4_deprecated_kv_entry_example.py +0 -0
  215. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_kv_store_database/alembic/versions/c55a69026a25_initial.py +0 -0
  216. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_kv_store_database/alembic.ini +0 -0
  217. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_kv_store_database/makemigration.sh +0 -0
  218. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_kv_store_multiple_database/alembic/README +0 -0
  219. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_kv_store_multiple_database/alembic/__init__.py +0 -0
  220. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_kv_store_multiple_database/alembic/env.py +0 -0
  221. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_kv_store_multiple_database/alembic/script.py.mako +0 -0
  222. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_kv_store_multiple_database/alembic/versions/cdb3214131a9_initial.py +0 -0
  223. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_kv_store_multiple_database/alembic.ini +0 -0
  224. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_kv_store_multiple_database/makemigration.sh +0 -0
  225. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_logging.py +0 -0
  226. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_messaging.py +0 -0
  227. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_mockrpcclient.py +0 -0
  228. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_model.py +0 -0
  229. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_rpc.py +0 -0
  230. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_schema.py +0 -0
  231. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_test_alert.py +0 -0
  232. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_test_gate.py +0 -0
  233. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_test_zeromq.py +0 -0
  234. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_access_service.py +0 -0
  235. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_charset.py +0 -0
  236. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_cleanup.py +0 -0
  237. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_csv_export.py +0 -0
  238. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_databox.py +0 -0
  239. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_eventlog.py +0 -0
  240. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_kv_store.py +0 -0
  241. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_kv_store_multiple.py +0 -0
  242. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_matching.py +0 -0
  243. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_misc_functions.py +0 -0
  244. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_package_reader.py +0 -0
  245. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_presence.py +0 -0
  246. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_settings.py +0 -0
  247. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_validation.py +0 -0
  248. {openmodule-14.0.1 → openmodule-14.0.2}/tests/test_utils_vehicle.py +0 -0
  249. {openmodule-14.0.1 → openmodule-14.0.2}/tox.ini +0 -0
@@ -1,6 +1,11 @@
1
1
  CHANGES
2
2
  =======
3
3
 
4
+ v14.0.2
5
+ -------
6
+
7
+ * Sentry improvements
8
+
4
9
  v14.0.1
5
10
  -------
6
11
 
@@ -162,7 +167,6 @@ v12.0.0.rc0
162
167
  * made gate\_control/day\_mode have no scope
163
168
  * schedule exports utility
164
169
  * SettingsProvider docs
165
- * SettingsProvider docs
166
170
 
167
171
  v11.1.1
168
172
  -------
@@ -202,9 +206,3 @@ v10.0.5
202
206
  v10.0.4
203
207
  -------
204
208
 
205
- * Improvements for backend and package reader
206
-
207
- v10.0.3
208
- -------
209
-
210
- * added freezegun and fakeredis to openmodule requirements
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openmodule
3
- Version: 14.0.1
3
+ Version: 14.0.2
4
4
  Summary: Libraries for developing the arivo openmodule
5
5
  Home-page: https://gitlab.com/arivo-public/device-python/openmodule.git
6
6
  Author: ARIVO
@@ -24,6 +24,10 @@ for your project that tells the SDK where to send the events. You can find the D
24
24
  * You can provide additional [sentry options](https://docs.sentry.io/platforms/python/configuration/options/) as keyword
25
25
  arguments to the `init_openmodule` function (`server_name` and `environment` cannot be overriden).
26
26
  * the `extras` keyword argument can be used to provide additional data to the Sentry SDK
27
+ * the `topics_to_ignore` keyword argument can be used to provide a list of topics that should not be captured by Sentry.
28
+ You should also check that no trace will be started for every message from that topic. (defaults to `["io"]`)
29
+ * the `functions_to_ignore` keyword argument can be used to provide a list of span names (auto generated for functions)
30
+ that should not be captured by Sentry. (defaults to `[]`)
27
31
 
28
32
  ```python
29
33
  def main():
@@ -75,6 +79,8 @@ with sentry.trace("my_block"):
75
79
 
76
80
  You can add context to the current transaction using one of the following methods:
77
81
 
82
+ * Adding the data as kwargs to the `sentry.trace` function.
83
+ * `sentry.trace("my_block", extras={"key": "value"}, tags={"key": "value"}, context={"key": "value"})`
78
84
  * `sentry_sdk.set_tag(key: str, value: str)`: Adds
79
85
  a [tag](https://docs.sentry.io/platforms/python/enriching-events/tags/) to the current transaction.
80
86
  * `sentry_sdk.set_tags(**key_value_pairs: str)`:
@@ -44,7 +44,7 @@ class Listener:
44
44
  def __init__(self, message_class: Type[ZMQMessage], type: Optional[str], filter: Optional[Callable],
45
45
  handler: Callable):
46
46
  self.filter = filter
47
- self.handler = handler
47
+ self.handler = sentry.trace(f"message_handler.{qualname_from_function(handler)}")(handler)
48
48
  self.type = type
49
49
  self.message_class = message_class
50
50
 
@@ -110,6 +110,7 @@ class MessageDispatcher:
110
110
  self.raise_validation_errors = raise_validation_errors
111
111
  self.raise_handler_errors = raise_handler_errors
112
112
  self.executor = executor or DummyExecutor()
113
+ self._new_transactions = not isinstance(self.executor, DummyExecutor)
113
114
  self._shutdown = False
114
115
  self._shutdown_lock = threading.Lock()
115
116
 
@@ -201,10 +202,12 @@ class MessageDispatcher:
201
202
  listeners = self.listeners.get(topic, [])
202
203
  for listener in listeners:
203
204
  if listener.matches(message):
205
+ message.update(sentry.get_trace_headers())
204
206
  self.executor.submit(self.execute, topic, listener, message)
205
207
 
206
208
  def execute(self, topic: str, listener: Listener, message: Dict):
207
- with sentry.continue_trace_zmq_message_process(topic, message):
209
+ with sentry.continue_trace_zmq_message_process(
210
+ topic, message, force_new_transaction=self._new_transactions):
208
211
  try:
209
212
  parsed_message = parse_obj_as(listener.message_class, message)
210
213
  except ValidationError as e:
@@ -214,8 +217,7 @@ class MessageDispatcher:
214
217
  self.log.exception("Invalid message received")
215
218
  else:
216
219
  try:
217
- with sentry.trace(f"message_handler.{qualname_from_function(listener.handler)}"):
218
- listener.handler(parsed_message)
220
+ listener.handler(parsed_message)
219
221
  except zmq.ContextTerminated:
220
222
  raise
221
223
  except Exception as e:
@@ -77,6 +77,7 @@ class RPCServer(object):
77
77
  self.thread = None
78
78
  self.resource = None
79
79
  self.executor = executor or DummyExecutor()
80
+ self._new_transactions = not isinstance(self.executor, DummyExecutor)
80
81
  # since zmq does prefix matching we keep a list of unique channel names here
81
82
  # so we do not log a warning "unknown handler" if our channel is a prefix of a different channel
82
83
  self.registered_channels = set()
@@ -129,7 +130,8 @@ class RPCServer(object):
129
130
 
130
131
  self.log.debug("register handler {}:{} -> {}".format(channel, type, handler))
131
132
  self.sub.subscribe(channel_to_request_topic(channel).encode("utf8"))
132
- self.handlers[(channel, type)] = HandlerEntry(request_class, response_class, handler)
133
+ traced_handler = sentry.trace(f"rpc_handler.{qualname_from_function(handler)}")(handler)
134
+ self.handlers[(channel, type)] = HandlerEntry(request_class, response_class, traced_handler)
133
135
  self.registered_channels = set(x[0] for x in self.handlers.keys())
134
136
  if register_schema:
135
137
  Schema.save_rpc(channel, type, request_class, response_class, handler)
@@ -194,15 +196,14 @@ class RPCServer(object):
194
196
  if settings.LOG_LEVEL != logging.DEBUG:
195
197
  self.log.info("received RPC channel: %s, type: %s", channel, message.type)
196
198
  try:
197
- with sentry.trace(f"rpc_handler.{qualname_from_function(handler.handler)}"):
198
- response = handler.handler(request, message)
199
- if isinstance(response, handler.response_class):
200
- # shortcut prevent serialization and de-serialization if the correct response
201
- # is already returned
202
- return self._response_to_dict(response)
203
- else:
204
- response = parse_obj_as(handler.response_class, response or {})
205
- return self._response_to_dict(response)
199
+ response = handler.handler(request, message)
200
+ if isinstance(response, handler.response_class):
201
+ # shortcut prevent serialization and de-serialization if the correct response
202
+ # is already returned
203
+ return self._response_to_dict(response)
204
+ else:
205
+ response = parse_obj_as(handler.response_class, response or {})
206
+ return self._response_to_dict(response)
206
207
  except Exception as e:
207
208
  self.log.exception("exception in handler {}:{}".format(channel, message.type))
208
209
  return {"status": RPCServerError.handler_error, "exception": str(e)}
@@ -211,7 +212,8 @@ class RPCServer(object):
211
212
  return None
212
213
 
213
214
  def _process_rpc_message(self, topic: str, message: dict):
214
- with sentry.continue_trace_zmq_message_process(topic, message):
215
+ with sentry.continue_trace_zmq_message_process(
216
+ topic, message, force_new_transaction=self._new_transactions):
215
217
  try:
216
218
  channel = self._channel_from_topic(topic)
217
219
 
@@ -262,6 +264,7 @@ class RPCServer(object):
262
264
  continue
263
265
  if self.running:
264
266
  # someone may have stopped our server while we were receiving a message
267
+ message.update(sentry.get_trace_headers())
265
268
  self.executor.submit(self._process_rpc_message, topic, message)
266
269
  except zmq.ContextTerminated:
267
270
  pass
@@ -5,13 +5,13 @@ import logging
5
5
  import os.path
6
6
  import time
7
7
  from contextlib import contextmanager
8
- from typing import Union, Callable, overload, Generator, Optional, Tuple, Any
8
+ from typing import Union, Callable, overload, Generator, Optional, Tuple, Any, List
9
9
 
10
10
  import orjson
11
11
  import requests
12
+ import sentry_sdk.integrations.logging
12
13
  import sentry_sdk.tracing
13
14
  import sentry_sdk.tracing_utils
14
- import sentry_sdk.integrations.logging
15
15
  import urllib3.exceptions
16
16
  from sentry_sdk.consts import EndpointType
17
17
  from sentry_sdk.envelope import Envelope
@@ -20,26 +20,37 @@ from sentry_sdk.utils import qualname_from_function
20
20
  from openmodule.config import settings
21
21
 
22
22
  _log = logging.getLogger("OmSentry")
23
+ _topics_to_ignore: List[str] = ["io"]
24
+ _functions_to_ignore: List[str] = ["message_handler.openmodule.utils.io.IoListener._on_io_message"]
25
+
23
26
 
27
+ @contextmanager
28
+ def noop_context():
29
+ yield
24
30
 
25
- def continue_trace_zmq_message_receive(topic: str, message: dict):
31
+
32
+ def continue_trace_zmq_message_receive(topic: str, message: dict, **kwargs):
26
33
  """
27
34
  Continues a sentry trace for a received zmq message. (If already in a transaction, it will create a scope instead)
28
35
  Our ZMQMessage class contains the baggage and sentry-trace fields required for this, so the dict must contain these.
29
36
  :param topic: The topic of the message (as received from the ZMQ socket and decoded)
30
37
  :param message: The ZMQMessage as a dict (as received from the ZMQ socket and json loaded)
31
38
  """
32
- return _continue_trace_zmq_message(topic, message, "topic.receive")
39
+ if topic in _topics_to_ignore:
40
+ return noop_context()
41
+ return _continue_trace_zmq_message(topic, message, "topic.receive", **kwargs)
33
42
 
34
43
 
35
- def continue_trace_zmq_message_process(topic: str, message: dict):
44
+ def continue_trace_zmq_message_process(topic: str, message: dict, **kwargs):
36
45
  """
37
46
  Continues a sentry trace for a zmq message executor. (If already in a transaction, it will create a scope instead)
38
47
  Our ZMQMessage class contains the baggage and sentry-trace fields required for this, so the dict must contain these.
39
48
  :param topic: The topic of the message (as received from the ZMQ socket and decoded)
40
49
  :param message: The ZMQMessage as a dict (as received from the ZMQ socket and json loaded)
41
50
  """
42
- return _continue_trace_zmq_message(topic, message, "topic.process")
51
+ if topic in _topics_to_ignore:
52
+ return noop_context()
53
+ return _continue_trace_zmq_message(topic, message, "topic.process", **kwargs)
43
54
 
44
55
 
45
56
  @overload # pragma: no cover
@@ -109,6 +120,14 @@ def get_baggage() -> Optional[str]:
109
120
  get_traceparent = sentry_sdk.get_traceparent
110
121
 
111
122
 
123
+ def get_trace_headers(empty_if_not_sampled: bool = False) -> dict:
124
+ if empty_if_not_sampled:
125
+ span = sentry_sdk.get_current_span()
126
+ if span and not span.sampled:
127
+ return {}
128
+ return {"sentry-trace": sentry_sdk.get_traceparent(), "baggage": sentry_sdk.get_baggage()}
129
+
130
+
112
131
  class _Trace:
113
132
  """
114
133
  Context manager for sentry tracing.
@@ -130,6 +149,20 @@ class _Trace:
130
149
  Otherwise, start a new span.
131
150
  If given a trace_headers dict, it will continue the trace with the given headers.
132
151
  """
152
+ if self.span_kwargs.get("name") in _functions_to_ignore:
153
+ yield
154
+ return
155
+
156
+ def set_context():
157
+ for key, value in extras.items():
158
+ sentry_sdk.set_extra(key, value)
159
+ sentry_sdk.set_tags(tags)
160
+ for key, value in contexts.items():
161
+ sentry_sdk.set_context(key, value)
162
+
163
+ extras = self.span_kwargs.pop("extras", {})
164
+ tags = self.span_kwargs.pop("tags", {})
165
+ contexts = self.span_kwargs.pop("contexts", {})
133
166
  span = sentry_sdk.get_current_span()
134
167
  if span is None or self.force_new_transaction:
135
168
  with sentry_sdk.isolation_scope():
@@ -139,12 +172,15 @@ class _Trace:
139
172
  with sentry_sdk.start_transaction(transaction=transaction, **self.span_kwargs) as transaction:
140
173
  if transaction:
141
174
  transaction.description = transaction.name
175
+ set_context()
142
176
  yield
143
177
  elif span.sampled:
144
178
  self.span_kwargs.pop("source", None)
145
179
  with sentry_sdk.start_span(**self.span_kwargs):
180
+ set_context()
146
181
  yield
147
182
  else: # No need to start a span if the parent is not sampled
183
+ set_context()
148
184
  yield
149
185
 
150
186
  def __enter__(self) -> None:
@@ -179,9 +215,9 @@ class _Trace:
179
215
  return func_with_tracing
180
216
 
181
217
 
182
- def _continue_trace_zmq_message(topic: str, message: dict, op: str):
218
+ def _continue_trace_zmq_message(topic: str, message: dict, op: str, **kwargs):
183
219
  name = f"{topic}/{message.get('type', '')}"
184
- return _Trace(trace_headers=message, op=op, name=name, source="zmq", origin="auto.zmq")
220
+ return _Trace(trace_headers=message, op=op, name=name, source="zmq", origin="auto.zmq", **kwargs)
185
221
 
186
222
 
187
223
  class StoringTransport(sentry_sdk.transport.HttpTransport):
@@ -349,6 +385,11 @@ def _patch_sentry_method():
349
385
 
350
386
  def _update_sentry_config(kwargs: dict):
351
387
  # Set default values
388
+ global _topics_to_ignore, _functions_to_ignore
389
+ _topics_to_ignore = kwargs.pop("topics_to_ignore", ["io"])
390
+ _functions_to_ignore = kwargs.pop(
391
+ "functions_to_ignore", ["message_handler.openmodule.utils.io.IoListener._on_io_message"])
392
+
352
393
  if "traces_sampler" not in kwargs:
353
394
  kwargs.setdefault("traces_sample_rate", 0.0001)
354
395
  if "profiles_sampler" not in kwargs:
@@ -371,6 +412,8 @@ def _update_sentry_config(kwargs: dict):
371
412
  kwargs["extras"]["name"] = settings.NAME
372
413
  if hasattr(settings, "GATE"):
373
414
  kwargs["extras"]["gate"] = settings.GATE
415
+ kwargs.setdefault("contexts", {})
416
+ kwargs["contexts"]["device"] = {"name": settings.RESOURCE, "model": settings.RESOURCE}
374
417
 
375
418
 
376
419
  def init_sentry(dsn: str, **kwargs):
@@ -388,12 +431,17 @@ def init_sentry(dsn: str, **kwargs):
388
431
 
389
432
  _update_sentry_config(kwargs)
390
433
  extras = kwargs.pop("extras", {})
434
+ contexts = kwargs.pop("contexts", {})
435
+ tags = kwargs.pop("tags", {})
391
436
  sentry_sdk.init(dsn=dsn, **kwargs)
392
437
 
393
438
  _patch_requests_library()
394
439
  _patch_sentry_method()
395
440
  for key, value in extras.items():
396
441
  sentry_sdk.get_global_scope().set_extra(key, value)
442
+ sentry_sdk.get_global_scope().set_tags(tags)
443
+ for key, value in contexts.items():
444
+ sentry_sdk.get_global_scope().set_context(key, value)
397
445
 
398
446
 
399
447
  def deinit_sentry():
@@ -137,7 +137,6 @@ class IoListener:
137
137
  return x if x else [IoState(pin="", gateway=Gateway(gate="", direction=""), type="", value=0, physical=0,
138
138
  inverted=False, last_timestamp=datetime.fromtimestamp(0))]
139
139
 
140
- @sentry.trace
141
140
  def _on_io_message(self, message: IoMessage):
142
141
  """
143
142
  This handler receives all IO Messages, saves any changes and calls any listeners registered in the IoListener
@@ -170,18 +169,20 @@ class IoListener:
170
169
  self.current_states[message.pin].last_timestamp = message.timestamp
171
170
 
172
171
  message = message.dict()
173
- for listener in self.listeners:
174
- """
175
- Handles the registered listeners the same as the dispatcher.
176
- Is copied here because all messages are needed to keep current_states up to date.
177
- """
178
- if listener.matches(message):
179
- try:
180
- listener.handler(self.current_states[message["pin"]])
181
- except zmq.ContextTerminated:
182
- raise
183
- except Exception as e:
184
- if self.raise_handler_errors:
185
- raise e from None
186
- else:
187
- self.log.exception("Error in message handler")
172
+ matched_listeners = [listener for listener in self.listeners if listener.matches(message)]
173
+ if matched_listeners:
174
+ with sentry.continue_trace_zmq_message_process("io", message):
175
+ for listener in matched_listeners:
176
+ """
177
+ Handles the registered listeners the same as the dispatcher.
178
+ Is copied here because all messages are needed to keep current_states up to date.
179
+ """
180
+ try:
181
+ listener.handler(self.current_states[message["pin"]])
182
+ except zmq.ContextTerminated:
183
+ raise
184
+ except Exception as e:
185
+ if self.raise_handler_errors:
186
+ raise e from None
187
+ else:
188
+ self.log.exception("Error in message handler")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openmodule
3
- Version: 14.0.1
3
+ Version: 14.0.2
4
4
  Summary: Libraries for developing the arivo openmodule
5
5
  Home-page: https://gitlab.com/arivo-public/device-python/openmodule.git
6
6
  Author: ARIVO
@@ -0,0 +1 @@
1
+ {"git_version": "3399243", "is_release": true}
@@ -1,5 +1,5 @@
1
1
  pydantic<2,>=1.7
2
- sentry-sdk==2.19.0
2
+ sentry-sdk~=2.19.0
3
3
  orjson<4,>=3.4.7
4
4
  pyzmq<23,>=22
5
5
  pyyaml<6,>5
@@ -1,3 +1,4 @@
1
+ import threading
1
2
  from typing import List
2
3
  from unittest import TestCase, mock
3
4
 
@@ -16,15 +17,18 @@ class SentryTestTransport(sentry_sdk.transport.Transport):
16
17
  def __init__(self, options=None):
17
18
  super().__init__(options)
18
19
  self.envelopes: List[Envelope] = []
20
+ self.envelopes_lock = threading.Lock()
19
21
 
20
22
  def capture_envelope(self, envelope: Envelope):
21
- self.envelopes.append(envelope)
23
+ with self.envelopes_lock:
24
+ self.envelopes.append(envelope)
22
25
 
23
26
  def get_envelopes(self, clear: bool = True) -> List[Envelope]:
24
- envelopes = self.envelopes
25
- if clear:
26
- self.envelopes = []
27
- return envelopes
27
+ with self.envelopes_lock:
28
+ envelopes = self.envelopes
29
+ if clear:
30
+ self.envelopes = []
31
+ return envelopes
28
32
 
29
33
 
30
34
  class SentryTestMixin(TestCase):
@@ -56,10 +60,8 @@ class SentryTestMixin(TestCase):
56
60
  return transport
57
61
 
58
62
  def _get_envelopes(self) -> List[Envelope]:
59
- return self.sentry_transport.envelopes
63
+ return self.sentry_transport.get_envelopes(clear=False)
60
64
 
61
65
  def get_sent_envelopes(self, timeout: float = 0, clear: bool = True) -> List[Envelope]:
62
- envelopes = wait_for_value(self._get_envelopes, target=[], invert_target=True, timeout=timeout)
63
- if clear:
64
- self.sentry_transport.envelopes = []
65
- return envelopes
66
+ wait_for_value(self._get_envelopes, target=[], invert_target=True, timeout=timeout)
67
+ return self.sentry_transport.get_envelopes(clear=clear)
@@ -1,5 +1,5 @@
1
1
  pydantic>=1.7,<2
2
- sentry-sdk==2.19.0
2
+ sentry-sdk~=2.19.0
3
3
  orjson>=3.4.7,<4
4
4
  pyzmq>=22,<23
5
5
  pyyaml>5,<6
@@ -10,8 +10,10 @@ import random
10
10
  import signal
11
11
  import subprocess
12
12
  import sys
13
+ import threading
13
14
  import time
14
15
  import unittest
16
+ from concurrent.futures.thread import ThreadPoolExecutor
15
17
  from contextlib import contextmanager
16
18
  from io import BytesIO
17
19
  from pathlib import Path
@@ -30,9 +32,12 @@ import openmodule.logging
30
32
  from openmodule import sentry
31
33
  from openmodule.config import settings, override_settings
32
34
  from openmodule.core import init_openmodule, shutdown_openmodule
33
- from openmodule.models.base import ZMQMessage
35
+ from openmodule.dispatcher import MessageDispatcher
36
+ from openmodule.models.base import ZMQMessage, Gateway, Direction
37
+ from openmodule.models.io import IoMessage
34
38
  from openmodule.rpc import RPCServer
35
39
  from openmodule.sentry import init_sentry, deinit_sentry
40
+ from openmodule.utils.io import IoListener
36
41
  from openmodule_test.sentry import SentryTestMixin
37
42
  from openmodule_test.utils import wait_for_value
38
43
  from openmodule_test.zeromq import ZMQTestMixin
@@ -149,18 +154,25 @@ class SentryInitTestCase(ZMQTestMixin):
149
154
  self.assertEqual(str(e.exception), "sentry DSN is required")
150
155
  self.assertFalse(openmodule.core._core_thread.sentry_was_initialized)
151
156
 
157
+ @override_settings(GATE="einfahrt")
152
158
  def test_sentry_init(self):
153
159
  config = self.zmq_config()
154
160
  init_openmodule(config, context=self.zmq_context(), sentry=True, dsn="http://test@test/1")
155
161
  self.assertTrue(openmodule.core._core_thread.sentry_was_initialized)
156
- self.assertIsInstance(sentry_sdk.get_global_scope().client, sentry_sdk.client.Client)
157
- self.assertIsInstance(sentry_sdk.get_global_scope().client.transport, sentry.StoringTransport)
158
- self.assertEqual(sentry_sdk.get_global_scope().client.options["release"], "test@test-version")
159
- self.assertEqual(sentry_sdk.get_global_scope().client.options["server_name"], "test-resource")
160
- self.assertEqual(sentry_sdk.get_global_scope().client.options["environment"], "staging")
161
- self.assertEqual(sentry_sdk.get_global_scope().client.options["dsn"], "http://test@test/1")
162
- self.assertEqual(sentry_sdk.get_global_scope().client.options["traces_sample_rate"], 0.0001)
163
- self.assertEqual(sentry_sdk.get_global_scope().client.options["profiles_sample_rate"], 0.001)
162
+ scope = sentry_sdk.get_global_scope()
163
+ self.assertIsInstance(scope.client, sentry_sdk.client.Client)
164
+ self.assertIsInstance(scope.client.transport, sentry.StoringTransport)
165
+ self.assertEqual(scope.client.options["release"], "test@test-version")
166
+ self.assertEqual(scope.client.options["server_name"], "test-resource")
167
+ self.assertEqual(scope.client.options["environment"], "staging")
168
+ self.assertEqual(scope.client.options["dsn"], "http://test@test/1")
169
+ self.assertEqual(scope.client.options["traces_sample_rate"], 0.0001)
170
+ self.assertEqual(scope.client.options["profiles_sample_rate"], 0.001)
171
+ self.assertEqual(scope._extras, {"name": "test", "gate": "einfahrt"})
172
+ self.assertEqual(scope._contexts, {'device': {'model': 'test-resource', 'name': 'test-resource'}})
173
+ self.assertEqual(sentry._topics_to_ignore, ["io"])
174
+ self.assertEqual(sentry._functions_to_ignore, ["message_handler.openmodule.utils.io.IoListener._on_io_message"])
175
+
164
176
 
165
177
  @override_settings(NAME="test")
166
178
  def test_service_name_generation(self):
@@ -184,6 +196,18 @@ class SentryInitTestCase(ZMQTestMixin):
184
196
  sentry._update_sentry_config(kwargs)
185
197
  self.assertEqual(kwargs["release"], "service-test@test-version")
186
198
 
199
+ def test_sentry_ignore_topics(self):
200
+ self.assertEqual(sentry._topics_to_ignore, ["io"])
201
+ init_openmodule(self.zmq_config(), context=self.zmq_context(), sentry=True, dsn="http://test@test/1",
202
+ topics_to_ignore=["test"])
203
+ self.assertEqual(sentry._topics_to_ignore, ["test"])
204
+
205
+ def test_sentry_ignore_functions(self):
206
+ self.assertEqual(sentry._functions_to_ignore, ["message_handler.openmodule.utils.io.IoListener._on_io_message"])
207
+ init_openmodule(self.zmq_config(), context=self.zmq_context(), sentry=True, dsn="http://test@test/1",
208
+ functions_to_ignore=["test"])
209
+ self.assertEqual(sentry._functions_to_ignore, ["test"])
210
+
187
211
 
188
212
  class SentryTestCase(SentryTestMixin):
189
213
  def setUp(self):
@@ -404,6 +428,94 @@ class SentryTestCase(SentryTestMixin):
404
428
  ExampleClass.method()
405
429
  self.assert_spans(span_recorder, ["func"])
406
430
 
431
+ def test_io_message_not_traced(self):
432
+ with sentry.continue_trace_zmq_message_receive("io", {}):
433
+ pass
434
+ with sentry.continue_trace_zmq_message_receive("not-io", {}):
435
+ pass
436
+ envelopes = self.get_sent_envelopes()
437
+ self.assertEqual(len(envelopes), 1)
438
+ self.assertEqual(len(envelopes[0].items), 1)
439
+ self.assertEqual(envelopes[0].items[0].payload.json["transaction"], "not-io/")
440
+
441
+ def test_ignored_function(self):
442
+ sentry._functions_to_ignore = ["test-ignore"]
443
+ with sentry.trace("test-ignore"):
444
+ pass
445
+ with sentry.trace("not-test-ignore"):
446
+ pass
447
+ envelopes = self.get_sent_envelopes()
448
+ self.assertEqual(len(envelopes), 1)
449
+ self.assertEqual(len(envelopes[0].items), 1)
450
+ self.assertEqual(envelopes[0].items[0].payload.json["transaction"], "not-test-ignore")
451
+
452
+ class SentryInDispatcherTestCase(SentryTestMixin):
453
+ def setUp(self):
454
+ super().setUp()
455
+ init_sentry("http://test@test/1")
456
+ sentry_sdk.get_client().options["traces_sample_rate"] = 1.0
457
+ self.dispatcher = None
458
+
459
+ def tearDown(self):
460
+ if self.dispatcher:
461
+ self.dispatcher.shutdown()
462
+ super().tearDown()
463
+ deinit_sentry()
464
+
465
+ def test_dispatcher(self):
466
+ def handler(*_):
467
+ pass
468
+
469
+ self.dispatcher = MessageDispatcher()
470
+ self.dispatcher.register_handler("test", ZMQMessage, handler, match_type=False, register_schema=False)
471
+ with sentry.trace("parent", sampled=True):
472
+ self.dispatcher.dispatch("test", ZMQMessage(type="test").dict())
473
+
474
+ envelopes = self.get_sent_envelopes()
475
+ self.assertEqual(len(envelopes), 1)
476
+ self.assertEqual(len(envelopes[0].items), 1)
477
+ self.assertEqual(envelopes[0].items[0].payload.json["transaction"], "parent")
478
+ self.assertEqual(len(envelopes[0].items[0].payload.json["spans"]), 2)
479
+ span_names = [span["description"] for span in envelopes[0].items[0].payload.json["spans"]]
480
+ handler_name = "message_handler.tests.test_sentry.SentryInDispatcherTestCase.test_dispatcher.<locals>.handler"
481
+ self.assertEqual(span_names, ["test/test", handler_name])
482
+
483
+ def test_io_handler_not_traced(self):
484
+ self.dispatcher = MessageDispatcher()
485
+ IoListener(self.dispatcher)
486
+ self.dispatcher.dispatch("io", IoMessage(edge=1, gateway=Gateway(gate="test", direction=Direction.IN),
487
+ type="io", pin="1", value=1).dict())
488
+ with self.assertRaises(TimeoutError):
489
+ self.get_sent_envelopes()
490
+
491
+ def test_multi_worker_dispatcher(self):
492
+ def handler(*_):
493
+ envelopes_got.wait(1)
494
+ handled.set()
495
+
496
+ handled = threading.Event()
497
+ envelopes_got = threading.Event()
498
+ self.dispatcher = MessageDispatcher(executor=ThreadPoolExecutor(max_workers=20))
499
+ self.dispatcher.register_handler("test", ZMQMessage, handler, match_type=False, register_schema=False)
500
+ with sentry.trace("parent", sampled=True):
501
+ self.dispatcher.dispatch("test", ZMQMessage(type="test").dict())
502
+ first_envelopes = self.get_sent_envelopes()
503
+ envelopes_got.set()
504
+ self.assertTrue(handled.wait(timeout=1))
505
+ second_envelopes = self.get_sent_envelopes(timeout=1)
506
+ self.assertEqual(len(first_envelopes), 1)
507
+ self.assertEqual(len(first_envelopes[0].items), 1)
508
+ self.assertEqual(first_envelopes[0].items[0].payload.json["transaction"], "parent")
509
+ self.assertEqual(len(first_envelopes[0].items[0].payload.json["spans"]), 0)
510
+
511
+ self.assertEqual(len(second_envelopes), 1)
512
+ self.assertEqual(len(second_envelopes[0].items), 1)
513
+ self.assertEqual(second_envelopes[0].items[0].payload.json["transaction"], "test/test")
514
+ self.assertEqual(len(second_envelopes[0].items[0].payload.json["spans"]), 1)
515
+ handler_name = ("message_handler.tests.test_sentry.SentryInDispatcherTestCase."
516
+ "test_multi_worker_dispatcher.<locals>.handler")
517
+ self.assertEqual(second_envelopes[0].items[0].payload.json["spans"][0]["description"], handler_name)
518
+
407
519
 
408
520
  class SentryUtilsTestCase(SentryTestMixin):
409
521
  @classmethod
@@ -1 +0,0 @@
1
- {"git_version": "18fe816", "is_release": true}
File without changes
File without changes
File without changes
File without changes
File without changes