port-ocean 0.22.10__tar.gz → 0.22.11__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.

Potentially problematic release.


This version of port-ocean might be problematic. Click here for more details.

Files changed (194) hide show
  1. {port_ocean-0.22.10 → port_ocean-0.22.11}/PKG-INFO +1 -1
  2. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/port/mixins/integrations.py +45 -0
  3. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/entities_state_applier/port/applier.py +6 -2
  4. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/resync_state_updater/updater.py +7 -1
  5. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/integrations/mixins/sync_raw.py +11 -4
  6. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/helpers/metric/metric.py +74 -40
  7. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/helpers/metric/utils.py +0 -2
  8. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/ocean.py +11 -8
  9. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/handlers/mixins/test_sync_raw.py +236 -10
  10. {port_ocean-0.22.10 → port_ocean-0.22.11}/pyproject.toml +1 -1
  11. {port_ocean-0.22.10 → port_ocean-0.22.11}/LICENSE.md +0 -0
  12. {port_ocean-0.22.10 → port_ocean-0.22.11}/README.md +0 -0
  13. {port_ocean-0.22.10 → port_ocean-0.22.11}/integrations/_infra/Dockerfile.Deb +0 -0
  14. {port_ocean-0.22.10 → port_ocean-0.22.11}/integrations/_infra/Dockerfile.alpine +0 -0
  15. {port_ocean-0.22.10 → port_ocean-0.22.11}/integrations/_infra/Dockerfile.base.builder +0 -0
  16. {port_ocean-0.22.10 → port_ocean-0.22.11}/integrations/_infra/Dockerfile.base.runner +0 -0
  17. {port_ocean-0.22.10 → port_ocean-0.22.11}/integrations/_infra/Dockerfile.dockerignore +0 -0
  18. {port_ocean-0.22.10 → port_ocean-0.22.11}/integrations/_infra/Makefile +0 -0
  19. {port_ocean-0.22.10 → port_ocean-0.22.11}/integrations/_infra/grpcio.sh +0 -0
  20. {port_ocean-0.22.10 → port_ocean-0.22.11}/integrations/_infra/init.sh +0 -0
  21. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/__init__.py +0 -0
  22. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/bootstrap.py +0 -0
  23. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/__init__.py +0 -0
  24. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cli.py +0 -0
  25. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/commands/__init__.py +0 -0
  26. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/commands/defaults/__init___.py +0 -0
  27. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/commands/defaults/clean.py +0 -0
  28. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/commands/defaults/dock.py +0 -0
  29. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/commands/defaults/group.py +0 -0
  30. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/commands/list_integrations.py +0 -0
  31. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/commands/main.py +0 -0
  32. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/commands/new.py +0 -0
  33. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/commands/pull.py +0 -0
  34. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/commands/sail.py +0 -0
  35. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/commands/version.py +0 -0
  36. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/__init__.py +0 -0
  37. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/cookiecutter.json +0 -0
  38. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/extensions.py +0 -0
  39. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/hooks/post_gen_project.py +0 -0
  40. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.env.example +0 -0
  41. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.gitignore +0 -0
  42. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/.gitignore +0 -0
  43. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/blueprints.json +0 -0
  44. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/port-app-config.yml +0 -0
  45. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/spec.yaml +0 -0
  46. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CHANGELOG.md +0 -0
  47. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CONTRIBUTING.md +0 -0
  48. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/README.md +0 -0
  49. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/changelog/.gitignore +0 -0
  50. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/debug.py +0 -0
  51. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/main.py +0 -0
  52. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/poetry.toml +0 -0
  53. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/pyproject.toml +0 -0
  54. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/sonar-project.properties +0 -0
  55. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/__init__.py +0 -0
  56. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/test_sample.py +0 -0
  57. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/cli/utils.py +0 -0
  58. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/__init__.py +0 -0
  59. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/auth/__init__.py +0 -0
  60. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/auth/auth_client.py +0 -0
  61. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/auth/oauth_client.py +0 -0
  62. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/port/__init__.py +0 -0
  63. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/port/authentication.py +0 -0
  64. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/port/client.py +0 -0
  65. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/port/mixins/__init__.py +0 -0
  66. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/port/mixins/blueprints.py +0 -0
  67. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/port/mixins/entities.py +0 -0
  68. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/port/mixins/migrations.py +0 -0
  69. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/port/mixins/organization.py +0 -0
  70. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/port/retry_transport.py +0 -0
  71. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/port/types.py +0 -0
  72. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/clients/port/utils.py +0 -0
  73. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/config/__init__.py +0 -0
  74. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/config/base.py +0 -0
  75. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/config/dynamic.py +0 -0
  76. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/config/settings.py +0 -0
  77. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/consumers/__init__.py +0 -0
  78. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/consumers/kafka_consumer.py +0 -0
  79. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/context/__init__.py +0 -0
  80. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/context/event.py +0 -0
  81. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/context/ocean.py +0 -0
  82. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/context/resource.py +0 -0
  83. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/__init__.py +0 -0
  84. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/defaults/__init__.py +0 -0
  85. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/defaults/clean.py +0 -0
  86. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/defaults/common.py +0 -0
  87. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/defaults/initialize.py +0 -0
  88. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/event_listener/__init__.py +0 -0
  89. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/event_listener/base.py +0 -0
  90. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/event_listener/factory.py +0 -0
  91. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/event_listener/http.py +0 -0
  92. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/event_listener/kafka.py +0 -0
  93. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/event_listener/once.py +0 -0
  94. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/event_listener/polling.py +0 -0
  95. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/event_listener/webhooks_only.py +0 -0
  96. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/__init__.py +0 -0
  97. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/base.py +0 -0
  98. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/entities_state_applier/__init__.py +0 -0
  99. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/entities_state_applier/base.py +0 -0
  100. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/entities_state_applier/port/__init__.py +0 -0
  101. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/entities_state_applier/port/get_related_entities.py +0 -0
  102. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/entities_state_applier/port/order_by_entities_dependencies.py +0 -0
  103. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/entity_processor/__init__.py +0 -0
  104. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/entity_processor/base.py +0 -0
  105. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/entity_processor/jq_entity_processor.py +0 -0
  106. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/port_app_config/__init__.py +0 -0
  107. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/port_app_config/api.py +0 -0
  108. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/port_app_config/base.py +0 -0
  109. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/port_app_config/models.py +0 -0
  110. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/queue/__init__.py +0 -0
  111. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/queue/abstract_queue.py +0 -0
  112. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/queue/local_queue.py +0 -0
  113. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/resync_state_updater/__init__.py +0 -0
  114. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/webhook/__init__.py +0 -0
  115. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/webhook/abstract_webhook_processor.py +0 -0
  116. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/webhook/processor_manager.py +0 -0
  117. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/handlers/webhook/webhook_event.py +0 -0
  118. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/integrations/__init__.py +0 -0
  119. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/integrations/base.py +0 -0
  120. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/integrations/mixins/__init__.py +0 -0
  121. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/integrations/mixins/events.py +0 -0
  122. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/integrations/mixins/handler.py +0 -0
  123. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/integrations/mixins/live_events.py +0 -0
  124. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/integrations/mixins/sync.py +0 -0
  125. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/integrations/mixins/utils.py +0 -0
  126. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/models.py +0 -0
  127. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/ocean_types.py +0 -0
  128. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/utils/entity_topological_sorter.py +0 -0
  129. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/core/utils/utils.py +0 -0
  130. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/debug_cli.py +0 -0
  131. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/exceptions/__init__.py +0 -0
  132. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/exceptions/api.py +0 -0
  133. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/exceptions/base.py +0 -0
  134. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/exceptions/clients.py +0 -0
  135. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/exceptions/context.py +0 -0
  136. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/exceptions/core.py +0 -0
  137. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/exceptions/port_defaults.py +0 -0
  138. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/exceptions/utils.py +0 -0
  139. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/exceptions/webhook_processor.py +0 -0
  140. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/helpers/__init__.py +0 -0
  141. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/helpers/async_client.py +0 -0
  142. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/helpers/retry.py +0 -0
  143. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/log/__init__.py +0 -0
  144. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/log/handlers.py +0 -0
  145. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/log/logger_setup.py +0 -0
  146. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/log/sensetive.py +0 -0
  147. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/middlewares.py +0 -0
  148. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/py.typed +0 -0
  149. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/run.py +0 -0
  150. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/sonar-project.properties +0 -0
  151. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/__init__.py +0 -0
  152. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/clients/__init__.py +0 -0
  153. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/clients/oauth/__init__.py +0 -0
  154. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/clients/oauth/test_oauth_client.py +0 -0
  155. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/clients/port/mixins/test_entities.py +0 -0
  156. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/clients/port/mixins/test_organization_mixin.py +0 -0
  157. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/conftest.py +0 -0
  158. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/conftest.py +0 -0
  159. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/defaults/test_common.py +0 -0
  160. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/handlers/entities_state_applier/test_applier.py +0 -0
  161. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/handlers/entity_processor/test_jq_entity_processor.py +0 -0
  162. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/handlers/mixins/test_live_events.py +0 -0
  163. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/handlers/port_app_config/test_api.py +0 -0
  164. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/handlers/port_app_config/test_base.py +0 -0
  165. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/handlers/queue/test_local_queue.py +0 -0
  166. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/handlers/webhook/test_abstract_webhook_processor.py +0 -0
  167. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/handlers/webhook/test_processor_manager.py +0 -0
  168. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/handlers/webhook/test_webhook_event.py +0 -0
  169. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/test_utils.py +0 -0
  170. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/utils/test_entity_topological_sorter.py +0 -0
  171. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/core/utils/test_resolve_entities_diff.py +0 -0
  172. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/helpers/__init__.py +0 -0
  173. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/helpers/fake_port_api.py +0 -0
  174. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/helpers/fixtures.py +0 -0
  175. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/helpers/integration.py +0 -0
  176. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/helpers/ocean_app.py +0 -0
  177. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/helpers/port_client.py +0 -0
  178. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/helpers/smoke_test.py +0 -0
  179. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/log/test_handlers.py +0 -0
  180. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/test_metric.py +0 -0
  181. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/test_ocean.py +0 -0
  182. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/test_smoke.py +0 -0
  183. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/utils/test_async_iterators.py +0 -0
  184. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/tests/utils/test_cache.py +0 -0
  185. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/utils/__init__.py +0 -0
  186. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/utils/async_http.py +0 -0
  187. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/utils/async_iterators.py +0 -0
  188. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/utils/cache.py +0 -0
  189. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/utils/misc.py +0 -0
  190. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/utils/queue_utils.py +0 -0
  191. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/utils/repeat.py +0 -0
  192. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/utils/signal.py +0 -0
  193. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/utils/time.py +0 -0
  194. {port_ocean-0.22.10 → port_ocean-0.22.11}/port_ocean/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: port-ocean
