Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh
- Dropped support for Falcon versions below 3.0.
- Dropped support for Flask below 2.0.
- Dropped support for aiohttp below 3.7.
- Removed the possibility to supply a specific client to the LaunchDarklyIntegration.
- The `enable_tracing` option was removed. Use `traces_sample_rate=1.0` instead.
- The deprecated `push_scope` and `configure_scope` APIs have been removed. Use `with new_scope():` to push a new scope and `scope = get_current_scope()` to retrieve the current scope instead.
- Transaction profiling and related code was removed.
Expand Down
18 changes: 6 additions & 12 deletions sentry_sdk/integrations/launchdarkly.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
if TYPE_CHECKING:
from typing import Any

from ldclient import LDClient
from ldclient.evaluation import EvaluationDetail
from ldclient.hook import EvaluationSeriesContext
except ImportError:
Expand All @@ -22,13 +21,13 @@
class LaunchDarklyIntegration(Integration):
identifier = "launchdarkly"

def __init__(self, ld_client: "LDClient | None" = None) -> None:
"""
:param client: An initialized LDClient instance. If a client is not provided, this
integration will attempt to use the shared global instance.
"""
@staticmethod
def setup_once() -> None:
version = parse_version(LDCLIENT_VERSION)
_check_minimum_version(LaunchDarklyIntegration, version)

try:
client = ld_client or ldclient.get()
client = ldclient.get()
except Exception as exc:
raise DidNotEnable("Error getting LaunchDarkly client. " + repr(exc))

Expand All @@ -38,11 +37,6 @@ def __init__(self, ld_client: "LDClient | None" = None) -> None:
# Register the flag collection hook with the LD client.
client.add_hook(LaunchDarklyHook())

@staticmethod
def setup_once() -> None:
version = parse_version(LDCLIENT_VERSION)
_check_minimum_version(LaunchDarklyIntegration, version)


class LaunchDarklyHook(Hook):
@property
Expand Down
105 changes: 35 additions & 70 deletions tests/integrations/launchdarkly/test_launchdarkly.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import ldclient
import pytest
from ldclient import LDClient
from ldclient.config import Config
from ldclient.context import Context
from ldclient.integrations.test_data import TestData
Expand All @@ -14,29 +13,18 @@
from tests.conftest import ApproxDict


@pytest.mark.parametrize(
"use_global_client",
(False, True),
)
def test_launchdarkly_integration(
sentry_init, use_global_client, capture_events, uninstall_integration
):
def test_launchdarkly_integration(sentry_init, capture_events, uninstall_integration):
td = TestData.data_source()
td.update(td.flag("hello").variation_for_all(True))
td.update(td.flag("world").variation_for_all(True))
# Disable background requests as we aren't using a server.
config = Config(
"sdk-key", update_processor_class=td, diagnostic_opt_out=True, send_events=False
)

uninstall_integration(LaunchDarklyIntegration.identifier)
if use_global_client:
ldclient.set_config(config)
sentry_init(integrations=[LaunchDarklyIntegration()])
client = ldclient.get()
else:
client = LDClient(config=config)
sentry_init(integrations=[LaunchDarklyIntegration(ld_client=client)])
ldclient.set_config(config)
sentry_init(integrations=[LaunchDarklyIntegration()])
client = ldclient.get()

