openmodule 14.0.1__tar.gz → 14.0.3__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.
- {openmodule-14.0.1 → openmodule-14.0.3}/ChangeLog +10 -13
- {openmodule-14.0.1/openmodule.egg-info → openmodule-14.0.3}/PKG-INFO +1 -1
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/sentry.md +6 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/dispatcher.py +6 -4
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/rpc/server.py +14 -11
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/sentry.py +72 -16
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/io.py +17 -16
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/kv_store.py +21 -7
- {openmodule-14.0.1 → openmodule-14.0.3/openmodule.egg-info}/PKG-INFO +1 -1
- openmodule-14.0.3/openmodule.egg-info/pbr.json +1 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule.egg-info/requires.txt +1 -1
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/sentry.py +12 -10
- {openmodule-14.0.1 → openmodule-14.0.3}/requirements.txt +1 -1
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_sentry.py +164 -20
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_kv_store.py +28 -5
- openmodule-14.0.1/openmodule.egg-info/pbr.json +0 -1
- {openmodule-14.0.1 → openmodule-14.0.3}/.gitlab-ci.yml +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/AUTHORS +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/LICENSE +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/README.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/access_service.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/anonymization.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/cleanup.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/coding_standard.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/commands.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/connection_status_listener.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/csv_export.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/database.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/deprecated.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/deprecated_code/README.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/deprecated_code/access_service/openmodule/models/access_service.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/deprecated_code/access_service/openmodule/utils/access_service.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/deprecated_code/access_service/openmodule_test/access_service.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/deprecated_code/access_service/tests/test_utils_access_service.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/deprecated_code/api/openmodule/utils/api.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/deprecated_code/api/openmodule_test/api.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/deprecated_code/api/tests/test_utils_api.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/deprecated_code/package_reader/openmodule/utils/package_reader.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/deprecated_code/package_reader/openmodule_test/fake_package_creator.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/deprecated_code/package_reader/tests/test_package_reader.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/event_sending.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/getting_started.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/health.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/images/broker.drawio.png +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/known_issues.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/migrations.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/package_reader.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/rpc.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/settings.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/settings_provider.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/testing.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/translation.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/docs/utils.md +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/alert.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/config.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/connection_status.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/core.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/database/custom_types.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/database/database.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/database/env.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/database/migration.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/health.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/logging.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/messaging.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/models/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/models/access_service.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/models/alert.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/models/base.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/models/io.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/models/kv_store.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/models/presence.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/models/privacy.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/models/rpc.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/models/settings.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/models/validation.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/models/vehicle.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/rpc/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/rpc/client.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/rpc/common.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/threading.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/access_service.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/charset.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/cleanup.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/csv_export.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/databox.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/db_helper.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/eventlog.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/matching.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/misc_functions.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/package_reader.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/presence.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/schema.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/settings.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/translation.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule/utils/validation.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule.egg-info/SOURCES.txt +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule.egg-info/dependency_links.txt +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule.egg-info/not-zip-safe +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule.egg-info/top_level.txt +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_commands/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_commands/setup.cfg +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_commands/setup.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_commands/translate.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/alert.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/connection_status.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/core.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/database.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/eventlistener.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/files.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/gate.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/health.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/interrupt.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/io_simulator.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/package_reader.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/presence.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/requirements.txt +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/rpc.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/settings.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/setup.cfg +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/setup.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/utils.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/openmodule_test/zeromq.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/setup.cfg +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/setup.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/test-requirements.txt +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/config.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/database_models_migration.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/database_models_test.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/invalid_database/alembic/README +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/invalid_database/alembic/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/invalid_database/alembic/env.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/invalid_database/alembic/script.py.mako +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/invalid_database/alembic/versions/ff26e54332f9_datetime_models.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/invalid_database/alembic.ini +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/invalid_database/makemigration.sh +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_double_column_delete_error/alembic/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_double_column_delete_error/alembic/env.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_double_column_delete_error/alembic/script.py.mako +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_double_column_delete_error/alembic/versions/812a3e5b8517_initial.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_double_column_delete_error/alembic/versions/a7ea100a784f_key_error.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_double_column_delete_error/alembic.ini +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_double_column_delete_error/makemigration.sh +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_no_such_table_error/alembic/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_no_such_table_error/alembic/env.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_no_such_table_error/alembic/script.py.mako +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_no_such_table_error/alembic/versions/812a3e5b8517_initial.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_no_such_table_error/alembic/versions/a7ea100a784f_no_such_table_error.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_no_such_table_error/alembic.ini +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_no_such_table_error/makemigration.sh +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_test_database/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_test_database/alembic/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_test_database/alembic/env.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_test_database/alembic/script.py.mako +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_test_database/alembic/versions/19789aa5361c_initial.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_test_database/alembic/versions/19d887929ae7_alter.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_test_database/alembic/versions/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_test_database/alembic.ini +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_test_database/alembic_migration_test_database.sqlite3 +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/migration_test_database/makemigration.sh +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/configs/config.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/configs/test_config.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/configs/test_config_1.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/standard_schemes/DEFAULT-10.yml +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/standard_schemes/DEFAULT-20.yml +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/standard_schemes/LEGACY-0.yml +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/translation/locale/de/LC_MESSAGES/translation.mo +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/translation/locale/de/LC_MESSAGES/translation.po +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/translation/locale/en/LC_MESSAGES/translation.mo +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/translation/locale/en/LC_MESSAGES/translation.po +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/translation/locale/translation.pot +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/translation/translate.sh +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/utils_matching/A-10.yml +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/utils_matching/A-20.yml +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/utils_matching/DEFAULT-10.yml +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/utils_matching/DEFAULT-20.yml +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/utils_matching/DEFAULT-30.yml +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/utils_matching/LEGACY-0.yml +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/utils_matching/TEST-10.yml +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/utils_matching/TEST-20.yml +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/utils_matching/TEST-30.yml +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/resources/utils_matching/TEST-40.yml +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/sentry_main.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_access_service_database/alembic/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_access_service_database/alembic/env.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_access_service_database/alembic/script.py.mako +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_access_service_database/alembic/versions/7bd4fcd38fde_removed_nfc_and_pin.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_access_service_database/alembic/versions/9ca98a2e5674_added_parksettings_id.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_access_service_database/alembic/versions/c821971f9230_initial.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_access_service_database/alembic.ini +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_access_service_database/makemigration.sh +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_alembic_migrations.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_alert.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_checks.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_config.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_connection_status.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_core.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_database/alembic/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_database/alembic/env.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_database/alembic/script.py.mako +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_database/alembic/versions/32b8c728abbf_initial.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_database/alembic.ini +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_database/makemigration.sh +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_database.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_dispatcher.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_health.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_interrupt.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_io_listen.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_kv_store_database/alembic/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_kv_store_database/alembic/env.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_kv_store_database/alembic/script.py.mako +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_kv_store_database/alembic/versions/9c5c944221f4_deprecated_kv_entry_example.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_kv_store_database/alembic/versions/c55a69026a25_initial.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_kv_store_database/alembic.ini +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_kv_store_database/makemigration.sh +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_kv_store_multiple_database/alembic/README +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_kv_store_multiple_database/alembic/__init__.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_kv_store_multiple_database/alembic/env.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_kv_store_multiple_database/alembic/script.py.mako +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_kv_store_multiple_database/alembic/versions/cdb3214131a9_initial.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_kv_store_multiple_database/alembic.ini +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_kv_store_multiple_database/makemigration.sh +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_logging.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_messaging.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_mockrpcclient.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_model.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_rpc.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_schema.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_test_alert.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_test_gate.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_test_zeromq.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_access_service.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_charset.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_cleanup.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_csv_export.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_databox.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_eventlog.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_kv_store_multiple.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_matching.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_misc_functions.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_package_reader.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_presence.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_settings.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_validation.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tests/test_utils_vehicle.py +0 -0
- {openmodule-14.0.1 → openmodule-14.0.3}/tox.ini +0 -0
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
CHANGES
|
|
2
2
|
=======
|
|
3
3
|
|
|
4
|
+
v14.0.3
|
|
5
|
+
-------
|
|
6
|
+
|
|
7
|
+
* OM-941 Sentry Bugfix
|
|
8
|
+
|
|
9
|
+
v14.0.2
|
|
10
|
+
-------
|
|
11
|
+
|
|
12
|
+
* Sentry improvements
|
|
13
|
+
|
|
4
14
|
v14.0.1
|
|
5
15
|
-------
|
|
6
16
|
|
|
@@ -161,8 +171,6 @@ v12.0.0.rc0
|
|
|
161
171
|
* settings models update
|
|
162
172
|
* made gate\_control/day\_mode have no scope
|
|
163
173
|
* schedule exports utility
|
|
164
|
-
* SettingsProvider docs
|
|
165
|
-
* SettingsProvider docs
|
|
166
174
|
|
|
167
175
|
v11.1.1
|
|
168
176
|
-------
|
|
@@ -197,14 +205,3 @@ v10.0.5
|
|
|
197
205
|
-------
|
|
198
206
|
|
|
199
207
|
* fixed problem in presence listener
|
|
200
|
-
* README for settings + backend
|
|
201
|
-
|
|
202
|
-
v10.0.4
|
|
203
|
-
-------
|
|
204
|
-
|
|
205
|
-
* Improvements for backend and package reader
|
|
206
|
-
|
|
207
|
-
v10.0.3
|
|
208
|
-
-------
|
|
209
|
-
|
|
210
|
-
* added freezegun and fakeredis to openmodule requirements
|
|
@@ -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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
198
|
-
|
|
199
|
-
if
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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(
|
|
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,35 @@ 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
|
+
|
|
26
|
+
|
|
27
|
+
@contextmanager
|
|
28
|
+
def noop_context():
|
|
29
|
+
yield
|
|
23
30
|
|
|
24
31
|
|
|
25
|
-
def continue_trace_zmq_message_receive(topic: str, message: dict):
|
|
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
|
+
return _continue_trace_zmq_message(topic, message, "topic.receive", **kwargs)
|
|
33
40
|
|
|
34
41
|
|
|
35
|
-
def continue_trace_zmq_message_process(topic: str, message: dict):
|
|
42
|
+
def continue_trace_zmq_message_process(topic: str, message: dict, **kwargs):
|
|
36
43
|
"""
|
|
37
44
|
Continues a sentry trace for a zmq message executor. (If already in a transaction, it will create a scope instead)
|
|
38
45
|
Our ZMQMessage class contains the baggage and sentry-trace fields required for this, so the dict must contain these.
|
|
39
46
|
:param topic: The topic of the message (as received from the ZMQ socket and decoded)
|
|
40
47
|
:param message: The ZMQMessage as a dict (as received from the ZMQ socket and json loaded)
|
|
41
48
|
"""
|
|
42
|
-
|
|
49
|
+
if topic in _topics_to_ignore:
|
|
50
|
+
return noop_context()
|
|
51
|
+
return _continue_trace_zmq_message(topic, message, "topic.process", **kwargs)
|
|
43
52
|
|
|
44
53
|
|
|
45
54
|
@overload # pragma: no cover
|
|
@@ -48,6 +57,7 @@ def trace(
|
|
|
48
57
|
op: Union[sentry_sdk.consts.OP, str] = sentry_sdk.consts.OP.FUNCTION,
|
|
49
58
|
trace_headers: Optional[dict] = None,
|
|
50
59
|
force_new_transaction: bool = False,
|
|
60
|
+
force_no_trace: bool = False,
|
|
51
61
|
**span_kwargs) -> Callable[[Callable], Callable]:
|
|
52
62
|
...
|
|
53
63
|
|
|
@@ -58,6 +68,7 @@ def trace(
|
|
|
58
68
|
op: Union[sentry_sdk.consts.OP, str] = sentry_sdk.consts.OP.FUNCTION,
|
|
59
69
|
trace_headers: Optional[dict] = None,
|
|
60
70
|
force_new_transaction: bool = False,
|
|
71
|
+
force_no_trace: bool = False,
|
|
61
72
|
**span_kwargs) -> Union[Callable, Generator[sentry_sdk.tracing.Span, None, None]]:
|
|
62
73
|
...
|
|
63
74
|
|
|
@@ -68,6 +79,7 @@ def trace(
|
|
|
68
79
|
op: Union[sentry_sdk.consts.OP, str] = sentry_sdk.consts.OP.FUNCTION,
|
|
69
80
|
trace_headers: Optional[dict] = None,
|
|
70
81
|
force_new_transaction: bool = False,
|
|
82
|
+
force_no_trace: bool = False,
|
|
71
83
|
**span_kwargs) -> Callable:
|
|
72
84
|
...
|
|
73
85
|
|
|
@@ -77,6 +89,7 @@ def trace(
|
|
|
77
89
|
op: Union[sentry_sdk.consts.OP, str] = sentry_sdk.consts.OP.FUNCTION,
|
|
78
90
|
trace_headers: Optional[dict] = None,
|
|
79
91
|
force_new_transaction: bool = False,
|
|
92
|
+
force_no_trace: bool = False,
|
|
80
93
|
**span_kwargs):
|
|
81
94
|
"""
|
|
82
95
|
Trace a function or a block of code.
|
|
@@ -86,6 +99,7 @@ def trace(
|
|
|
86
99
|
span_kwargs["op"] = op
|
|
87
100
|
span_kwargs["trace_headers"] = trace_headers
|
|
88
101
|
span_kwargs["force_new_transaction"] = force_new_transaction
|
|
102
|
+
span_kwargs["force_no_trace"] = force_no_trace
|
|
89
103
|
if name is None:
|
|
90
104
|
return _Trace(**span_kwargs)
|
|
91
105
|
elif callable(name):
|
|
@@ -109,6 +123,14 @@ def get_baggage() -> Optional[str]:
|
|
|
109
123
|
get_traceparent = sentry_sdk.get_traceparent
|
|
110
124
|
|
|
111
125
|
|
|
126
|
+
def get_trace_headers(empty_if_not_sampled: bool = False) -> dict:
|
|
127
|
+
if empty_if_not_sampled:
|
|
128
|
+
span = sentry_sdk.get_current_span()
|
|
129
|
+
if span and not span.sampled:
|
|
130
|
+
return {}
|
|
131
|
+
return {"sentry-trace": get_traceparent(), "baggage": get_baggage()}
|
|
132
|
+
|
|
133
|
+
|
|
112
134
|
class _Trace:
|
|
113
135
|
"""
|
|
114
136
|
Context manager for sentry tracing.
|
|
@@ -118,9 +140,11 @@ class _Trace:
|
|
|
118
140
|
force_new_transaction: bool
|
|
119
141
|
ctx: Any
|
|
120
142
|
|
|
121
|
-
def __init__(self, *, trace_headers: Optional[dict] = None, force_new_transaction: bool = False,
|
|
143
|
+
def __init__(self, *, trace_headers: Optional[dict] = None, force_new_transaction: bool = False,
|
|
144
|
+
force_no_trace: bool = False, **span_kwargs):
|
|
122
145
|
self.trace_headers = trace_headers
|
|
123
146
|
self.force_new_transaction = force_new_transaction
|
|
147
|
+
self.force_no_trace = force_no_trace
|
|
124
148
|
self.span_kwargs = span_kwargs
|
|
125
149
|
|
|
126
150
|
@contextmanager
|
|
@@ -130,21 +154,40 @@ class _Trace:
|
|
|
130
154
|
Otherwise, start a new span.
|
|
131
155
|
If given a trace_headers dict, it will continue the trace with the given headers.
|
|
132
156
|
"""
|
|
157
|
+
force_no_trace = self.force_no_trace or self.span_kwargs.get("name") in _functions_to_ignore
|
|
158
|
+
|
|
159
|
+
def set_context():
|
|
160
|
+
for key, value in extras.items():
|
|
161
|
+
sentry_sdk.set_extra(key, value)
|
|
162
|
+
sentry_sdk.set_tags(tags)
|
|
163
|
+
for key, value in contexts.items():
|
|
164
|
+
sentry_sdk.set_context(key, value)
|
|
165
|
+
|
|
166
|
+
extras = self.span_kwargs.pop("extras", {})
|
|
167
|
+
tags = self.span_kwargs.pop("tags", {})
|
|
168
|
+
contexts = self.span_kwargs.pop("contexts", {})
|
|
133
169
|
span = sentry_sdk.get_current_span()
|
|
134
170
|
if span is None or self.force_new_transaction:
|
|
135
171
|
with sentry_sdk.isolation_scope():
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
transaction = sentry_sdk.continue_trace(self.trace_headers, **self.span_kwargs)
|
|
139
|
-
with sentry_sdk.start_transaction(transaction=transaction, **self.span_kwargs) as transaction:
|
|
140
|
-
if transaction:
|
|
141
|
-
transaction.description = transaction.name
|
|
172
|
+
if force_no_trace:
|
|
173
|
+
set_context()
|
|
142
174
|
yield
|
|
143
|
-
|
|
175
|
+
else:
|
|
176
|
+
transaction: Optional[sentry_sdk.tracing.Transaction] = None
|
|
177
|
+
if self.trace_headers and "sentry-trace" in self.trace_headers:
|
|
178
|
+
transaction = sentry_sdk.continue_trace(self.trace_headers, **self.span_kwargs)
|
|
179
|
+
with sentry_sdk.start_transaction(transaction=transaction, **self.span_kwargs) as transaction:
|
|
180
|
+
if transaction:
|
|
181
|
+
transaction.description = transaction.name
|
|
182
|
+
set_context()
|
|
183
|
+
yield
|
|
184
|
+
elif not force_no_trace and span.sampled:
|
|
144
185
|
self.span_kwargs.pop("source", None)
|
|
145
186
|
with sentry_sdk.start_span(**self.span_kwargs):
|
|
187
|
+
set_context()
|
|
146
188
|
yield
|
|
147
189
|
else: # No need to start a span if the parent is not sampled
|
|
190
|
+
set_context()
|
|
148
191
|
yield
|
|
149
192
|
|
|
150
193
|
def __enter__(self) -> None:
|
|
@@ -179,9 +222,10 @@ class _Trace:
|
|
|
179
222
|
return func_with_tracing
|
|
180
223
|
|
|
181
224
|
|
|
182
|
-
def _continue_trace_zmq_message(topic: str, message: dict, op: str):
|
|
225
|
+
def _continue_trace_zmq_message(topic: str, message: dict, op: str, **kwargs):
|
|
183
226
|
name = f"{topic}/{message.get('type', '')}"
|
|
184
|
-
return _Trace(trace_headers=message, op=op, name=name, source="zmq", origin="auto.zmq"
|
|
227
|
+
return _Trace(trace_headers=message, op=op, name=name, source="zmq", origin="auto.zmq",
|
|
228
|
+
force_no_trace=topic in _topics_to_ignore, **kwargs)
|
|
185
229
|
|
|
186
230
|
|
|
187
231
|
class StoringTransport(sentry_sdk.transport.HttpTransport):
|
|
@@ -349,6 +393,11 @@ def _patch_sentry_method():
|
|
|
349
393
|
|
|
350
394
|
def _update_sentry_config(kwargs: dict):
|
|
351
395
|
# Set default values
|
|
396
|
+
global _topics_to_ignore, _functions_to_ignore
|
|
397
|
+
_topics_to_ignore = kwargs.pop("topics_to_ignore", ["io"])
|
|
398
|
+
_functions_to_ignore = kwargs.pop(
|
|
399
|
+
"functions_to_ignore", ["message_handler.openmodule.utils.io.IoListener._on_io_message"])
|
|
400
|
+
|
|
352
401
|
if "traces_sampler" not in kwargs:
|
|
353
402
|
kwargs.setdefault("traces_sample_rate", 0.0001)
|
|
354
403
|
if "profiles_sampler" not in kwargs:
|
|
@@ -371,6 +420,8 @@ def _update_sentry_config(kwargs: dict):
|
|
|
371
420
|
kwargs["extras"]["name"] = settings.NAME
|
|
372
421
|
if hasattr(settings, "GATE"):
|
|
373
422
|
kwargs["extras"]["gate"] = settings.GATE
|
|
423
|
+
kwargs.setdefault("contexts", {})
|
|
424
|
+
kwargs["contexts"]["device"] = {"name": settings.RESOURCE, "model": settings.RESOURCE}
|
|
374
425
|
|
|
375
426
|
|
|
376
427
|
def init_sentry(dsn: str, **kwargs):
|
|
@@ -388,12 +439,17 @@ def init_sentry(dsn: str, **kwargs):
|
|
|
388
439
|
|
|
389
440
|
_update_sentry_config(kwargs)
|
|
390
441
|
extras = kwargs.pop("extras", {})
|
|
442
|
+
contexts = kwargs.pop("contexts", {})
|
|
443
|
+
tags = kwargs.pop("tags", {})
|
|
391
444
|
sentry_sdk.init(dsn=dsn, **kwargs)
|
|
392
445
|
|
|
393
446
|
_patch_requests_library()
|
|
394
447
|
_patch_sentry_method()
|
|
395
448
|
for key, value in extras.items():
|
|
396
449
|
sentry_sdk.get_global_scope().set_extra(key, value)
|
|
450
|
+
sentry_sdk.get_global_scope().set_tags(tags)
|
|
451
|
+
for key, value in contexts.items():
|
|
452
|
+
sentry_sdk.get_global_scope().set_context(key, value)
|
|
397
453
|
|
|
398
454
|
|
|
399
455
|
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
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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")
|
|
@@ -3,6 +3,7 @@ import logging
|
|
|
3
3
|
import random
|
|
4
4
|
import threading
|
|
5
5
|
import time
|
|
6
|
+
import uuid
|
|
6
7
|
import warnings
|
|
7
8
|
from typing import Type, Optional, List, Union, Dict
|
|
8
9
|
|
|
@@ -193,7 +194,7 @@ class KVStore:
|
|
|
193
194
|
additional_kvs = current_kvs
|
|
194
195
|
return KVSyncResponse(additions=additional_kvs, changes=changed_kvs, missing=missing_kvs)
|
|
195
196
|
|
|
196
|
-
def _log_sync_rpc_response(self, rpc_entry: RPCClient.RPCEntry) -> bool:
|
|
197
|
+
def _log_sync_rpc_response(self, rpc_entry: RPCClient.RPCEntry, conn_id: str) -> bool:
|
|
197
198
|
"""
|
|
198
199
|
Waits for the RPC to finish and logs the response
|
|
199
200
|
:return: if successful
|
|
@@ -203,11 +204,22 @@ class KVStore:
|
|
|
203
204
|
rpc_entry.result(ServerSyncResponse)
|
|
204
205
|
return True
|
|
205
206
|
except RPCClient.TimeoutError:
|
|
206
|
-
|
|
207
|
+
if core().connection_listener.changed(conn_id):
|
|
208
|
+
self.log.warning("Connection loss during sync")
|
|
209
|
+
else:
|
|
210
|
+
self.log.error("Timeout syncing kvs")
|
|
207
211
|
except RPCClient.CancelError:
|
|
208
|
-
|
|
212
|
+
if core().connection_listener.changed(conn_id):
|
|
213
|
+
self.log.warning("Connection loss during sync")
|
|
214
|
+
else:
|
|
215
|
+
self.log.error("Cancelled waiting for result of syncing kvs")
|
|
209
216
|
except RPCClient.ValidationError:
|
|
210
217
|
self.log.exception("Error parsing sync response")
|
|
218
|
+
except RPCClient.RPCServerError as e:
|
|
219
|
+
if len(e.args) > 0 and e.args[0] == "request_timeout" and core().connection_listener.changed(conn_id):
|
|
220
|
+
self.log.warning("Connection loss during sync")
|
|
221
|
+
else:
|
|
222
|
+
self.log.exception("Error on server side in sync")
|
|
211
223
|
except (RPCClient.ServerHandlerError, RPCClient.ServerValidationError, RPCClient.ServerFilterError):
|
|
212
224
|
self.log.exception("Error on server side in sync")
|
|
213
225
|
except Exception:
|
|
@@ -215,9 +227,9 @@ class KVStore:
|
|
|
215
227
|
return False
|
|
216
228
|
|
|
217
229
|
@sentry.trace
|
|
218
|
-
def sync(self) -> bool:
|
|
230
|
+
def sync(self, conn_id: str) -> bool:
|
|
219
231
|
self.sync_rpc_entry = self.sync_with_server()
|
|
220
|
-
success = self._log_sync_rpc_response(self.sync_rpc_entry)
|
|
232
|
+
success = self._log_sync_rpc_response(self.sync_rpc_entry, conn_id)
|
|
221
233
|
self.sync_rpc_entry = None
|
|
222
234
|
if success: # if sync was successful cancel retries
|
|
223
235
|
return True
|
|
@@ -291,6 +303,7 @@ class KVStoreHandler:
|
|
|
291
303
|
|
|
292
304
|
def run(self):
|
|
293
305
|
"""We only sync on startup and on reconnect"""
|
|
306
|
+
conn_id = uuid.uuid4().hex
|
|
294
307
|
try:
|
|
295
308
|
while self.running:
|
|
296
309
|
if self._wait_for_change_to_online():
|
|
@@ -305,7 +318,8 @@ class KVStoreHandler:
|
|
|
305
318
|
ConnectionStatus.online):
|
|
306
319
|
# cancel trying to sync if offline
|
|
307
320
|
break
|
|
308
|
-
|
|
321
|
+
core().connection_listener.changed(conn_id)
|
|
322
|
+
if store.sync(conn_id):
|
|
309
323
|
# if sync was successful cancel retries
|
|
310
324
|
break
|
|
311
325
|
# we try again as long we are still alive
|
|
@@ -347,7 +361,7 @@ class KVStoreWithChangedNotification(KVStore):
|
|
|
347
361
|
changed += list(old_values.keys())
|
|
348
362
|
return changed
|
|
349
363
|
|
|
350
|
-
def _send_changed_notification(self, new_values: Dict[str, str], old_values: Dict[str, str]):
|
|
364
|
+
def _send_changed_notification(self, new_values: Dict[str, str], old_values: Dict[str, str]): # pragma: no cover
|
|
351
365
|
"""
|
|
352
366
|
consider using self._find_changed_kvs when implementing this
|
|
353
367
|
also make sure your db model has a meaningful `comparison_value` method
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"git_version": "03b80ec", "is_release": true}
|
|
@@ -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.
|
|
23
|
+
with self.envelopes_lock:
|
|
24
|
+
self.envelopes.append(envelope)
|
|
22
25
|
|
|
23
26
|
def get_envelopes(self, clear: bool = True) -> List[Envelope]:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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.
|
|
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
|
-
|
|
63
|
-
|
|
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)
|