3
- Version: 0.22.10
3
+ Version: 0.22.11
4
4
  Summary: Port Ocean is a CLI tool for managing your Port projects.
5
5
  Home-page: https://app.getport.io
6
6
  Keywords: ocean,port-ocean,port
@@ -25,6 +25,10 @@ class LogAttributes(TypedDict):
25
25
  ingestUrl: str
26
26
 
27
27
 
28
+ class MetricsAttributes(TypedDict):
29
+ ingestUrl: str
30
+
31
+
28
32
  class IntegrationClientMixin:
29
33
  def __init__(
30
34
  self,
@@ -38,6 +42,7 @@ class IntegrationClientMixin:
38
42
  self.auth = auth
39
43
  self.client = client
40
44
  self._log_attributes: LogAttributes | None = None
45
+ self._metrics_attributes: MetricsAttributes | None = None
41
46
 
42
47
  async def is_integration_provision_enabled(
43
48
  self, integration_type: str, should_raise: bool = True, should_log: bool = True
@@ -106,6 +111,12 @@ class IntegrationClientMixin:
106
111
  self._log_attributes = response["logAttributes"]
107
112
  return self._log_attributes
108
113
 
114
+ async def get_metrics_attributes(self) -> LogAttributes:
115
+ if self._metrics_attributes is None:
116
+ response = await self.get_current_integration()
117
+ self._metrics_attributes = response["metricAttributes"]
118
+ return self._metrics_attributes
119
+
109
120
  async def _poll_integration_until_default_provisioning_is_complete(
110
121
  self,
111
122
  ) -> Dict[str, Any]:
@@ -197,6 +208,40 @@ class IntegrationClientMixin:
197
208
  handle_port_status_code(response)
198
209
  return response.json()["integration"]
199
210
 
211
+ async def post_integration_sync_metrics(
212
+ self, metrics: list[dict[str, Any]]
213
+ ) -> None:
214
+ logger.debug("starting POST metrics request", metrics=metrics)
215
+ metrics_attributes = await self.get_metrics_attributes()
216
+ headers = await self.auth.headers()
217
+ response = await self.client.post(
218
+ metrics_attributes["ingestUrl"],
219
+ headers=headers,
220
+ json={
221
+ "syncKindsMetrics": metrics,
222
+ },
223
+ )
224
+ handle_port_status_code(response, should_log=False)
225
+ logger.debug("Finished POST metrics request")
226
+
227
+ async def put_integration_sync_metrics(self, kind_metrics: dict[str, Any]) -> None:
228
+ logger.debug("starting PUT metrics request", kind_metrics=kind_metrics)
229
+ metrics_attributes = await self.get_metrics_attributes()
230
+ url = (
231
+ metrics_attributes["ingestUrl"]
232
+ + f"/resync/{kind_metrics['eventId']}/kind/{kind_metrics['kindIdentifier']}"
233
+ )
234
+ headers = await self.auth.headers()
235
+ response = await self.client.put(
236
+ url,
237
+ headers=headers,
238
+ json={
239
+ "syncKindMetrics": kind_metrics,
240
+ },
241
+ )
242
+ handle_port_status_code(response, should_log=False)
243
+ logger.debug("Finished PUT metrics request")
244
+
200
245
  async def ingest_integration_logs(self, logs: list[dict[str, Any]]) -> None:
201
246
  logger.debug("Ingesting logs")
202
247
  log_attributes = await self.get_log_attributes()
@@ -104,8 +104,12 @@ class HttpEntitiesStateApplier(BaseEntitiesStateApplier):
104
104
  ):
105
105
  await self._safe_delete(diff.deleted, kept_entities, user_agent_type)
106
106
  ocean.metrics.inc_metric(
107
- name=MetricType.DELETION_COUNT_NAME,
108
- labels=[ocean.metrics.current_resource_kind(), MetricPhase.DELETE],
107
+ name=MetricType.OBJECT_COUNT_NAME,
108
+ labels=[
109
+ ocean.metrics.current_resource_kind(),
110
+ MetricPhase.DELETE,
111
+ MetricPhase.DeletionResult.DELETED,
112
+ ],
109
113
  value=len(diff.deleted),
110
114
  )
111
115
  else:
@@ -90,4 +90,10 @@ class ResyncStateUpdater:
90
90
  labels=[ocean.metrics.current_resource_kind(), MetricPhase.RESYNC],
91
91
  value=int(status == IntegrationStateStatus.Completed),
92
92
  )
