示例#1
0
def integration_enabled_params(request):
    if request.param == "auto":
        return {"_experiments": {"auto_enabling_integrations": True}}
    elif request.param == "manual":
        return {"integrations": [flask_sentry.FlaskIntegration()]}
    else:
        raise ValueError(request.param)
示例#2
0
def test_errors(sentry_init, capture_exceptions, capture_events, app, debug,
                testing):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])

    app.debug = debug
    app.testing = testing

    @app.route("/")
    def index():
        1 / 0

    exceptions = capture_exceptions()
    events = capture_events()

    client = app.test_client()
    try:
        client.get("/")
    except ZeroDivisionError:
        pass

    exc, = exceptions
    assert isinstance(exc, ZeroDivisionError)

    event, = events
    assert event["exception"]["values"][0]["mechanism"]["type"] == "flask"
示例#3
0
def test_flask_files_and_form(sentry_init, capture_events, app):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()], request_bodies="always")

    data = {"foo": "a" * 2000, "file": (BytesIO(b"hello"), "hello.txt")}

    @app.route("/", methods=["POST"])
    def index():
        assert list(request.form) == ["foo"]
        assert list(request.files) == ["file"]
        assert not request.get_json()
        capture_message("hi")
        return "ok"

    events = capture_events()

    client = app.test_client()
    response = client.post("/", data=data)
    assert response.status_code == 200

    (event,) = events
    assert event["_meta"]["request"]["data"]["foo"] == {
        "": {"len": 2000, "rem": [["!limit", "x", 509, 512]]}
    }
    assert len(event["request"]["data"]["foo"]) == 512

    assert event["_meta"]["request"]["data"]["file"] == {
        "": {"len": 0, "rem": [["!raw", "x", 0, 0]]}
    }
    assert not event["request"]["data"]["file"]
示例#4
0
def test_flask_formdata_request_appear_transaction_body(
        sentry_init, capture_events, app):
    """
    Test that ensures that transaction request data contains body, even if no exception was raised
    """
    sentry_init(integrations=[flask_sentry.FlaskIntegration()],
                traces_sample_rate=1.0)

    data = {"username": "******", "age": "26"}

    @app.route("/", methods=["POST"])
    def index():
        assert request.form["username"] == data["username"]
        assert request.form["age"] == data["age"]
        assert not request.get_data()
        assert not request.get_json()
        set_tag("view", "yes")
        capture_message("hi")
        return "ok"

    events = capture_events()

    client = app.test_client()
    response = client.post("/", data=data)
    assert response.status_code == 200

    event, transaction_event = events

    assert "request" in transaction_event
    assert "data" in transaction_event["request"]
    assert transaction_event["request"]["data"] == data
示例#5
0
def test_does_not_leak_scope(sentry_init, capture_events, app):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])
    events = capture_events()

    with configure_scope() as scope:
        scope.set_tag("request_data", False)

    @app.route("/")
    def index():
        with configure_scope() as scope:
            scope.set_tag("request_data", True)

        def generate():
            for row in range(1000):
                with configure_scope() as scope:
                    assert scope._tags["request_data"]

                yield str(row) + "\n"

        return Response(stream_with_context(generate()), mimetype="text/csv")

    client = app.test_client()
    response = client.get("/")
    assert response.data.decode() == "".join(
        str(row) + "\n" for row in range(1000))
    assert not events

    with configure_scope() as scope:
        assert not scope._tags["request_data"]
示例#6
0
def test_flask_large_json_request(sentry_init, capture_events, app):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])

    data = {"foo": {"bar": "a" * 2000}}

    @app.route("/", methods=["POST"])
    def index():
        assert request.json == data
        assert request.data == json.dumps(data).encode("ascii")
        assert not request.form
        capture_message("hi")
        return "ok"

    events = capture_events()

    client = app.test_client()
    response = client.post("/",
                           content_type="application/json",
                           data=json.dumps(data))
    assert response.status_code == 200

    event, = events
    assert event[""]["request"]["data"]["foo"]["bar"] == {
        "": {
            "len": 2000,
            "rem": [["!limit", "x", 509, 512]]
        }
    }
    assert len(event["request"]["data"]["foo"]["bar"]) == 512
示例#7
0
def test_flask_medium_formdata_request(sentry_init, capture_events, app):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])

    data = {"foo": "a" * 2000}

    @app.route("/", methods=["POST"])
    def index():
        assert request.form["foo"] == data["foo"]
        assert not request.data
        assert not request.json
        capture_message("hi")
        return "ok"

    events = capture_events()

    client = app.test_client()
    response = client.post("/", data=data)
    assert response.status_code == 200

    event, = events
    assert event[""]["request"]["data"]["foo"] == {
        "": {
            "len": 2000,
            "rem": [["!limit", "x", 509, 512]]
        }
    }
    assert len(event["request"]["data"]["foo"]) == 512
