launchdarkly.py 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. from typing import TYPE_CHECKING
  2. from sentry_sdk.feature_flags import add_feature_flag
  3. from sentry_sdk.integrations import DidNotEnable, Integration
  4. try:
  5. import ldclient
  6. from ldclient.hook import Hook, Metadata
  7. if TYPE_CHECKING:
  8. from ldclient import LDClient
  9. from ldclient.hook import EvaluationSeriesContext
  10. from ldclient.evaluation import EvaluationDetail
  11. from typing import Any
  12. except ImportError:
  13. raise DidNotEnable("LaunchDarkly is not installed")
  14. class LaunchDarklyIntegration(Integration):
  15. identifier = "launchdarkly"
  16. def __init__(self, ld_client=None):
  17. # type: (LDClient | None) -> None
  18. """
  19. :param client: An initialized LDClient instance. If a client is not provided, this
  20. integration will attempt to use the shared global instance.
  21. """
  22. try:
  23. client = ld_client or ldclient.get()
  24. except Exception as exc:
  25. raise DidNotEnable("Error getting LaunchDarkly client. " + repr(exc))
  26. if not client.is_initialized():
  27. raise DidNotEnable("LaunchDarkly client is not initialized.")
  28. # Register the flag collection hook with the LD client.
  29. client.add_hook(LaunchDarklyHook())
  30. @staticmethod
  31. def setup_once():
  32. # type: () -> None
  33. pass
  34. class LaunchDarklyHook(Hook):
  35. @property
  36. def metadata(self):
  37. # type: () -> Metadata
  38. return Metadata(name="sentry-flag-auditor")
  39. def after_evaluation(self, series_context, data, detail):
  40. # type: (EvaluationSeriesContext, dict[Any, Any], EvaluationDetail) -> dict[Any, Any]
  41. if isinstance(detail.value, bool):
  42. add_feature_flag(series_context.key, detail.value)
  43. return data
  44. def before_evaluation(self, series_context, data):
  45. # type: (EvaluationSeriesContext, dict[Any, Any]) -> dict[Any, Any]
  46. return data # No-op.