93
- await ocean.metrics.flush(kind=ocean.metrics.current_resource_kind())
93
+
94
+ await ocean.metrics.send_metrics_to_webhook(
95
+ kind=ocean.metrics.current_resource_kind()
96
+ )
97
+ # await ocean.metrics.report_sync_metrics(
98
+ # kinds=[ocean.metrics.current_resource_kind()]
99
+ # ) # TODO: uncomment this when end points are ready
@@ -614,8 +614,10 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
614
614
  use_cache=False
615
615
  )
616
616
  logger.info(f"Resync will use the following mappings: {app_config.dict()}")
617
- ocean.metrics.initialize_metrics([f"{resource.kind}-{index}" for index, resource in enumerate(app_config.resources)])
618
- await ocean.metrics.flush()
617
+
618
+ kinds = [f"{resource.kind}-{index}" for index, resource in enumerate(app_config.resources)]
619
+ ocean.metrics.initialize_metrics(kinds)
620
+ # await ocean.metrics.report_sync_metrics(kinds=kinds) # TODO: uncomment this when end points are ready
619
621
 
620
622
  # Execute resync_start hooks
621
623
  for resync_start_fn in self.event_strategy["resync_start"]:
@@ -643,7 +645,7 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
643
645
  async with resource_context(resource,index):
