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
15 changes: 6 additions & 9 deletions sentry_sdk/integrations/cohere.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,6 @@ class CohereIntegration(Integration):
identifier = "cohere"
origin = f"auto.ai.{identifier}"

def __init__(self: "CohereIntegration", include_prompts: bool = True) -> None:
self.include_prompts = include_prompts

@staticmethod
def setup_once() -> None:
version = parse_version(COHERE_VERSION)
Expand All @@ -93,12 +90,12 @@ def setup_once() -> None:
BaseCohere.chat_stream = _wrap_chat(BaseCohere.chat_stream, streaming=True)


def _should_record(integration: "CohereIntegration", category: str) -> bool:
def _should_record(category: str) -> bool:
client = sentry_sdk.get_client()
if has_data_collection_enabled(client.options):
return bool(client.options["data_collection"]["gen_ai"][category])

return should_send_default_pii() and integration.include_prompts
return should_send_default_pii()


def _capture_exception(exc: "Any") -> None:
Expand Down Expand Up @@ -180,7 +177,7 @@ def new_chat(*args: "Any", **kwargs: "Any") -> "Any":
reraise(*exc_info)

with capture_internal_exceptions():
if _should_record(integration, "inputs"):
if _should_record("inputs"):
set_data_normalized(
span,
SPANDATA.AI_INPUT_MESSAGES,
Expand Down Expand Up @@ -216,7 +213,7 @@ def new_iterator() -> "Iterator[StreamedChatResponse]":
collect_chat_response_fields(
span,
x.response,
include_pii=_should_record(integration, "outputs"),
include_pii=_should_record("outputs"),
)
yield x
span.end()
Expand All @@ -226,7 +223,7 @@ def new_iterator() -> "Iterator[StreamedChatResponse]":
collect_chat_response_fields(
span,
res,
include_pii=_should_record(integration, "outputs"),
include_pii=_should_record("outputs"),
)
span.end()
else:
Expand All @@ -251,7 +248,7 @@ def new_embed(*args: "Any", **kwargs: "Any") -> "Any":
"sentry.origin": CohereIntegration.origin,
},
) as span:
if "texts" in kwargs and _should_record(integration, "inputs"):
if "texts" in kwargs and _should_record("inputs"):
if isinstance(kwargs["texts"], str):
set_data_normalized(span, SPANDATA.AI_TEXTS, [kwargs["texts"]])
elif (
Expand Down
53 changes: 18 additions & 35 deletions tests/integrations/cohere/test_cohere.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,16 @@


@pytest.mark.parametrize(
"send_default_pii, include_prompts",
[(True, True), (True, False), (False, True), (False, False)],
"send_default_pii",
[True, False],
)
def test_nonstreaming_chat(
sentry_init,
capture_items,
send_default_pii,
include_prompts,
):
sentry_init(
integrations=[CohereIntegration(include_prompts=include_prompts)],
integrations=[CohereIntegration()],
traces_sample_rate=1.0,
send_default_pii=send_default_pii,
)
Expand Down Expand Up @@ -59,7 +58,7 @@ def test_nonstreaming_chat(
assert span["attributes"]["sentry.op"] == "ai.chat_completions.create.cohere"
assert span["attributes"][SPANDATA.AI_MODEL_ID] == "some-model"

if send_default_pii and include_prompts:
if send_default_pii:
assert (
'{"role": "system", "content": "some context"}'
in span["attributes"][SPANDATA.AI_INPUT_MESSAGES]
Expand All @@ -80,17 +79,16 @@ def test_nonstreaming_chat(

# noinspection PyTypeChecker
@pytest.mark.parametrize(
"send_default_pii, include_prompts",
[(True, True), (True, False), (False, True), (False, False)],
"send_default_pii",
[True, False],
)
def test_streaming_chat(
sentry_init,
capture_items,
send_default_pii,
include_prompts,
):
sentry_init(
integrations=[CohereIntegration(include_prompts=include_prompts)],
integrations=[CohereIntegration()],
traces_sample_rate=1.0,
send_default_pii=send_default_pii,
)
Expand Down Expand Up @@ -142,7 +140,7 @@ def test_streaming_chat(
assert span["attributes"]["sentry.op"] == "ai.chat_completions.create.cohere"
assert span["attributes"][SPANDATA.AI_MODEL_ID] == "some-model"

if send_default_pii and include_prompts:
if send_default_pii:
assert (
'{"role": "system", "content": "some context"}'
in span["attributes"][SPANDATA.AI_INPUT_MESSAGES]
Expand Down Expand Up @@ -206,17 +204,16 @@ def test_span_status_error(sentry_init, capture_items):


@pytest.mark.parametrize(
"send_default_pii, include_prompts",
[(True, True), (True, False), (False, True), (False, False)],
"send_default_pii",
[True, False],
)
def test_embed(
sentry_init,
capture_items,
send_default_pii,
include_prompts,
):
sentry_init(
integrations=[CohereIntegration(include_prompts=include_prompts)],
integrations=[CohereIntegration()],
traces_sample_rate=1.0,
send_default_pii=send_default_pii,
)
Expand Down Expand Up @@ -249,7 +246,7 @@ def test_embed(
span = items[0].payload

assert span["attributes"]["sentry.op"] == "ai.embeddings.create.cohere"
if send_default_pii and include_prompts:
if send_default_pii:
assert "hello" in span["attributes"][SPANDATA.AI_INPUT_MESSAGES]
else:
assert SPANDATA.AI_INPUT_MESSAGES not in span["attributes"]
Expand Down Expand Up @@ -326,28 +323,25 @@ def test_span_origin_embed(sentry_init, capture_items):
assert span["attributes"]["sentry.origin"] == "auto.ai.cohere"


# data_collection config, send_default_pii, include_prompts, expect_inputs, expect_outputs
# data_collection config, send_default_pii, expect_inputs, expect_outputs
DATA_COLLECTION_CASES = [
pytest.param(
{"gen_ai": {"inputs": True, "outputs": True}},
False,
False,
True,
True,
id="gen-ai-inputs-and-outputs-enabled-override-legacy-off",
),
pytest.param(
{"gen_ai": {"inputs": False, "outputs": False}},
True,
True,
False,
False,
id="gen-ai-inputs-and-outputs-disabled-override-legacy-on",
),
pytest.param(
{"gen_ai": {"inputs": True, "outputs": False}},
False,
False,
True,
False,
id="gen-ai-inputs-enabled-outputs-disabled",
Expand All @@ -356,14 +350,12 @@ def test_span_origin_embed(sentry_init, capture_items):
{"gen_ai": {"inputs": False, "outputs": True}},
False,
False,
False,
True,
id="gen-ai-outputs-enabled-inputs-disabled",
),
pytest.param(
{"gen_ai": {}},
False,
False,
True,
True,
id="gen-ai-inputs-and-outputs-omitted-default-to-enabled",
Expand All @@ -373,13 +365,11 @@ def test_span_origin_embed(sentry_init, capture_items):
True,
True,
True,
True,
id="no-gen-ai-config-legacy-pii-and-include-prompts-enabled",
id="no-gen-ai-config-legacy-pii",
),
pytest.param(
None,
False,
True,
False,
False,
id="no-gen-ai-config-legacy-pii-disabled",
Expand All @@ -391,10 +381,9 @@ def _init_with_data_collection(
sentry_init,
data_collection,
send_default_pii,
include_prompts,
):
kwargs = dict(
integrations=[CohereIntegration(include_prompts=include_prompts)],
integrations=[CohereIntegration()],
traces_sample_rate=1.0,
send_default_pii=send_default_pii,
)
Expand All @@ -405,23 +394,21 @@ def _init_with_data_collection(


@pytest.mark.parametrize(
"data_collection, send_default_pii, include_prompts, expect_inputs, expect_outputs",
"data_collection, send_default_pii, expect_inputs, expect_outputs",
DATA_COLLECTION_CASES,
)
def test_nonstreaming_chat_data_collection(
sentry_init,
capture_items,
data_collection,
send_default_pii,
include_prompts,
expect_inputs,
expect_outputs,
):
_init_with_data_collection(
sentry_init,
data_collection,
send_default_pii,
include_prompts,
)

client = Client(api_key="z")
Expand Down Expand Up @@ -483,23 +470,21 @@ def test_nonstreaming_chat_data_collection(


@pytest.mark.parametrize(
"data_collection, send_default_pii, include_prompts, expect_inputs, expect_outputs",
"data_collection, send_default_pii, expect_inputs, expect_outputs",
DATA_COLLECTION_CASES,
)
def test_streaming_chat_data_collection(
sentry_init,
capture_items,
data_collection,
send_default_pii,
include_prompts,
expect_inputs,
expect_outputs,
):
_init_with_data_collection(
sentry_init,
data_collection,
send_default_pii,
include_prompts,
)

client = Client(api_key="z")
Expand Down Expand Up @@ -574,23 +559,21 @@ def test_streaming_chat_data_collection(


@pytest.mark.parametrize(
"data_collection, send_default_pii, include_prompts, expect_inputs, expect_outputs",
"data_collection, send_default_pii, expect_inputs, expect_outputs",
DATA_COLLECTION_CASES,
)
def test_embed_data_collection(
sentry_init,
capture_items,
data_collection,
send_default_pii,
include_prompts,
expect_inputs,
expect_outputs,
):
_init_with_data_collection(
sentry_init,
data_collection,
send_default_pii,
include_prompts,
)

client = Client(api_key="z")
Expand Down
Loading