openmodule 13.6.0__tar.gz → 14.0.1__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 (253) hide show
  1. {openmodule-13.6.0 → openmodule-14.0.1}/ChangeLog +12 -14
  2. {openmodule-13.6.0/openmodule.egg-info → openmodule-14.0.1}/PKG-INFO +1 -1
  3. {openmodule-13.6.0 → openmodule-14.0.1}/docs/getting_started.md +6 -4
  4. {openmodule-13.6.0 → openmodule-14.0.1}/docs/known_issues.md +3 -0
  5. {openmodule-13.6.0 → openmodule-14.0.1}/docs/migrations.md +11 -0
  6. openmodule-14.0.1/docs/sentry.md +93 -0
  7. {openmodule-13.6.0 → openmodule-14.0.1}/docs/settings.md +6 -6
  8. {openmodule-13.6.0 → openmodule-14.0.1}/docs/testing.md +53 -7
  9. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/config.py +0 -8
  10. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/connection_status.py +2 -0
  11. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/core.py +17 -17
  12. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/dispatcher.py +20 -16
  13. openmodule-14.0.1/openmodule/logging.py +34 -0
  14. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/messaging.py +13 -6
  15. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/models/base.py +3 -1
  16. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/rpc/client.py +20 -16
  17. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/rpc/server.py +60 -54
  18. openmodule-14.0.1/openmodule/sentry.py +412 -0
  19. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/access_service.py +3 -0
  20. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/csv_export.py +2 -0
  21. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/databox.py +2 -0
  22. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/eventlog.py +2 -0
  23. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/io.py +2 -0
  24. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/kv_store.py +8 -0
  25. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/package_reader.py +6 -0
  26. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/presence.py +7 -0
  27. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/settings.py +3 -0
  28. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/validation.py +2 -0
  29. {openmodule-13.6.0 → openmodule-14.0.1/openmodule.egg-info}/PKG-INFO +1 -1
  30. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule.egg-info/SOURCES.txt +3 -0
  31. openmodule-14.0.1/openmodule.egg-info/pbr.json +1 -0
  32. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule.egg-info/requires.txt +1 -2
  33. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/interrupt.py +0 -1
  34. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/requirements.txt +0 -1
  35. openmodule-14.0.1/openmodule_test/sentry.py +65 -0
  36. openmodule-14.0.1/openmodule_test/utils.py +36 -0
  37. {openmodule-13.6.0 → openmodule-14.0.1}/requirements.txt +1 -2
  38. {openmodule-13.6.0 → openmodule-14.0.1}/test-requirements.txt +0 -1
  39. openmodule-14.0.1/tests/sentry_main.py +32 -0
  40. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_core.py +26 -33
  41. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_health.py +0 -1
  42. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_interrupt.py +8 -8
  43. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_logging.py +14 -0
  44. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_messaging.py +8 -4
  45. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_mockrpcclient.py +0 -1
  46. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_model.py +3 -2
  47. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_rpc.py +16 -10
  48. openmodule-14.0.1/tests/test_sentry.py +747 -0
  49. {openmodule-13.6.0 → openmodule-14.0.1}/tox.ini +1 -1
  50. openmodule-13.6.0/openmodule/logging.py +0 -12
  51. openmodule-13.6.0/openmodule/sentry.py +0 -103
  52. openmodule-13.6.0/openmodule.egg-info/pbr.json +0 -1
  53. openmodule-13.6.0/openmodule_test/utils.py +0 -9
  54. openmodule-13.6.0/tests/test_sentry.py +0 -175
  55. {openmodule-13.6.0 → openmodule-14.0.1}/.gitlab-ci.yml +0 -0
  56. {openmodule-13.6.0 → openmodule-14.0.1}/AUTHORS +0 -0
  57. {openmodule-13.6.0 → openmodule-14.0.1}/LICENSE +0 -0
  58. {openmodule-13.6.0 → openmodule-14.0.1}/README.md +0 -0
  59. {openmodule-13.6.0 → openmodule-14.0.1}/docs/access_service.md +0 -0
  60. {openmodule-13.6.0 → openmodule-14.0.1}/docs/anonymization.md +0 -0
  61. {openmodule-13.6.0 → openmodule-14.0.1}/docs/cleanup.md +0 -0
  62. {openmodule-13.6.0 → openmodule-14.0.1}/docs/coding_standard.md +0 -0
  63. {openmodule-13.6.0 → openmodule-14.0.1}/docs/commands.md +0 -0
  64. {openmodule-13.6.0 → openmodule-14.0.1}/docs/connection_status_listener.md +0 -0
  65. {openmodule-13.6.0 → openmodule-14.0.1}/docs/csv_export.md +0 -0
  66. {openmodule-13.6.0 → openmodule-14.0.1}/docs/database.md +0 -0
  67. {openmodule-13.6.0 → openmodule-14.0.1}/docs/deprecated.md +0 -0
  68. {openmodule-13.6.0 → openmodule-14.0.1}/docs/deprecated_code/README.md +0 -0
  69. {openmodule-13.6.0 → openmodule-14.0.1}/docs/deprecated_code/access_service/openmodule/models/access_service.py +0 -0
  70. {openmodule-13.6.0 → openmodule-14.0.1}/docs/deprecated_code/access_service/openmodule/utils/access_service.py +0 -0
  71. {openmodule-13.6.0 → openmodule-14.0.1}/docs/deprecated_code/access_service/openmodule_test/access_service.py +0 -0
  72. {openmodule-13.6.0 → openmodule-14.0.1}/docs/deprecated_code/access_service/tests/test_utils_access_service.py +0 -0
  73. {openmodule-13.6.0 → openmodule-14.0.1}/docs/deprecated_code/api/openmodule/utils/api.py +0 -0
  74. {openmodule-13.6.0 → openmodule-14.0.1}/docs/deprecated_code/api/openmodule_test/api.py +0 -0
  75. {openmodule-13.6.0 → openmodule-14.0.1}/docs/deprecated_code/api/tests/test_utils_api.py +0 -0
  76. {openmodule-13.6.0 → openmodule-14.0.1}/docs/deprecated_code/package_reader/openmodule/utils/package_reader.py +0 -0
  77. {openmodule-13.6.0 → openmodule-14.0.1}/docs/deprecated_code/package_reader/openmodule_test/fake_package_creator.py +0 -0
  78. {openmodule-13.6.0 → openmodule-14.0.1}/docs/deprecated_code/package_reader/tests/test_package_reader.py +0 -0
  79. {openmodule-13.6.0 → openmodule-14.0.1}/docs/event_sending.md +0 -0
  80. {openmodule-13.6.0 → openmodule-14.0.1}/docs/health.md +0 -0
  81. {openmodule-13.6.0 → openmodule-14.0.1}/docs/images/broker.drawio.png +0 -0
  82. {openmodule-13.6.0 → openmodule-14.0.1}/docs/package_reader.md +0 -0
  83. {openmodule-13.6.0 → openmodule-14.0.1}/docs/rpc.md +0 -0
  84. {openmodule-13.6.0 → openmodule-14.0.1}/docs/settings_provider.md +0 -0
  85. {openmodule-13.6.0 → openmodule-14.0.1}/docs/translation.md +0 -0
  86. {openmodule-13.6.0 → openmodule-14.0.1}/docs/utils.md +0 -0
  87. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/__init__.py +0 -0
  88. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/alert.py +0 -0
  89. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/database/custom_types.py +0 -0
  90. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/database/database.py +0 -0
  91. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/database/env.py +0 -0
  92. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/database/migration.py +0 -0
  93. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/health.py +0 -0
  94. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/models/__init__.py +0 -0
  95. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/models/access_service.py +0 -0
  96. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/models/alert.py +0 -0
  97. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/models/io.py +0 -0
  98. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/models/kv_store.py +0 -0
  99. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/models/presence.py +0 -0
  100. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/models/privacy.py +0 -0
  101. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/models/rpc.py +0 -0
  102. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/models/settings.py +0 -0
  103. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/models/validation.py +0 -0
  104. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/models/vehicle.py +0 -0
  105. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/rpc/__init__.py +0 -0
  106. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/rpc/common.py +0 -0
  107. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/threading.py +0 -0
  108. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/__init__.py +0 -0
  109. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/charset.py +0 -0
  110. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/cleanup.py +0 -0
  111. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/db_helper.py +0 -0
  112. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/matching.py +0 -0
  113. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/misc_functions.py +0 -0
  114. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/schema.py +0 -0
  115. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule/utils/translation.py +0 -0
  116. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule.egg-info/dependency_links.txt +0 -0
  117. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule.egg-info/not-zip-safe +0 -0
  118. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule.egg-info/top_level.txt +0 -0
  119. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_commands/__init__.py +0 -0
  120. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_commands/setup.cfg +0 -0
  121. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_commands/setup.py +0 -0
  122. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_commands/translate.py +0 -0
  123. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/__init__.py +0 -0
  124. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/alert.py +0 -0
  125. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/connection_status.py +0 -0
  126. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/core.py +0 -0
  127. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/database.py +0 -0
  128. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/eventlistener.py +0 -0
  129. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/files.py +0 -0
  130. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/gate.py +0 -0
  131. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/health.py +0 -0
  132. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/io_simulator.py +0 -0
  133. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/package_reader.py +0 -0
  134. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/presence.py +0 -0
  135. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/rpc.py +0 -0
  136. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/settings.py +0 -0
  137. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/setup.cfg +0 -0
  138. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/setup.py +0 -0
  139. {openmodule-13.6.0 → openmodule-14.0.1}/openmodule_test/zeromq.py +0 -0
  140. {openmodule-13.6.0 → openmodule-14.0.1}/setup.cfg +0 -0
  141. {openmodule-13.6.0 → openmodule-14.0.1}/setup.py +0 -0
  142. {openmodule-13.6.0 → openmodule-14.0.1}/tests/__init__.py +0 -0
  143. {openmodule-13.6.0 → openmodule-14.0.1}/tests/config.py +0 -0
  144. {openmodule-13.6.0 → openmodule-14.0.1}/tests/database_models_migration.py +0 -0
  145. {openmodule-13.6.0 → openmodule-14.0.1}/tests/database_models_test.py +0 -0
  146. {openmodule-13.6.0 → openmodule-14.0.1}/tests/invalid_database/alembic/README +0 -0
  147. {openmodule-13.6.0 → openmodule-14.0.1}/tests/invalid_database/alembic/__init__.py +0 -0
  148. {openmodule-13.6.0 → openmodule-14.0.1}/tests/invalid_database/alembic/env.py +0 -0
  149. {openmodule-13.6.0 → openmodule-14.0.1}/tests/invalid_database/alembic/script.py.mako +0 -0
  150. {openmodule-13.6.0 → openmodule-14.0.1}/tests/invalid_database/alembic/versions/ff26e54332f9_datetime_models.py +0 -0
  151. {openmodule-13.6.0 → openmodule-14.0.1}/tests/invalid_database/alembic.ini +0 -0
  152. {openmodule-13.6.0 → openmodule-14.0.1}/tests/invalid_database/makemigration.sh +0 -0
  153. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_double_column_delete_error/alembic/__init__.py +0 -0
  154. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_double_column_delete_error/alembic/env.py +0 -0
  155. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_double_column_delete_error/alembic/script.py.mako +0 -0
  156. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_double_column_delete_error/alembic/versions/812a3e5b8517_initial.py +0 -0
  157. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_double_column_delete_error/alembic/versions/a7ea100a784f_key_error.py +0 -0
  158. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_double_column_delete_error/alembic.ini +0 -0
  159. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_double_column_delete_error/makemigration.sh +0 -0
  160. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_no_such_table_error/alembic/__init__.py +0 -0
  161. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_no_such_table_error/alembic/env.py +0 -0
  162. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_no_such_table_error/alembic/script.py.mako +0 -0
  163. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_no_such_table_error/alembic/versions/812a3e5b8517_initial.py +0 -0
  164. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_no_such_table_error/alembic/versions/a7ea100a784f_no_such_table_error.py +0 -0
  165. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_no_such_table_error/alembic.ini +0 -0
  166. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_no_such_table_error/makemigration.sh +0 -0
  167. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_test_database/__init__.py +0 -0
  168. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_test_database/alembic/__init__.py +0 -0
  169. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_test_database/alembic/env.py +0 -0
  170. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_test_database/alembic/script.py.mako +0 -0
  171. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_test_database/alembic/versions/19789aa5361c_initial.py +0 -0
  172. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_test_database/alembic/versions/19d887929ae7_alter.py +0 -0
  173. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_test_database/alembic/versions/__init__.py +0 -0
  174. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_test_database/alembic.ini +0 -0
  175. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_test_database/alembic_migration_test_database.sqlite3 +0 -0
  176. {openmodule-13.6.0 → openmodule-14.0.1}/tests/migration_test_database/makemigration.sh +0 -0
  177. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/configs/config.py +0 -0
  178. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/configs/test_config.py +0 -0
  179. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/configs/test_config_1.py +0 -0
  180. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/standard_schemes/DEFAULT-10.yml +0 -0
  181. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/standard_schemes/DEFAULT-20.yml +0 -0
  182. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/standard_schemes/LEGACY-0.yml +0 -0
  183. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/translation/locale/de/LC_MESSAGES/translation.mo +0 -0
  184. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/translation/locale/de/LC_MESSAGES/translation.po +0 -0
  185. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/translation/locale/en/LC_MESSAGES/translation.mo +0 -0
  186. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/translation/locale/en/LC_MESSAGES/translation.po +0 -0
  187. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/translation/locale/translation.pot +0 -0
  188. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/translation/translate.sh +0 -0
  189. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/utils_matching/A-10.yml +0 -0
  190. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/utils_matching/A-20.yml +0 -0
  191. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/utils_matching/DEFAULT-10.yml +0 -0
  192. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/utils_matching/DEFAULT-20.yml +0 -0
  193. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/utils_matching/DEFAULT-30.yml +0 -0
  194. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/utils_matching/LEGACY-0.yml +0 -0
  195. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/utils_matching/TEST-10.yml +0 -0
  196. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/utils_matching/TEST-20.yml +0 -0
  197. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/utils_matching/TEST-30.yml +0 -0
  198. {openmodule-13.6.0 → openmodule-14.0.1}/tests/resources/utils_matching/TEST-40.yml +0 -0
  199. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_access_service_database/alembic/__init__.py +0 -0
  200. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_access_service_database/alembic/env.py +0 -0
  201. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_access_service_database/alembic/script.py.mako +0 -0
  202. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_access_service_database/alembic/versions/7bd4fcd38fde_removed_nfc_and_pin.py +0 -0
  203. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_access_service_database/alembic/versions/9ca98a2e5674_added_parksettings_id.py +0 -0
  204. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_access_service_database/alembic/versions/c821971f9230_initial.py +0 -0
  205. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_access_service_database/alembic.ini +0 -0
  206. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_access_service_database/makemigration.sh +0 -0
  207. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_alembic_migrations.py +0 -0
  208. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_alert.py +0 -0
  209. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_checks.py +0 -0
  210. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_config.py +0 -0
  211. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_connection_status.py +0 -0
  212. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_database/alembic/__init__.py +0 -0
  213. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_database/alembic/env.py +0 -0
  214. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_database/alembic/script.py.mako +0 -0
  215. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_database/alembic/versions/32b8c728abbf_initial.py +0 -0
  216. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_database/alembic.ini +0 -0
  217. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_database/makemigration.sh +0 -0
  218. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_database.py +0 -0
  219. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_dispatcher.py +0 -0
  220. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_io_listen.py +0 -0
  221. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_kv_store_database/alembic/__init__.py +0 -0
  222. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_kv_store_database/alembic/env.py +0 -0
  223. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_kv_store_database/alembic/script.py.mako +0 -0
  224. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_kv_store_database/alembic/versions/9c5c944221f4_deprecated_kv_entry_example.py +0 -0
  225. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_kv_store_database/alembic/versions/c55a69026a25_initial.py +0 -0
  226. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_kv_store_database/alembic.ini +0 -0
  227. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_kv_store_database/makemigration.sh +0 -0
  228. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_kv_store_multiple_database/alembic/README +0 -0
  229. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_kv_store_multiple_database/alembic/__init__.py +0 -0
  230. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_kv_store_multiple_database/alembic/env.py +0 -0
  231. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_kv_store_multiple_database/alembic/script.py.mako +0 -0
  232. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_kv_store_multiple_database/alembic/versions/cdb3214131a9_initial.py +0 -0
  233. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_kv_store_multiple_database/alembic.ini +0 -0
  234. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_kv_store_multiple_database/makemigration.sh +0 -0
  235. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_schema.py +0 -0
  236. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_test_alert.py +0 -0
  237. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_test_gate.py +0 -0
  238. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_test_zeromq.py +0 -0
  239. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_access_service.py +0 -0
  240. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_charset.py +0 -0
  241. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_cleanup.py +0 -0
  242. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_csv_export.py +0 -0
  243. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_databox.py +0 -0
  244. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_eventlog.py +0 -0
  245. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_kv_store.py +0 -0
  246. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_kv_store_multiple.py +0 -0
  247. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_matching.py +0 -0
  248. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_misc_functions.py +0 -0
  249. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_package_reader.py +0 -0
  250. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_presence.py +0 -0
  251. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_settings.py +0 -0
  252. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_validation.py +0 -0
  253. {openmodule-13.6.0 → openmodule-14.0.1}/tests/test_utils_vehicle.py +0 -0