644
646
  resource_kind_id = f"{resource.kind}-{index}"
645
647
  ocean.metrics.sync_state = SyncState.SYNCING
646
- await ocean.metrics.flush(kind=resource_kind_id)
648
+ # await ocean.metrics.report_kind_sync_metrics(kind=resource_kind_id) # TODO: uncomment this when end points are ready
647
649
 
648
650
  task = asyncio.create_task(
649
651
  self._register_in_batches(resource, user_agent_type)
@@ -653,9 +655,14 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
653
655
  kind_results: tuple[list[Entity], list[Exception]] = await task
654
656
 
655
657
  creation_results.append(kind_results)
658
+
656
659
  if ocean.metrics.sync_state != SyncState.FAILED:
657
660
  ocean.metrics.sync_state = SyncState.COMPLETED
658
- await ocean.metrics.flush(kind=resource_kind_id)
661
+
662
+ await ocean.metrics.send_metrics_to_webhook(
663
+ kind=resource_kind_id
664
+ )
665
+ # await ocean.metrics.report_kind_sync_metrics(kind=resource_kind_id) # TODO: uncomment this when end points are ready
659
666
 
660
667
  await self.sort_and_upsert_failed_entities(user_agent_type)
661
668
 
@@ -13,6 +13,7 @@ import prometheus_client.parser
13
13
 
14
14
  if TYPE_CHECKING:
15
15
  from port_ocean.config.settings import MetricsSettings, IntegrationSettings
16
+ from port_ocean.clients.port.client import PortClient
16
17
 
17
18
 
18
19
  class MetricPhase:
@@ -35,21 +36,22 @@ class MetricPhase:
35
36
  class ExtractResult:
36
37
  EXTRACTED = "raw_extracted"
37
38
 
39
+ class DeletionResult:
40
+ DELETED = "deleted"
41
+
38
42
 
39
43
  class MetricType:
40
44
  # Define metric names as constants
41
45
  DURATION_NAME = "duration_seconds"
42
46
  OBJECT_COUNT_NAME = "object_count"
43
- ERROR_COUNT_NAME = "error_count"
44
47
  SUCCESS_NAME = "success"
45
48
  RATE_LIMIT_WAIT_NAME = "rate_limit_wait_seconds"
46
- DELETION_COUNT_NAME = "deletion_count"
47
49
 
48
50
 
49
51
  class SyncState:
50
52
  SYNCING = "syncing"
51
53
  COMPLETED = "completed"
52
- QUEUED = "queued"
54
+ PENDING = "pending"
53
55
  FAILED = "failed"
54
56
 
55
57
 
@@ -65,11 +67,6 @@ _metrics_registry: Dict[str, Tuple[str, str, List[str]]] = {
65
67
  "object_count description",
66
68
  ["kind", "phase", "object_count_type"],
67
69
  ),
68
- MetricType.ERROR_COUNT_NAME: (
69
- MetricType.ERROR_COUNT_NAME,
70
- "error_count description",
71
- ["kind", "phase"],
72
- ),
73
70
  MetricType.SUCCESS_NAME: (
74
71
  MetricType.SUCCESS_NAME,
75
72
  "success description",
@@ -80,11 +77,6 @@ _metrics_registry: Dict[str, Tuple[str, str, List[str]]] = {
80
77
  "rate_limit_wait description",
81
78
  ["kind", "phase", "endpoint"],
82
79
  ),
83
- MetricType.DELETION_COUNT_NAME: (
84
- MetricType.DELETION_COUNT_NAME,
85
- "deletion_count description",
86
- ["kind", "phase"],
87
- ),
88
80
  }
89
81
 
90
82
 
@@ -115,16 +107,18 @@ class Metrics:
115
107
  self,
116
108
  metrics_settings: "MetricsSettings",
117
109
  integration_configuration: "IntegrationSettings",
110
+ port_client: "PortClient",
118
111
  ) -> None:
119
112
  self.metrics_settings = metrics_settings
120
113
  self.integration_configuration = integration_configuration
114
+ self.port_client = port_client
121
115
  self.registry = prometheus_client.CollectorRegistry()
122
116
  self.metrics: dict[str, Gauge] = {}
123
117
  self.load_metrics()
124
118
  self._integration_version: Optional[str] = None
125
119
  self._ocean_version: Optional[str] = None
126
120
  self.event_id = ""
127
- self.sync_state = SyncState.QUEUED
121
+ self.sync_state = SyncState.PENDING
128
122
 
129
123
  @property
130
124
  def event_id(self) -> str:
@@ -163,9 +157,6 @@ class Metrics:
163
157
  return self.metrics_settings.enabled
164
158
 
165
159
  def load_metrics(self) -> None:
166
- if not self.enabled:
167
- return None
168
-
169
160
  # Load all registered metrics
170
161
  for name, (_, description, labels) in _metrics_registry.items():
171
162
  self.metrics[name] = Gauge(
@@ -173,8 +164,6 @@ class Metrics:
173
164
  )
174
165
 
175
166
  def get_metric(self, name: str, labels: list[str]) -> Gauge | EmptyMetric:
176
- if not self.enabled:
177
- return EmptyMetric()
178
167
  metrics = self.metrics.get(name)
