Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(flags): Add LaunchDarkly Integration #3679

Merged
merged 31 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c25b802
Initial src and dependency code
aliu39 Oct 22, 2024
e60e1a4
Move get_ldclient to a top-level helper
aliu39 Oct 22, 2024
597004b
Add to requirements-testing
aliu39 Oct 22, 2024
75a3442
Split up static version from latest
aliu39 Oct 22, 2024
43332d2
Merge branch 'cmanallen/flags-open-feature-integration' of https://gi…
aliu39 Oct 22, 2024
a2e3383
Fix import
aliu39 Oct 23, 2024
5165ffb
Pass in client to Integration initializer and basic unit test
aliu39 Oct 23, 2024
c9daf17
Add threaded, asyncio, and global ldclient tests
aliu39 Oct 23, 2024
d7ae9f5
Change metadata, test not enabled cases
aliu39 Oct 23, 2024
7740f43
Add versioned tests to workflows
aliu39 Oct 23, 2024
0309b82
Rm doc references
aliu39 Oct 23, 2024
cec37dc
Fix split-tox-gh-actions GROUPS
aliu39 Oct 23, 2024
22d1024
Add doc references
aliu39 Oct 24, 2024
d9775b8
Formatting from pr comments. Max line length=100
aliu39 Oct 25, 2024
91eb352
Move hook registration to setup_once
aliu39 Oct 25, 2024
2f59b47
Merge branch 'cmanallen/flags-open-feature-integration' into aliu/lau…
cmanallen Oct 28, 2024
a9d5099
Fix typing and extract error_processor to common module
cmanallen Oct 30, 2024
50d2dae
Raise if the integration was not enabled before setup_once is called
cmanallen Oct 30, 2024
44aebf3
Rename parameter
cmanallen Oct 30, 2024
144e064
Move hook registration to the init method
cmanallen Oct 30, 2024
13434c3
Update tox to use 3.8 or greater
cmanallen Oct 30, 2024
77d4055
Fix name
cmanallen Oct 30, 2024
8a1a20e
Remove duplicate definition
cmanallen Oct 30, 2024
2dab8c3
Remove another dupe and change naming
cmanallen Oct 30, 2024
c97e102
Restrict versions
cmanallen Oct 30, 2024
ead840f
Remove integration init
cmanallen Oct 30, 2024
bb678c2
Rename extras_require for launchdarkly
cmanallen Oct 30, 2024
08289c2
Try resetting the client
cmanallen Oct 30, 2024
a3d90bd
Remove launchdarkly from testing requirements
cmanallen Oct 30, 2024
711fe55
Revert "Remove integration init"
cmanallen Oct 30, 2024
5218c7a
Remove client reset
cmanallen Oct 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions requirements-linting.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ pep8-naming
pre-commit # local linting
httpcore
openfeature-sdk
launchdarkly-server-sdk
1 change: 1 addition & 0 deletions scripts/split-tox-gh-actions/split-tox-gh-actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
"tornado",
],
"Miscellaneous": [
"ldclient",
"loguru",
"openfeature",
"opentelemetry",
Expand Down
72 changes: 72 additions & 0 deletions sentry_sdk/integrations/launchdarkly.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from typing import TYPE_CHECKING
import sentry_sdk

from sentry_sdk.integrations import DidNotEnable, Integration

try:
import ldclient
from ldclient.hook import Hook

if TYPE_CHECKING:
from ldclient import LDClient
from ldclient.hook import EvaluationSeriesContext, Metadata
from ldclient.evaluation import EvaluationDetail

from sentry_sdk._types import Event, ExcInfo
from typing import Any, Optional
except ImportError:
raise DidNotEnable("LaunchDarkly is not installed")


class LaunchDarklyIntegration(Integration):
identifier = "launchdarkly"

@staticmethod
def get_ldclient():
# type: () -> LDClient
try:
client = ldclient.get()
except Exception as exc:
sentry_sdk.capture_exception(exc)
raise DidNotEnable(
"Failed to find LaunchDarkly client instance. " + str(exc)
)

if client and client.is_initialized():
return client
raise DidNotEnable("LaunchDarkly client is not initialized")

@staticmethod
def setup_once():
# type: () -> None
def error_processor(event, _exc_info):
# type: (Event, ExcInfo) -> Optional[Event]
scope = sentry_sdk.get_current_scope()
event["contexts"]["flags"] = {"values": scope.flags.get()}
return event

scope = sentry_sdk.get_current_scope()
scope.add_error_processor(error_processor)

# Register the hook with the global launchdarkly client.
client = LaunchDarklyIntegration.get_ldclient()
client.add_hook(LaunchDarklyHook())


class LaunchDarklyHook(Hook):

@property
def metadata(self):
# type: () -> Metadata
return Metadata(name="sentry-on-error-hook")

def after_evaluation(self, series_context, data, detail):
# type: (EvaluationSeriesContext, dict[Any, Any], EvaluationDetail) -> dict[Any, Any]
if isinstance(detail.value, bool):
flags = sentry_sdk.get_current_scope().flags
flags.set(series_context.key, detail.value)
return data
aliu39 marked this conversation as resolved.
Show resolved Hide resolved

def before_evaluation(self, _series_context, data):
aliu39 marked this conversation as resolved.
Show resolved Hide resolved
# type: (EvaluationSeriesContext, dict[Any, Any]) -> dict[Any, Any]
return data # No-op.
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def get_file_text(file_name):
"huey": ["huey>=2"],
"huggingface_hub": ["huggingface_hub>=0.22"],
"langchain": ["langchain>=0.0.210"],
"ldclient": ["launchdarkly-server-sdk>=9.8.0"],
"litestar": ["litestar>=2.0.0"],
"loguru": ["loguru>=0.5"],
"openai": ["openai>=1.0.0", "tiktoken>=0.3.0"],
Expand Down
3 changes: 3 additions & 0 deletions tests/integrations/launchdarkly/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import pytest

pytest.importorskip("ldclient")
aliu39 marked this conversation as resolved.
Show resolved Hide resolved
7 changes: 7 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ envlist =
{py3.9,py3.11,py3.12}-langchain-latest
{py3.9,py3.11,py3.12}-langchain-notiktoken

# LaunchDarkly
{py3.8,py3.9,py3.10,py3.11,py3.12}-launchdarkly-latest

# Litestar
# litestar 2.0.0 is the earliest version that supports Python < 3.12
{py3.8,py3.11}-litestar-v{2.0}
Expand Down Expand Up @@ -520,6 +523,9 @@ deps =
langchain-notiktoken: langchain-openai
langchain-notiktoken: openai>=1.6.1

# LaunchDarkly
launchdarkly-latest: launchdarkly-server-sdk~=9.8.0

# Litestar
litestar: pytest-asyncio
litestar: python-multipart
Expand Down Expand Up @@ -727,6 +733,7 @@ setenv =
huey: TESTPATH=tests/integrations/huey
huggingface_hub: TESTPATH=tests/integrations/huggingface_hub
langchain: TESTPATH=tests/integrations/langchain
launchdarkly: TESTPATH=tests/integrations/launchdarkly
litestar: TESTPATH=tests/integrations/litestar
loguru: TESTPATH=tests/integrations/loguru
openai: TESTPATH=tests/integrations/openai
Expand Down
Loading