1
0
mirror of synced 2026-01-01 18:02:53 -05:00
Files
airbyte/airbyte-cdk/python/unit_tests/sources/utils/test_sentry.py
Alexandre Girard 3894134d11 Bump year in license short to 2022 (#13191)
* Bump to 2022

* format
2022-05-25 17:56:49 -07:00

126 lines
5.0 KiB
Python

#
# Copyright (c) 2022 Airbyte, Inc., all rights reserved.
#
import json
import os
from dataclasses import dataclass
from logging import getLogger
from typing import List
from unittest import mock
import requests
from airbyte_cdk.sources.utils.sentry import AirbyteSentry
from sentry_sdk.transport import Transport
@mock.patch("airbyte_cdk.sources.utils.sentry.sentry_sdk")
def test_sentry_init_no_env(sentry_mock):
assert AirbyteSentry.DSN_ENV_NAME not in os.environ
AirbyteSentry.init("test_source")
assert not sentry_mock.init.called
assert not AirbyteSentry.sentry_enabled
AirbyteSentry.set_tag("tagname", "value")
assert not sentry_mock.set_tag.called
AirbyteSentry.add_breadcrumb("msg", data={})
assert not sentry_mock.add_breadcrumb.called
with AirbyteSentry.start_transaction("name", "op"):
assert not sentry_mock.start_transaction.called
with AirbyteSentry.start_transaction_span("name", "op"):
assert not sentry_mock.start_span.called
@mock.patch.dict(os.environ, {AirbyteSentry.DSN_ENV_NAME: "dsn"})
@mock.patch("airbyte_cdk.sources.utils.sentry.sentry_sdk")
def test_sentry_init(sentry_mock):
AirbyteSentry.init("test_source")
assert sentry_mock.init.called
sentry_mock.set_tag.assert_any_call("source", "test_source")
sentry_mock.set_tag.assert_any_call("run_id", mock.ANY)
assert AirbyteSentry.sentry_enabled
AirbyteSentry.set_tag("tagname", "value")
assert sentry_mock.set_tag.called
AirbyteSentry.add_breadcrumb("msg", data={})
assert sentry_mock.add_breadcrumb.called
with AirbyteSentry.start_transaction("name", "op"):
assert sentry_mock.start_transaction.called
with AirbyteSentry.start_transaction_span("name", "op"):
assert sentry_mock.start_span.called
@dataclass
class TestTransport(Transport):
secrets: List[str]
# Sentry sdk wraps sending event with try except that would intercept
# AssertionError exception resulting it would ignore assert directive.
# Use this variable to check if test failed after sentry code executed.
failed = None
def capture_envelope(self, envelop):
for s in self.secrets:
for i in envelop.items:
payload = json.dumps(i.payload.json)
assert s not in payload
def capture_event(self, event):
if self.failed:
return
event = json.dumps(event)
for s in self.secrets:
if s in event:
self.failed = f"{s} should not be in {event}"
return
@mock.patch.dict(os.environ, {AirbyteSentry.DSN_ENV_NAME: "https://22222@222.ingest.sentry.io/111"})
def test_sentry_sensitive_info(httpserver):
SECRET = "SOME_secret"
UNEXPECTED_SECRET = "UnexEpectedSecret"
SECRETS = [SECRET]
transport = TestTransport(secrets=[*SECRETS, UNEXPECTED_SECRET])
AirbyteSentry.init("test_source", transport=transport, secret_values=SECRETS)
AirbyteSentry.add_breadcrumb("msg", {"crumb": SECRET})
AirbyteSentry.set_context("my secret", {"api_key": SECRET})
AirbyteSentry.capture_message(f"this is {SECRET}")
AirbyteSentry.capture_message(f"Issue url http://localhost:{httpserver.port}/test?api_key={UNEXPECTED_SECRET}")
AirbyteSentry.capture_message(f"Issue url http://localhost:{httpserver.port}/test?access_token={UNEXPECTED_SECRET}")
AirbyteSentry.capture_message(f"Issue url http://localhost:{httpserver.port}/test?refresh_token={UNEXPECTED_SECRET}")
AirbyteSentry.set_context("headers", {"Authorization": f"Bearer {UNEXPECTED_SECRET}"})
getLogger("airbyte").info(f"this is {SECRET}")
requests.get(
f"http://localhost:{httpserver.port}/test?api_key={SECRET}",
headers={"Authorization": f"Bearer {SECRET}"},
).text
requests.get(
f"http://localhost:{httpserver.port}/test?api_key={UNEXPECTED_SECRET}",
headers={"Authorization": f"Bearer {UNEXPECTED_SECRET}"},
).text
AirbyteSentry.capture_exception(Exception(f"Secret info: {SECRET}"))
assert not transport.failed
@mock.patch.dict(os.environ, {AirbyteSentry.DSN_ENV_NAME: "https://22222@222.ingest.sentry.io/111"})
def test_sentry_sensitive_info_transactions(httpserver):
SECRET = "SOME_secret"
SECRETS = [SECRET]
UNEXPECTED_SECRET = "UnexEpectedSecret"
transport = TestTransport(secrets=[*SECRETS, UNEXPECTED_SECRET])
AirbyteSentry.init("test_source", transport=transport, secret_values=SECRETS)
AirbyteSentry.set_context("my secret", {"api_key": SECRET})
AirbyteSentry.set_context("headers", {"Authorization": f"Bearer {UNEXPECTED_SECRET}"})
with AirbyteSentry.start_transaction("name", "op"):
with AirbyteSentry.start_transaction_span(
"name", description=f"http://localhost:{httpserver.port}/test?api_key={UNEXPECTED_SECRET}"
):
requests.get(
f"http://localhost:{httpserver.port}/test?api_key={SECRET}",
headers={"Authorization": f"Bearer {SECRET}"},
).text
assert not transport.failed