179
168
  if not metrics:
180
169
  return EmptyMetric()
@@ -188,9 +177,6 @@ class Metrics:
188
177
  labels (list[str]): The labels to apply to the metric.
189
178
  value (float): The value to inc.
190
179
  """
191
- if not self.enabled:
192
- return None
193
-
194
180
  self.get_metric(name, labels).inc(value)
195
181
 
196
182
  def set_metric(self, name: str, labels: list[str], value: float) -> None:
@@ -201,9 +187,6 @@ class Metrics:
201
187
  labels (list[str]): The labels to apply to the metric.
202
188
  value (float): The value to set.
203
189
  """
204
- if not self.enabled:
205
- return None
206
-
207
190
  self.get_metric(name, labels).set(value)
208
191
 
209
192
  def initialize_metrics(self, kind_blockes: list[str]) -> None:
@@ -271,15 +254,39 @@ class Metrics:
271
254
  self.registry
272
255
  ).decode()
273
256
 
274
- async def flush(
275
- self, metric_name: Optional[str] = None, kind: Optional[str] = None
257
+ async def report_sync_metrics(
258
+ self, metric_name: Optional[str] = None, kinds: Optional[list[str]] = None
276
259
  ) -> None:
277
- if not self.enabled:
260
+ if kinds is None:
278
261
  return None
279
262
 
280
- if not self.metrics_settings.webhook_url:
263
+ metrics = []
264
+
265
+ for kind in kinds:
266
+ metric = self.generate_metrics(metric_name, kind)
267
+ metrics.extend(metric)
268
+
269
+ try:
270
+ await self.port_client.post_integration_sync_metrics(metrics)
271
+ except Exception as e:
272
+ logger.error(f"Error posting metrics: {e}", metrics=metrics)
273
+
274
+ async def report_kind_sync_metrics(
275
+ self, metric_name: Optional[str] = None, kind: Optional[str] = None
276
+ ) -> None:
277
+ metrics = self.generate_metrics(metric_name, kind)
278
+ if not metrics:
281
279
  return None
282
280
 
281
+ try:
282
+ for metric in metrics:
283
+ await self.port_client.put_integration_sync_metrics(metric)
284
+ except Exception as e:
285
+ logger.error(f"Error putting metrics: {e}", metrics=metrics)
286
+
287
+ def generate_metrics(
288
+ self, metric_name: Optional[str] = None, kind: Optional[str] = None
289
+ ) -> list[dict[str, Any]]:
283
290
  try:
284
291
  latest_raw = self.generate_latest()
285
292
  metric_families = prometheus_client.parser.text_string_to_metric_families(
@@ -318,27 +325,54 @@ class Metrics:
318
325
 
319
326
  # If no metrics were filtered, exit early
320
327
  if not metrics_dict.get("kind", {}):
321
- return None
328
+ return []
322
329
 
330
+ events = []
323
331
  for kind_key, metrics in metrics_dict.get("kind", {}).items():
324
332
  # Skip if we're filtering by kind and this isn't the requested kind
325
333
  if kind and kind_key != kind:
326
334
  continue
327
335
 
328
336
  event = {
329
- "integration_type": self.integration_configuration.type,
330
- "integration_identifier": self.integration_configuration.identifier,
331
- "integration_version": self.integration_version,
332
- "ocean_version": self.ocean_version,
333
- "kind_identifier": kind_key,
334
- "kind": "-".join(kind_key.split("-")[:-1]),
335
- "event_id": self.event_id,
336
- "sync_state": self.sync_state,
337
+ "integrationType": self.integration_configuration.type,
338
+ "integrationIdentifier": self.integration_configuration.identifier,
339
+ "integrationVersion": self.integration_version,
340
+ "oceanVersion": self.ocean_version,
341
+ "kindIdentifier": kind_key,
342
+ "kind": (
343
+ "-".join(kind_key.split("-")[:-1])
344
+ if "-" in kind_key
345
+ else kind_key
346
+ ),
347
+ "kindIndex": 0 if kind_key == "__runtime__" else int(kind_key[-1]),
348
+ "eventId": self.event_id,
349
+ "syncState": self.sync_state,
337
350
  "metrics": metrics,
338
351
  }
339
- logger.info(f"Sending metrics to webhook {kind_key}: {event}")
352
+ events.append(event)
353
+ return events
354
+ except Exception as e:
355
+ logger.error(f"Error sending metrics to webhook: {e}")
356
+ return []
357
+
358
+ async def send_metrics_to_webhook(
359
+ self, metric_name: Optional[str] = None, kind: Optional[str] = None
360
+ ) -> None:
361
+ try:
362
+ if not self.enabled:
363
+ return None
364
+
365
+ if not self.metrics_settings.webhook_url:
366
+ return None
367
+
368
+ metrics = self.generate_metrics(metric_name, kind)
369
+ if not metrics:
370
+ return None
371
+
372
+ for metric in metrics:
373
+ logger.info(f"Sending metrics to webhook {metric['kind']}: {metric}")
340
374
  await AsyncClient().post(
341
- url=self.metrics_settings.webhook_url, json=event
375
+ url=self.metrics_settings.webhook_url, json=metric
342
376
  )
343
377
  except Exception as e:
344
378
  logger.error(f"Error sending metrics to webhook: {e}")
@@ -11,8 +11,6 @@ def TimeMetric(phase: str) -> Any:
11
11
 
12
12
  @wraps(func)
13
13
  async def wrapper(*args: Any, **kwargs: dict[Any, Any]) -> Any:
14
- if not ocean.metrics.enabled:
15
- return await func(*args, **kwargs)
16
14
  start = time.monotonic()
17
15
  res = await func(*args, **kwargs)
18
16
  end = time.monotonic()
@@ -57,9 +57,20 @@ class Ocean:
57
57
  *self.config.get_sensitive_fields_data()
58
58
  )
59
59
  self.integration_router = integration_router or APIRouter()
60
+
61
+ self.port_client = PortClient(
62
+ base_url=self.config.port.base_url,
63
+ client_id=self.config.port.client_id,
64
+ client_secret=self.config.port.client_secret,
65
+ integration_identifier=self.config.integration.identifier,
66
+ integration_type=self.config.integration.type,
67
+ integration_version=__integration_version__,
68
+ )
69
+
60
70
  self.metrics = port_ocean.helpers.metric.metric.Metrics(
61
71
  metrics_settings=self.config.metrics,
62
72
  integration_configuration=self.config.integration,
73
+ port_client=self.port_client,
63
74
  )
64
75
 
65
76
  self.webhook_manager = LiveEventsProcessorManager(
@@ -69,14 +80,6 @@ class Ocean:
69
80
  max_wait_seconds_before_shutdown=self.config.max_wait_seconds_before_shutdown,
70
81
  )
71
82
 
72
- self.port_client = PortClient(
73
- base_url=self.config.port.base_url,
74
- client_id=self.config.port.client_id,
75
- client_secret=self.config.port.client_secret,
76
- integration_identifier=self.config.integration.identifier,
77
- integration_type=self.config.integration.type,
78
- integration_version=__integration_version__,
79
- )
80
83
  self.integration = (
81
84
  integration_class(ocean) if integration_class else BaseIntegration(ocean)
82
85
  )