# Evaluate
client.variation("hello", Context.create("my-org", "organization"), False)
Expand All @@ -62,18 +50,18 @@ def test_launchdarkly_integration_threaded(
td = TestData.data_source()
td.update(td.flag("hello").variation_for_all(True))
td.update(td.flag("world").variation_for_all(True))
client = LDClient(
config=Config(
"sdk-key",
update_processor_class=td,
diagnostic_opt_out=True, # Disable background requests as we aren't using a server.
send_events=False,
)
config = Config(
"sdk-key",
update_processor_class=td,
diagnostic_opt_out=True, # Disable background requests as we aren't using a server.
send_events=False,
)
ldclient.set_config(config)
client = ldclient.get()
context = Context.create("user1")

uninstall_integration(LaunchDarklyIntegration.identifier)
sentry_init(integrations=[LaunchDarklyIntegration(ld_client=client)])
sentry_init(integrations=[LaunchDarklyIntegration()])
events = capture_events()

def task(flag_key):
Expand Down Expand Up @@ -122,23 +110,24 @@ def test_launchdarkly_integration_asyncio(
):
"""Assert concurrently evaluated flags do not pollute one another."""

uninstall_integration(LaunchDarklyIntegration.identifier)

asyncio = pytest.importorskip("asyncio")

td = TestData.data_source()
td.update(td.flag("hello").variation_for_all(True))
td.update(td.flag("world").variation_for_all(True))
client = LDClient(
config=Config(
"sdk-key",
update_processor_class=td,
diagnostic_opt_out=True, # Disable background requests as we aren't using a server.
send_events=False,
)
config = Config(
"sdk-key",
update_processor_class=td,
diagnostic_opt_out=True, # Disable background requests as we aren't using a server.
send_events=False,
)
ldclient.set_config(config)
client = ldclient.get()
context = Context.create("user1")

uninstall_integration(LaunchDarklyIntegration.identifier)
sentry_init(integrations=[LaunchDarklyIntegration(ld_client=client)])
sentry_init(integrations=[LaunchDarklyIntegration()])
events = capture_events()

async def task(flag_key):
Expand Down Expand Up @@ -182,72 +171,48 @@ async def runner():
}


def test_launchdarkly_integration_did_not_enable(monkeypatch):
# Client is not passed in and set_config wasn't called.
# TODO: Bad practice to access internals like this. We can skip this test, or remove this
# case entirely (force user to pass in a client instance).
def test_launchdarkly_integration_did_not_enable(uninstall_integration):
# set_config wasn't called.
ldclient._reset_client()
try:
ldclient.__lock.lock()
ldclient.__config = None
finally:
ldclient.__lock.unlock()

with pytest.raises(DidNotEnable):
LaunchDarklyIntegration()
uninstall_integration(LaunchDarklyIntegration.identifier)

td = TestData.data_source()
# Disable background requests as we aren't using a server.
# Required because we corrupt the internal state above.
config = Config(
"sdk-key", update_processor_class=td, diagnostic_opt_out=True, send_events=False
)
# Client not initialized.
client = LDClient(config=config)
monkeypatch.setattr(client, "is_initialized", lambda: False)
with pytest.raises(DidNotEnable):
LaunchDarklyIntegration(ld_client=client)
sentry_sdk.init(
integrations=[LaunchDarklyIntegration()],
)


@pytest.mark.parametrize(
"use_global_client",
(False, True),
)
@pytest.mark.parametrize(
"span_streaming",
[True, False],
)
def test_launchdarkly_span_integration(
sentry_init,
use_global_client,
capture_events,
capture_items,
uninstall_integration,
span_streaming,
):
td = TestData.data_source()
td.update(td.flag("hello").variation_for_all(True))
# Disable background requests as we aren't using a server.
config = Config(
"sdk-key", update_processor_class=td, diagnostic_opt_out=True, send_events=False
)

uninstall_integration(LaunchDarklyIntegration.identifier)
if use_global_client:
ldclient.set_config(config)
sentry_init(
traces_sample_rate=1.0,
integrations=[LaunchDarklyIntegration()],
trace_lifecycle="stream" if span_streaming else "static",
)
client = ldclient.get()
else:
client = LDClient(config=config)
sentry_init(
traces_sample_rate=1.0,
integrations=[LaunchDarklyIntegration(ld_client=client)],
trace_lifecycle="stream" if span_streaming else "static",
)
ldclient.set_config(config)
sentry_init(
traces_sample_rate=1.0,
integrations=[LaunchDarklyIntegration()],
trace_lifecycle="stream" if span_streaming else "static",
)
client = ldclient.get()

if span_streaming:
items = capture_items("span")
Expand Down
Loading