@@ -1,6 +1,18 @@
1
1
  CHANGES
2
2
  =======
3
3
 
4
+ v14.0.1
5
+ -------
6
+
7
+ * fixed sentry release name
8
+
9
+ v14.0.0
10
+ -------
11
+
12
+ * Add breaking changes to docs
13
+ * OM-693 Openmodule sentry v2
14
+ * Update known\_issues.md [skip ci]
15
+
4
16
  v13.6.0
5
17
  -------
6
18
 
@@ -151,9 +163,6 @@ v12.0.0.rc0
151
163
  * schedule exports utility
152
164
  * SettingsProvider docs
153
165
  * SettingsProvider docs
154
- * added settings\_models requirement, marking Test\* classes that are not tests with \_\_test\_\_ = False
155
- * AAAAAAAABBBBBBBBBBBBBBMerge branch 'master' into DEV-5415
156
- * [skip ci] Broken until settings\_model pip package is fixed. Removed deprecated features for v12. Using settings\_models in SettingsProvider
157
166
 
158
167
  v11.1.1
159
168
  -------
@@ -199,14 +208,3 @@ v10.0.3
199
208
  -------
200
209
 
201
210
  * added freezegun and fakeredis to openmodule requirements
202
-
203
- v10.0.2
204
- -------
205
-
206
- * touching a filer, since the tag's job is skipped because the commit mentioned 'sk\_ip ci'
207
-
208
- v10.0.2.rc2
209
- -----------
210
-
211
- * added more documentation [skip ci]
212
- * fixes an issue in the multiprocessing\_logging package in testcases
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openmodule
3
- Version: 13.6.0
3
+ Version: 14.0.1
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
@@ -12,7 +12,7 @@ All device services connect to the broker. Device services use the `SUB` port of
12
12
  and the `PUB` port to receive messages.