示例#8
0
def test_flask_too_large_raw_request(sentry_init, input_char, capture_events,
                                     app):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()],
                request_bodies="small")

    data = input_char * 2000

    @app.route("/", methods=["POST"])
    def index():
        assert not request.form
        if isinstance(data, bytes):
            assert request.data == data
        else:
            assert request.data == data.encode("ascii")
        assert not request.json
        capture_message("hi")
        return "ok"

    events = capture_events()

    client = app.test_client()
    response = client.post("/", data=data)
    assert response.status_code == 200

    event, = events
    assert event[""]["request"]["data"] == {
        "": {
            "len": 2000,
            "rem": [["!config", "x", 0, 2000]]
        }
    }
    assert not event["request"]["data"]
示例#9
0
def test_tracing_success(sentry_init, capture_events, app):
    sentry_init(traces_sample_rate=1.0,
                integrations=[flask_sentry.FlaskIntegration()])

    @app.before_request
    def _():
        set_tag("before_request", "yes")

    @app.route("/message_tx")
    def hi_tx():
        set_tag("view", "yes")
        capture_message("hi")
        return "ok"

    events = capture_events()

    with app.test_client() as client:
        response = client.get("/message_tx")
        assert response.status_code == 200

    message_event, transaction_event = events

    assert transaction_event["type"] == "transaction"
    assert transaction_event["transaction"] == "hi_tx"
    assert transaction_event["contexts"]["trace"]["status"] == "ok"
    assert transaction_event["tags"]["view"] == "yes"
    assert transaction_event["tags"]["before_request"] == "yes"

    assert message_event["message"] == "hi"
    assert message_event["transaction"] == "hi_tx"
    assert message_event["tags"]["view"] == "yes"
    assert message_event["tags"]["before_request"] == "yes"
示例#10
0
def test_error_in_errorhandler(sentry_init, capture_events, app):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])

    app.debug = False
    app.testing = False

    @app.route("/")
    def index():
        raise ValueError()

    @app.errorhandler(500)
    def error_handler(err):
        1 / 0

    events = capture_events()

    client = app.test_client()

    with pytest.raises(ZeroDivisionError):
        client.get("/")

    event1, event2 = events

    (exception, ) = event1["exception"]["values"]
    assert exception["type"] == "ValueError"

    exception = event2["exception"]["values"][-1]
    assert exception["type"] == "ZeroDivisionError"
示例#11
0
def test_scoped_test_client(sentry_init, app):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])

    @app.route("/")
    def index():
        return "ok"

    with app.test_client() as client:
        response = client.get("/")
        assert response.status_code == 200
示例#12
0
def test_flask_login_not_configured(sentry_init, app, capture_events, monkeypatch):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])

    assert flask_sentry.flask_login

    events = capture_events()
    client = app.test_client()
    client.get("/message")

    event, = events
    assert event.get("user", {}).get("id") is None
示例#13
0
def test_dont_override_sentry_trace_context(sentry_init, app):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])

    @app.route("/")
    def index():
        return render_template_string("{{ sentry_trace }}", sentry_trace="hi")

    with app.test_client() as client:
        response = client.get("/")
        assert response.status_code == 200
        assert response.data == b"hi"
示例#14
0
def register_error_handlers(app):
    @app.register_error_handler(OleaException)
    def handle_olea_exceptions(e):
        return jsonify({'code': e.code, 'parms': e.parms}), 409

    if not app.config.get('IGNORE_ERRORS', False):
        sentry_sdk_init(dsn=app.config['SENTRY_DSN'],
                        integrations=[
                            flask.FlaskIntegration(),
                            sqlalchemy.SqlalchemyIntegration(),
                            redis.RedisIntegration()
                        ])
示例#15
0
def test_has_context(sentry_init, app, capture_events):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])
    events = capture_events()

    client = app.test_client()
    response = client.get("/message")
    assert response.status_code == 200

    event, = events
    assert event["transaction"] == "hi"
    assert "data" not in event["request"]
    assert event["request"]["url"] == "http://localhost/message"
示例#16
0
def test_flask_login_not_installed(sentry_init, app, capture_events, monkeypatch):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])

    monkeypatch.setattr(flask_sentry, "flask_login", None)

    events = capture_events()

    client = app.test_client()
    client.get("/message")

    event, = events
    assert event.get("user", {}).get("id") is None
