launchdarkly.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  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: "LDClient | None" = None) -> None:
  17. """
  18. :param client: An initialized LDClient instance. If a client is not provided, this
  19. integration will attempt to use the shared global instance.
  20. """
  21. try:
  22. client = ld_client or ldclient.get()
  23. except Exception as exc:
  24. raise DidNotEnable("Error getting LaunchDarkly client. " + repr(exc))
  25. if not client.is_initialized():
  26. raise DidNotEnable("LaunchDarkly client is not initialized.")
  27. # Register the flag collection hook with the LD client.
  28. client.add_hook(LaunchDarklyHook())
  29. @staticmethod
  30. def setup_once() -> None:
  31. pass
  32. class LaunchDarklyHook(Hook):
  33. @property
  34. def metadata(self) -> "Metadata":
  35. return Metadata(name="sentry-flag-auditor")
  36. def after_evaluation(
  37. self,
  38. series_context: "EvaluationSeriesContext",
  39. data: "dict[Any, Any]",
  40. detail: "EvaluationDetail",
  41. ) -> "dict[Any, Any]":
  42. if isinstance(detail.value, bool):
  43. add_feature_flag(series_context.key, detail.value)
  44. return data
  45. def before_evaluation(
  46. self, series_context: "EvaluationSeriesContext", data: "dict[Any, Any]"
  47. ) -> "dict[Any, Any]":
  48. return data # No-op.