13
13
 
14
14
  We are send [multipart messages](https://zguide.zeromq.org/docs/chapter2/#Multipart-Messages) to the broker.
15
- The multipart message consists of a `topic` and a `payload`. The `topic` is used to route the message to possible
15
+ The multipart message consists of a `topic` and a `payload`. The `topic` is used to route the message to possible
16
16
  multiple device services (Broadcast). The `payload` is a JSON string containing the actual data.
17
17
 
18
18
  ![Broker](./images/broker.drawio.png)
@@ -75,6 +75,7 @@ The Openmodule will raise an `AssertionError` if the validator is missing.
75
75
  ### Project Structure
76
76
 
77
77
  The Openmodule is structured in the following way:
78
+
78
79
  ```
79
80
  openmodule/
80
81
  ├── openmodule/
@@ -97,6 +98,7 @@ The `openmodule_commands` folder contains some utility commands like for example
97
98
  ### Project Structure of a Device Service
98
99
 
99
100
  A typical device service has the following structure:
101
+
100
102
  ```
101
103
  device-service/
102
104
  ├── docker/
@@ -121,7 +123,7 @@ The YAML file `default.yml` is an optional additional config file if you need a
121
123
 
122
124
  The `src` folder contains the actual source code of the device service. The `app.py` file contains the main function
123
125
  of the device service. An example of the `app.py` is shown in the section
124
- [Create a Openmodule Instance](getting_started.md#create-a-openmodule-instance).
126
+ [Create a Openmodule Instance](getting_started.md#create-a-openmodule-instance).
125
127
  This example of the `app.py` file was copied from our template project.
126
128
  The `config.py` file contains the configuration of the device service. The `models.py` file
127
129
  should hold all models that are used in the device service.
@@ -184,7 +186,7 @@ To solve this migrate your model definition and the YAML initialization
184
186
 
185
187
  The first step that are you have to do is to create an instance of the Openmodule class.
186
188
  Below you see an example of the main Python file `app.py`. This file was copied from our template project and
187
- you do not have to manually create it.
189
+ you do not have to manually create it. You also need to provide a Sentry DSN to the Openmodule.
188
190
 
189
191
  ```python
190
192
  import logging
@@ -204,7 +206,7 @@ def main_wrapper():
204
206
 
205
207
 
206
208
  def main():
207
- core = init_openmodule(settings)
209
+ core = init_openmodule(settings, dsn="https://<key>@debug.acc.si/<project>")
208
210
  try:
209
211
  while True:
210
212
  time.sleep(1)
@@ -5,6 +5,9 @@ version. The changelog may contain many other notes aswell.
5
5
 
6
6
  The version numbers below always note the _version through which the issue was fixed_.
7
7
 
8
+ ## 13.6.0
9
+ * fixed message dispatcher trying to handle messages after shutdown was called
10
+
8
11
  ## 13.1.2
9
12
 
10
13
  * fixed error output on RPCs not sent by this RPCClient
@@ -1,5 +1,16 @@
1
1
  # Breaking Version Changes
2
2
 
3
+ ## 14.0.0
4
+ * sentry_sdk version was updated
5
+ * redis was removed
6
+ * The `RPCServer` does no longer call `os._exit` if `"status"` is in the handler return value.
7
+ It raises a `ValueError` instead.
8
+ * The `init_openmodule` now takes a sentry `dsn` as an argument. This is required if sentry is enabled
9
+ (is enabled by default if not `TESTING` and not `DEBUG`).
10
+ * The `receive_message_from_socket` is now a context manager and should be used with a `with` statement.
11
+ This was done, so that any received zmq message automatically continues an existing sentry trace.
12
+ * Example: `with receive_message_from_socket(socket) as (topic, message):`
13
+
3
14
  ## 13.6.0
4
15
  * messaging:
5
16
  * the `get_pub_socket` now raises an AssertionError because we no longer support multiple publishers.
@@ -0,0 +1,93 @@
1
+ from openmodule.core import init_openmodule
2
+
3
+ # Sentry
4
+
5
+ [TOC]
6
+
7
+ ## Introduction
8
+
9
+ Sentry is a service that helps us monitor and fix errors in our applications. It provides real-time error tracking and
10
+ notifications.
11
+
12
+ The Python Sentry SDK automatically creates events from uncaught exceptions and logs of level `error` and above.
13
+ All error logs and exceptions are part of a transaction, even if no trace is created. So adding additional context to a
14
+ transaction will also apply to the error logs and exceptions.
15
+
16
+ It also provides tools for tracing process flows and diagnosing performance issues.
17
+
18
+ ## Initialization
19
+
20
+ To use Sentry, you need to provide the DSN to the OpenModuleCore initialization function. The DSN is a unique identifier
21
+ for your project that tells the SDK where to send the events. You can find the DSN in the Sentry project settings.
22
+
23
+ * During Testing and Development, sentry will not be initialized, and no events will be sent.
24
+ * You can provide additional [sentry options](https://docs.sentry.io/platforms/python/configuration/options/) as keyword
25
+ arguments to the `init_openmodule` function (`server_name` and `environment` cannot be overriden).
26
+ * the `extras` keyword argument can be used to provide additional data to the Sentry SDK
27
+
28
+ ```python
29
+ def main():
30
+ core = init_openmodule(settings, dsn="https://<key>@debug.acc.si/<project>")
31
+ ```
32
+
33
+ ## Errors & Exceptions
34
+
35
+ Uncaught exceptions and `logging.exception(...)` calls are automatically captured by Sentry and turned into issues with
36
+ a stack trace. `logging.error(...)` calls are also captured, but without a stack trace, so it's better to use
37
+ `logging.exception(...)` when possible.
38
+
39
+ ### requests raise_for_status
40
+
41
+ When using the `requests` library, you can use the `raise_for_status` method to raise an exception if the request was
42
+ unsuccessful. This will cause sentry to automatically add the response body to the current transaction.
43
+
44
+ ## Tracing
45
+
46
+ Openmodule provides the `sentry.trace` function that can be used as a decorator to trace a function or as a context
47
+ manager to trace a block of code. This will create a new span for the function or block of code and record its duration.
48
+ If no transaction is active, a new transaction will be created before the span.
49
+
50
+ * When using the decorator, the span will have the (qual)name of the function (if none is provided).
51
+ * When using the context manager, you **should** provide a name for the span.
52
+ * In addition to name, the op parameter can be used to specify the operation type of the span.
53
+ (default is `function` and should be sufficient for most cases, others can be found
54
+ [here](https://develop.sentry.dev/sdk/telemetry/traces/span-operations/).)
55
+
56
+ ```python
57
+ from openmodule import sentry
58
+
59
+
60
+ @sentry.trace
61
+ def my_function():
62
+ pass
63
+
64
+
65
+ @sentry.trace(name="other_function")
66
+ def my_function2():
67
+ pass
68
+
69
+
70
+ with sentry.trace("my_block"):
71
+ pass
72
+ ```
73
+
74
+ ## Adding Additional Information
75
+
76
+ You can add context to the current transaction using one of the following methods:
77
+
78
+ * `sentry_sdk.set_tag(key: str, value: str)`: Adds
79
+ a [tag](https://docs.sentry.io/platforms/python/enriching-events/tags/) to the current transaction.
80
+ * `sentry_sdk.set_tags(**key_value_pairs: str)`:
81
+ Adds [tags](https://docs.sentry.io/platforms/python/enriching-events/tags/) to the current transaction.
82
+ * `sentry_sdk.set_context(key: str, value: Any)`: Adds
83
+ a [context](https://docs.sentry.io/platforms/python/enriching-events/context/) to the current transaction.
84
+ * `sentry_sdk.set_extra(key: str, value: Any)`: Adds extra data to the current transaction. (similar to tags, but not
85
+ indexed for searching and more free-form)
86
+
87
+ ```python
88
+ with sentry.trace("my_block"):
89
+ sentry_sdk.set_tag("key", "value")
90
+ sentry_sdk.set_tags({"key1": "value1", "key2": "value2"})
91
+ sentry_sdk.set_context("key", {"whatever": "you want"})
92
+ sentry_sdk.set_extra("key", "value")
93
+ ```
@@ -47,14 +47,14 @@ class GlobalSettings:
47
47
  BROKER_SUB = broker_sub()
48
48
  BROKER_PUB = broker_pub()
49
49
 
50
- LOCAL_DEVELOPMENT = bool("LOCAL_DEVELOPMENT", False)
51
50
  is_bridged_slave = is_bridged_slave()
52
51
  DIST_FOLDER = dist_folder()
53
52
  DEV_DEVICE = dev_device()
54
53
 
55
- # redis
56
- REDIS_HOST = string("REDIS_HOST", "localhost")
57
- REDIS_PASSWORD = string("REDIS_PASSWORD", "") or None
58
- REDIS_PORT = int("REDIS_PORT", 6379)
59
- REDIS_DB = int("REDIS_DB", 0)
54
+ # translation
55
+ LOCALE_DIR = locale_dir()
56
+ LANGUAGE = "" if testing() else string("LANGUAGE", "de").lower()
57
+
58
+ # databox
59
+ DATABOX_UPLOAD_DIR = string("DATABOX_UPLOAD_DIR", "/upload")
60
60
  ```
@@ -154,8 +154,8 @@ Mixin for testing alembic migrations. Tests start with a clean database without
154
154
 
155
155
  You can also provide your own sqlite3 database that will be copied for each test.
156
156
 
157
- **⚠ Do not use the database models defined in your app for these tests.**
158
- Instead use the `AlembicMigrationTestMixin.get_model`method to get the model from the database schema.
157
+ **⚠ Do not use the database models defined in your app for these tests.**
158
+ Instead use the `AlembicMigrationTestMixin.get_model`method to get the model from the database schema.
159
159
  Your Source code will not work with models from a different database revision. Do not call any functions that rely on
160
160
  the database models in your tests.
161
161
 
@@ -326,7 +326,8 @@ shut down within 3 seconds and print that it hase received a KeyboardInterrupt.
326
326
 
327
327
  Since main tests are somewhat complex, we provide some examples for different use cases.
328
328
 
329
- **Wait for an RPC server to be started, and send a test RPC. Also ensure that the service sends a specific message on start and stop (basic backend test case).**
329
+ **Wait for an RPC server to be started, and send a test RPC. Also ensure that the service sends a specific message on
330
+ start and stop (basic backend test case).**
330
331
 
331
332
  ```python
332
333
  class MainTest(RPCServerTestMixin, MainTestMixin):
@@ -340,12 +341,16 @@ class MainTest(RPCServerTestMixin, MainTestMixin):
340
341
  self.assertEqual("register", register_request.get("type"))
341
342
 
342
343
  # wait for the rpc server to become responsive
343
- self.wait_for_rpc_response("backend", "auth", AccessRequest(name=settings.NAME, medium_id="GARIVO1", medium_type="lpr"), AccessResponse)
344
+ self.wait_for_rpc_response("backend", "auth",
345
+ AccessRequest(name=settings.NAME, medium_id="GARIVO1", medium_type="lpr"),
346
+ AccessResponse)
344
347
 
345
348
  # make a test request
346
- response = self.rpc("backend", "auth", AccessRequest(name=settings.NAME, medium_id="GARIVO1", medium_type="lpr"), AccessResponse)
349
+ response = self.rpc("backend", "auth",
350
+ AccessRequest(name=settings.NAME, medium_id="GARIVO1", medium_type="lpr"),
351
+ AccessResponse)
347
352
  self.assertEqual("GARIVO1", response.medium_id)
348
-
353
+
349
354
  finally:
350
355
  self.send_signal_to_process(process, signal.SIGTERM)
351
356
  self.assertCleanShutdown(process)
@@ -445,8 +450,49 @@ finally:
445
450
  Another fix is setting the `log_config` to `None`, but with this setting the Uvicorn log output is disabled
446
451
  for `python -m tox` command.
447
452
 
453
+ ## Utils
454
+
455
+ ### DeveloperError
456
+
457
+ Can be used to raise an error in the test code (e.g. when mocking a function and wanting an unimplemented error)
458
+
459
+ ```python
460
+ def test():
461
+ def mocker():
462
+ raise DeveloperError("This function should not be called")
463
+
464
+ with mock.patch("module.func", mocker):
465
+ with self.assertRaises(DeveloperError):
466
+ module.function_that_calls_func()
467
+ ```
468
+
469
+ ### wait_for_value
470
+
471
+ This function waits until the given `getter` function returns the expected value or the timeout is reached.
472
+ That is useful when you want to wait for a value to change in another thread.
473
+
474
+ If no `target` is given, it waits until the `getter` function returns a value that is different from the initial value.
475
+ **warning**: The getter function might return the 'changed' value in the initial call, which would lead to no change
476
+ happening.
477
+
478
+ `invert_target` can be set to True to wait for the getter function to return a value that is different from the target.
479
+
480
+ ```python
481
+ class Test(TestCase):
482
+ def get_value(self):
483
+ return self.whatever
484
+
485
+ def change_value(self):
486
+ time.sleep(1)
487
+ self.whatever = 2
488
+
489
+ def test(self):
490
+ self.whatever = 1
491
+ threading.Thread(target=self.change_value).start()
492
+ self.whatever = wait_for_value(self.get_value, 2)
493
+ ```
494
+
448
495
  ## Exit with Error 112
449
496
 
450
497
  Whenever the RPCServer finds a RPCResponse model containing a `status` field, a log line is printed and the process is
451
498
  terminated with error code 112. The log line might not be printed in some cases, so watch out for 112
452
-
@@ -483,19 +483,11 @@ class GlobalSettings:
483
483
  BROKER_SUB = broker_sub()
484
484
  BROKER_PUB = broker_pub()
485
485
 
486
- LOCAL_DEVELOPMENT = bool("LOCAL_DEVELOPMENT", False)
487
486
  COMPUTE_ID = compute_id()
488
487
  DAEMON = bool("DAEMON", False)
489
488
  DIST_FOLDER = dist_folder()
490
489
  DEV_DEVICE = dev_device()
491
490
 
492
- # redis
493
- REDIS_HOST = string("REDIS_HOST", "localhost")
494
- REDIS_PASSWORD = string("REDIS_PASSWORD", "") or None
495
- REDIS_PORT = int("REDIS_PORT", 6379)
496
- REDIS_DB = int("REDIS_DB", 0)
497
- REDIS_CONNECTION_STATUS_KEY = string("REDIS_CONNECTION_STATUS_KEY", "device_connection_status")
498
-
499
491
  # translation
500
492
  LOCALE_DIR = locale_dir()
501
493
  LANGUAGE = "" if testing() else string("LANGUAGE", "de").lower()
@@ -4,6 +4,7 @@ import time
4
4
  from enum import Enum
5
5
  from typing import Optional, Set
6
6
 
7
+ from openmodule import sentry
7
8
  from openmodule.dispatcher import MessageDispatcher
8
9
  from openmodule.models.base import ZMQMessage, OpenModuleModel
9
10
 
@@ -98,6 +99,7 @@ class ConnectionStatusListener:
98
99
  self._log.debug("Connection status message timeout")
99
100
  self._set(ConnectionStatus.shutdown)
100
101
 
102
+ @sentry.trace
101
103
  def get_current_status(self) -> ConnectionRPCResponse:
102
104
  """Checks the current_status by sending an RPC to om_rpc_client"""
103
105
  try:
@@ -9,6 +9,7 @@ from concurrent.futures.thread import ThreadPoolExecutor
9
9
  import zmq
10
10
  from typing import Optional
11
11
 
12
+ from openmodule import sentry
12
13
  from openmodule.alert import AlertHandler
13
14
  from openmodule.config import validate_config_module
14
15
  from openmodule.dispatcher import ZMQMessageDispatcher
@@ -71,9 +72,9 @@ class OpenModuleCore(threading.Thread):
71
72
  def _run(self):
72
73
  try:
73
74
  while True:
74
- topic, message = receive_message_from_socket(self.sub_socket)
75
- if topic is not None:
76
- self.messages.dispatch(topic, message)
75
+ with receive_message_from_socket(self.sub_socket) as (topic, message):
76
+ if topic is not None:
77
+ self.messages.dispatch(topic, message)
77
78
  except zmq.ContextTerminated:
78
79
  self.log.debug("context terminated, core shutting down")
79
80
  finally:
@@ -84,15 +85,16 @@ class OpenModuleCore(threading.Thread):
84
85
  def _run_internal(self):
85
86
  try:
86
87
  while True:
87
- topic, message = receive_message_from_socket(self.sub_socket_internal)
88
- if topic is not None:
89
- self._messages_internal.dispatch(topic, message)
90
- self.connection_listener.check_timeout()
88
+ with receive_message_from_socket(self.sub_socket_internal) as (topic, message):
89
+ if topic is not None:
90
+ self._messages_internal.dispatch(topic, message)
91
+ self.connection_listener.check_timeout()
91
92
  except zmq.ContextTerminated:
92
93
  pass
93
94
  finally:
94
95
  self.sub_socket_internal.close()
95
96
 
97
+ @sentry.trace(op="topic.send")
96
98
  def publish(self, message: ZMQMessage, topic: str):
97
99
  assert isinstance(topic, str), "topic must be a string"
98
100
 
@@ -134,10 +136,10 @@ def print_environment(core: OpenModuleCore):
134
136
  )
135
137
 
136
138
 
137
- def init_openmodule(config, sentry=None, logging=True, dsgvo=True,
139
+ def init_openmodule(config, *, dsn: str = None, sentry=None, logging=True, dsgvo=True,
138
140
  health_handler: Optional[HealthHandlerType] = None,
139
141
  context=None, database=False, catch_sigterm=True,
140
- dispatcher_max_threads=1, wait_for_broker=True) -> OpenModuleCore:
142
+ dispatcher_max_threads=1, wait_for_broker=True, **sentry_kwargs) -> OpenModuleCore:
141
143
  if health_handler:
142
144
  warnings.warn(
143
145
  "health_handler is deprecated, and will simply be ignored. Please use metrics "
@@ -172,18 +174,16 @@ def init_openmodule(config, sentry=None, logging=True, dsgvo=True,
172
174
  # we activate sentry if
173
175
  # -> sentry=None (default) -> then we only activate in production
174
176
  # -> sentry=True/False this overrides and we activate/deactivate as desired
175
- activate_sentry = False
176
177
  if sentry is None:
177
- if should_activate_sentry(config):
178
- activate_sentry = True
179
- else:
178
+ sentry = should_activate_sentry()
179
+ if not sentry:
180
180
  _core_thread.log.info("not activating sentry in debug or test mode")
181
- else:
182
- activate_sentry = sentry
183
181
 
184
- if activate_sentry:
182
+ if sentry:
183
+ if dsn is None:
184
+ raise ValueError("sentry DSN is required")
185
+ init_sentry(dsn, **sentry_kwargs)
185
186
  _core_thread.sentry_was_initialized = True
186
- init_sentry(_core_thread)
187
187
 
188
188
  if dsgvo:
189
189
  init_dsgvo_config()
@@ -12,7 +12,9 @@ from typing import Union, Optional, Callable, DefaultDict, List, Dict, TypeVar,
12
12
 
13
13
  import zmq
14
14
  from pydantic import ValidationError, BaseModel, parse_obj_as
15
+ from sentry_sdk.utils import qualname_from_function
15
16
 
17
+ from openmodule import sentry
16
18
  from openmodule.config import settings
17
19
  from openmodule.models.base import ZMQMessage
18
20
  from openmodule.utils.schema import Schema
@@ -199,26 +201,28 @@ class MessageDispatcher:
199
201
  listeners = self.listeners.get(topic, [])
200
202
  for listener in listeners:
201
203
  if listener.matches(message):
202
- self.executor.submit(self.execute, listener, message)
204
+ self.executor.submit(self.execute, topic, listener, message)
203
205
 
204
- def execute(self, listener: Listener, message: Dict):
205
- try:
206
- parsed_message = parse_obj_as(listener.message_class, message)
207
- except ValidationError as e:
208
- if self.raise_validation_errors:
209
- raise e from None
210
- else:
211
- self.log.exception("Invalid message received")
212
- else:
206
+ def execute(self, topic: str, listener: Listener, message: Dict):
207
+ with sentry.continue_trace_zmq_message_process(topic, message):
213
208
  try:
214
- listener.handler(parsed_message)
215
- except zmq.ContextTerminated:
216
- raise
217
- except Exception as e:
218
- if self.raise_handler_errors:
209
+ parsed_message = parse_obj_as(listener.message_class, message)
210
+ except ValidationError as e:
211
+ if self.raise_validation_errors:
219
212
  raise e from None
220
213
  else:
221
- self.log.exception("Error in message handler")
214
+ self.log.exception("Invalid message received")
215
+ else:
216
+ try:
217
+ with sentry.trace(f"message_handler.{qualname_from_function(listener.handler)}"):
218
+ listener.handler(parsed_message)
219
+ except zmq.ContextTerminated:
220
+ raise
221
+ except Exception as e:
222
+ if self.raise_handler_errors:
223
+ raise e from None
224
+ else:
225
+ self.log.exception("Error in message handler")
222
226
 
223
227
 
224
228
  class SubscribingMessageDispatcher(MessageDispatcher):
@@ -0,0 +1,34 @@
1
+ import logging
2
+ import sys
3
+
4
+ import requests
5
+
6
+ _patched_exceptions = set()
7
+
8
+
9
+ def _patch_requests_library():
10
+ """Adds the response text to the string representation of a requests.RequestException"""
11
+ if requests.RequestException in _patched_exceptions:
12
+ return
13
+ _patched_exceptions.add(requests.RequestException)
14
+
15
+ original_exception_string = requests.RequestException.__str__
16
+
17
+ def new_exception_string(self: requests.RequestException):
18
+ ret_str = original_exception_string(self)
19
+ if self.response is not None:
20
+ ret_str = f"{ret_str}: {self.response.text[:1000]}"
21
+ return ret_str
22
+
23
+ setattr(requests.RequestException, "__str__", new_exception_string)
24
+
25
+
26
+ def init_logging(core):
27
+ assert hasattr(core.config, "LOG_LEVEL"), (
28
+ "LOG_LEVEL setting not found in your config. In order to use logging please add \n"
29
+ "> LOG_LEVEL = config.log_level()\n"
30
+ "to your config.py"
31
+ )
32
+ _patch_requests_library()
33
+ logging.basicConfig(level=core.config.LOG_LEVEL, stream=sys.stdout)
34
+ logging.captureWarnings(True)
@@ -3,11 +3,13 @@ import logging
3
3
  import random
4
4
  import string
5
5
  import time
6
+ from contextlib import contextmanager
6
7
  from typing import Optional, Tuple, Dict
7
8
 
8
9
  import orjson
9
10
  import zmq
10
11
 
12
+ from openmodule import sentry
11
13
  from openmodule.dispatcher import MessageDispatcher
12
14
  from openmodule.models.base import ZMQMessage
13
15
 
@@ -80,16 +82,19 @@ def wait_for_connection(dispatcher: MessageDispatcher, pub_socket=None, pub_lock
80
82
  raise TimeoutError("could not connect to the message broker in time")
81
83
 
82
84
 
85
+ @contextmanager
83
86
  def receive_message_from_socket(sub_socket: zmq.Socket) -> Tuple[Optional[str], Optional[Dict]]:
84
87
  """
85
88
  :param sub_socket: zmq socket to receive
86
- :return: returns None if an invalid message was received
87
- otherwise returns a tuple containing (topic: str, message: dict)
89
+ Enters a sentry trace for the received message. For this reason, the function should be used as a context manager.
90
+ :yields: a tuple containing (None, None) if an invalid message was received
91
+ otherwise yields a tuple containing (topic: str, message: dict)
88
92
  """
89
93
  parts = sub_socket.recv_multipart()
90
94
  if len(parts) != 2:
91
95
  logging.error(f"received a zmq message with an invalid number of parts: {len(parts)}")
92
- return None, None
96
+ yield None, None
97
+ return
93
98
 
94
99
  topic, message = parts
95
100
 
@@ -97,10 +102,12 @@ def receive_message_from_socket(sub_socket: zmq.Socket) -> Tuple[Optional[str],
97
102
  message_dict = orjson.loads(message)
98
103
  except orjson.JSONDecodeError as e:
99
104
  logging.error(f"received a zmq message with an invalid json. parsing error: {str(e)}")
100
- return None, None
105
+ yield None, None
101
106
  else:
102
107
  if not isinstance(message_dict, dict):
103
108
  logging.error(f"received a zmq message which was not a dict but a {type(message)}")
104
- return None, None
109
+ yield None, None
105
110
  else:
106
- return topic.decode("utf8"), message_dict
111
+ decoded_topic = topic.decode("utf8")
112
+ with sentry.continue_trace_zmq_message_receive(decoded_topic, message_dict):
113
+ yield decoded_topic, message_dict
@@ -13,7 +13,7 @@ from dateutil.tz import UTC
13
13
  from pydantic import Field, BaseModel, validator, root_validator
14
14
  from pydantic.main import ROOT_KEY
15
15
 
16
- from openmodule import config
16
+ from openmodule import config, sentry
17
17
  from openmodule.config import settings
18
18
 
19
19
 
@@ -139,6 +139,8 @@ class ZMQMessage(OpenModuleModel):
139
139
  timestamp: datetime = Field(default_factory=lambda: datetime.utcnow())
140
140
  name: str = Field(default_factory=lambda: settings.NAME)
141
141
  type: str
142
+ baggage: Optional[str] = Field(default_factory=sentry.get_baggage)
143
+ sentry_trace: Optional[str] = Field(default_factory=sentry.get_traceparent, alias="sentry-trace")
142
144
 
143
145
  _tz_timestamp = timezone_validator("timestamp")
144
146