示例#17
0
def test_transaction_style(sentry_init, app, capture_events, transaction_style,
                           expected_transaction):
    sentry_init(integrations=[
        flask_sentry.FlaskIntegration(transaction_style=transaction_style)
    ])
    events = capture_events()

    client = app.test_client()
    response = client.get("/message")
    assert response.status_code == 200

    (event, ) = events
    assert event["transaction"] == expected_transaction
示例#18
0
def test_bad_request_not_captured(sentry_init, capture_events, app):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])
    events = capture_events()

    @app.route("/")
    def index():
        abort(400)

    client = app.test_client()

    client.get("/")

    assert not events
示例#19
0
def test_flask_login_partially_configured(sentry_init, app, capture_events,
                                          monkeypatch):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])

    events = capture_events()

    login_manager = LoginManager()
    login_manager.init_app(app)

    client = app.test_client()
    client.get("/message")

    event, = events
    assert event.get("user", {}).get("id") is None
示例#20
0
def configure():
    """Configure Sentry logging integration for Celery.

    See the `official instructions for Celery integration
    <https://docs.sentry.io/platforms/python/celery/>`_.

    Notes
    -----
    Add the API key username/pasword pair to your netrc file.

    """
    # Catching NetrcParseError confuses sphinx.
    if SPHINX:  # pragma: no cover
        return

    # Delayed import
    from .. import app

    scheme, netloc, *rest = urlparse(DSN)

    try:
        auth = netrc().authenticators(netloc)
        if not auth:
            raise ValueError('No netrc entry found for {}'.format(netloc))
    except (NetrcParseError, OSError, ValueError):
        log.exception(
            'Disabling Sentry integration because we could not load '
            'the username and password for %s from the netrc file', netloc)
        return

    # The "legacy" Sentry DSN requires a "public key" and a "private key",
    # which are transmitted as the username and password in the URL.
    # However, as of Sentry 9, then "private key" part is no longer required.
    username, _, _ = auth
    dsn = urlunparse((scheme, '{}@{}'.format(username, netloc), *rest))
    version = 'gwcelery-{}'.format(_version.get_versions()['version'])
    environment = app.conf['sentry_environment']
    sentry_sdk.init(dsn,
                    environment=environment,
                    release=version,
                    integrations=[
                        celery.CeleryIntegration(),
                        condor.CondorIntegration(),
                        flask.FlaskIntegration(),
                        redis.RedisIntegration(),
                        requests.RequestsIntegration(),
                        subprocess.SubprocessIntegration(),
                        tornado.TornadoIntegration()
                    ])
示例#21
0
def test_sentry_trace_context(sentry_init, app, capture_events):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])
    events = capture_events()

    @app.route("/")
    def index():
        sentry_span = Hub.current.scope.span
        capture_message(sentry_span.to_traceparent())
        return render_template_string("{{ sentry_trace }}")

    with app.test_client() as client:
        response = client.get("/")
        assert response.status_code == 200
        assert response.data.decode(
            "utf-8") == '<meta name="sentry-trace" content="%s" />' % (
                events[0]["message"], )
示例#22
0
def test_tracing_success(sentry_init, capture_events, app):
    sentry_init(traces_sample_rate=1.0,
                integrations=[flask_sentry.FlaskIntegration()])

    events = capture_events()

    with app.test_client() as client:
        response = client.get("/message")
        assert response.status_code == 200

    message_event, transaction_event = events

    assert transaction_event["type"] == "transaction"
    assert transaction_event["transaction"] == "hi"
    assert transaction_event["contexts"]["trace"]["status"] == "ok"

    assert message_event["message"] == "hi"
    assert message_event["transaction"] == "hi"
示例#23
0
def test_logging(sentry_init, capture_events, app):
    # ensure that Flask's logger magic doesn't break ours
    sentry_init(integrations=[
        flask_sentry.FlaskIntegration(),
        LoggingIntegration(event_level="ERROR"),
    ])

    @app.route("/")
    def index():
        app.logger.error("hi")
        return "ok"

    events = capture_events()

    client = app.test_client()
    client.get("/")

    event, = events
    assert event["level"] == "error"
示例#24
0
def test_flask_session_tracking(sentry_init, capture_envelopes, app):
    sentry_init(
        integrations=[flask_sentry.FlaskIntegration()],
        release="demo-release",
        _experiments=dict(
            auto_session_tracking=True,
        ),
    )

    @app.route("/")
    def index():
        with configure_scope() as scope:
            scope.set_user({"ip_address": "1.2.3.4", "id": "42"})
        try:
            raise ValueError("stuff")
        except Exception:
            logging.exception("stuff happened")
        1 / 0

    envelopes = capture_envelopes()

    with app.test_client() as client:
        try:
            client.get("/", headers={"User-Agent": "blafasel/1.0"})
        except ZeroDivisionError:
            pass

    Hub.current.client.flush()

    (first_event, error_event, session) = envelopes
    first_event = first_event.get_event()
    error_event = error_event.get_event()
    session = session.items[0].payload.json

    assert first_event["exception"]["values"][0]["type"] == "ValueError"
    assert error_event["exception"]["values"][0]["type"] == "ZeroDivisionError"
    assert session["status"] == "crashed"
    assert session["did"] == "42"
    assert session["errors"] == 2
    assert session["init"]
    assert session["attrs"]["release"] == "demo-release"
    assert session["attrs"]["ip_address"] == "1.2.3.4"
    assert session["attrs"]["user_agent"] == "blafasel/1.0"
示例#25
0
def test_flask_empty_json_request(sentry_init, capture_events, app, data):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])

    @app.route("/", methods=["POST"])
    def index():
        assert request.get_json() == data
        assert request.get_data() == json.dumps(data).encode("ascii")
        assert not request.form
        capture_message("hi")
        return "ok"

    events = capture_events()

    client = app.test_client()
    response = client.post("/", content_type="application/json", data=json.dumps(data))
    assert response.status_code == 200

    (event,) = events
    assert event["request"]["data"] == data
示例#26
0
文件: __init__.py 项目: Pix-00/olea
def register_error_handlers(app):
    from flask_json import json_response

    # - - - - - - - - - - - - - - - - - - - - - - -
    @app.errorhandler(BaseError)
    def handle_olea_exceptions(e: BaseError):
        return json_response(status_=e.http_code, data_=e)

    # - - - - - - - - - - - - - - - - - - - - - - -
    from sentry_sdk import init as sentry_init
    from sentry_sdk.integrations import flask, redis, sqlalchemy

    if not app.config.get('IGNORE_ERRORS', False):
        sentry_init(dsn=app.config['SENTRY_DSN'],
                    integrations=[
                        flask.FlaskIntegration(),
                        sqlalchemy.SqlalchemyIntegration(),
                        redis.RedisIntegration(),
                    ],
                    traces_sample_rate=0.2)
示例#27
0
def test_class_based_views(sentry_init, app, capture_events):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])
    events = capture_events()

    @app.route("/")
    class HelloClass(View):
        def dispatch_request(self):
            capture_message("hi")
            return "ok"

    app.add_url_rule("/hello-class/", view_func=HelloClass.as_view("hello_class"))

    with app.test_client() as client:
        response = client.get("/hello-class/")
        assert response.status_code == 200

    (event,) = events

    assert event["message"] == "hi"
    assert event["transaction"] == "hello_class"
示例#28
0
def test_500(sentry_init, capture_events, app):
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])

    app.debug = False
    app.testing = False

    @app.route("/")
    def index():
        1 / 0

    @app.errorhandler(500)
    def error_handler(err):
        return "Sentry error: %s" % last_event_id()

    events = capture_events()

    client = app.test_client()
    response = client.get("/")

    (event,) = events
    assert response.data.decode("utf-8") == "Sentry error: %s" % event["event_id"]
示例#29
0
def test_errorhandler_for_exception_swallows_exception(sentry_init, app,
                                                       capture_events,
                                                       exc_cls):
    # In contrast to error handlers for a status code, error
    # handlers for exceptions can swallow the exception (this is
    # just how the Flask signal works)
    sentry_init(integrations=[flask_sentry.FlaskIntegration()])
    events = capture_events()

    @app.route("/")
    def index():
        1 / 0

    @app.errorhandler(exc_cls)
    def zerodivision(e):
        return "ok"

    with app.test_client() as client:
        response = client.get("/")
        assert response.status_code == 200

    assert not events
示例#30
0
def create_wsgi():
    application = FlaskApp(__name__)
    config = settings.load_config((
        settings.FlaskSettings,
        settings.SentrySetting,
    ))
    application.app.config.from_object(config)
    CORS(application.app)

    application.add_api(specification='v1/openapi.yaml',
                        resolver=VersionResolver('app.http.v1.handlers'),
                        strict_validation=True,
                        validate_responses=True)

    @application.app.teardown_appcontext
    def shutdown_session(exception):
        models.session.remove()

    sentry_init(dsn=config.SENTRY_DSN,
                integrations=[sentry_flask.FlaskIntegration()])

    return application