def test_sample_rates_metrics(mini_sentry, relay_with_processing, events_consumer): events_consumer = events_consumer() relay = relay_with_processing() mini_sentry.add_basic_project_config(42) sample_rates = [ { "id": "client_sampler", "rate": 0.01 }, { "id": "dyanmic_user", "rate": 0.5 }, ] envelope = Envelope() envelope.add_event({"message": "hello, world!"}) envelope.items[0].headers["sample_rates"] = sample_rates relay.send_envelope(42, envelope) event, _ = events_consumer.get_event() assert event["_metrics"]["sample_rates"] == sample_rates
def test_basic_event(): envelope = Envelope() expected = {"message": "Hello, World!"} envelope.add_event(expected) assert envelope.get_event() == {"message": "Hello, World!"}
def test_strip_measurement_interface(mini_sentry, relay_with_processing, events_consumer): events_consumer = events_consumer() relay = relay_with_processing() mini_sentry.add_basic_project_config(42) envelope = Envelope() envelope.add_event({ "message": "Hello, World!", "measurements": { "LCP": { "value": 420.69 }, "fid": { "value": 2020 }, "cls": { "value": None }, }, }) relay.send_envelope(42, envelope) event, _ = events_consumer.get_event() assert event["logentry"] == {"formatted": "Hello, World!"} # expect measurements interface object to be stripped out since it's attached to a non-transaction event assert "measurements" not in event, event
def inner(user): project_info = get_project_info(user) envelope = Envelope() envelope.add_event(event) return send_envelope(user.client, project_info.id, project_info.key, envelope)
def inner(task_set: TaskSet): event = event_generator() project_info = get_project_info(task_set) envelope = Envelope() envelope.add_event(event) return send_envelope(task_set.client, project_info.id, project_info.key, envelope)
def _create_event_envelope(public_key): envelope = Envelope() event, trace_id, event_id = _create_event_item() envelope.add_event(event) _add_trace_info(envelope, trace_id=trace_id, public_key=public_key) return envelope, trace_id, event_id
def test_envelope(mini_sentry, relay_chain): relay = relay_chain() mini_sentry.project_configs[42] = relay.basic_project_config() envelope = Envelope() envelope.add_event({"message": "Hello, World!"}) relay.send_envelope(42, envelope) event = mini_sentry.captured_events.get(timeout=1).get_event() assert event["logentry"] == {"formatted": "Hello, World!"}
def test_envelope_without_header(mini_sentry, relay): relay = relay(mini_sentry) PROJECT_ID = 42 mini_sentry.add_basic_project_config(PROJECT_ID) envelope = Envelope(headers={"dsn": relay.get_dsn(PROJECT_ID)}) envelope.add_event({"message": "Hello, World!"}) relay.send_envelope( PROJECT_ID, envelope, headers={"X-Sentry-Auth": ""}, # Empty auth header is ignored by Relay ) event = mini_sentry.captured_events.get(timeout=1).get_event() assert event["logentry"] == {"formatted": "Hello, World!"}
def test_sample_rates(mini_sentry, relay_chain): relay = relay_chain(min_relay_version="21.1.0") mini_sentry.add_basic_project_config(42) sample_rates = [ {"id": "client_sampler", "rate": 0.01}, {"id": "dyanmic_user", "rate": 0.5}, ] envelope = Envelope() envelope.add_event({"message": "hello, world!"}) envelope.items[0].headers["sample_rates"] = sample_rates relay.send_envelope(42, envelope) envelope = mini_sentry.captured_events.get(timeout=1) assert envelope.items[0].headers["sample_rates"] == sample_rates
def test_multi_item_envelope(mini_sentry, relay): """ Test that multi item envelopes are handled correctly. Pass an envelope containing of a transaction that will be sampled and an event and test """ project_id = 42 relay = relay(mini_sentry, _outcomes_enabled_config()) # create a basic project config config = mini_sentry.add_basic_project_config(project_id) # add a sampling rule to project config that removes all transactions (sample_rate=0) public_key = config["publicKeys"][0]["publicKey"] _add_sampling_config(config, project_ids=[project_id], sample_rate=0) # we'll run the test twice to make sure that the fast path works as well for i in range(2): # create an envelope with a trace context that is initiated by this project (for simplicity) envelope = Envelope() transaction, trace_id = _create_transaction_item() envelope.add_transaction(transaction) envelope.add_event({"message": "Hello"}) _add_trace_info(envelope, trace_id=trace_id, public_key=public_key) # send the event, the transaction should be removed. relay.send_envelope(project_id, envelope) msg = mini_sentry.captured_events.get(timeout=1) assert msg is not None transaction = msg.get_transaction_event() event = msg.get_event() # check that the transaction was removed during the transaction sampling process assert transaction is None # but the event was kept assert event is not None assert event.setdefault("logentry", {}).get("formatted") == "Hello" # no outcome should be generated since we forward the event to upstream # NOTE this might change in the future so we might get outcomes here in the future with pytest.raises(queue.Empty): mini_sentry.captured_outcomes.get(timeout=2)
def append_event(event): envelope = Envelope() envelope.add_event(event) envelopes.append(envelope) return old_capture_event(event)
def capture_event( self, event, # type: Event hint=None, # type: Optional[Hint] scope=None, # type: Optional[Scope] ): # type: (...) -> Optional[str] """Captures an event. :param event: A ready-made event that can be directly sent to Sentry. :param hint: Contains metadata about the event that can be read from `before_send`, such as the original exception object or a HTTP request object. :returns: An event ID. May be `None` if there is no DSN set or of if the SDK decided to discard the event for other reasons. In such situations setting `debug=True` on `init()` may help. """ if disable_capture_event.get(False): return None if self.transport is None: return None if hint is None: hint = {} event_id = event.get("event_id") hint = dict(hint or ()) # type: Hint if event_id is None: event["event_id"] = event_id = uuid.uuid4().hex if not self._should_capture(event, hint, scope): return None event_opt = self._prepare_event(event, hint, scope) if event_opt is None: return None # whenever we capture an event we also check if the session needs # to be updated based on that information. session = scope._session if scope else None if session: self._update_session_from_event(session, event) attachments = hint.get("attachments") is_transaction = event_opt.get("type") == "transaction" if is_transaction or attachments: # Transactions or events with attachments should go to the # /envelope/ endpoint. envelope = Envelope( headers={ "event_id": event_opt["event_id"], "sent_at": format_timestamp(datetime.utcnow()), }) if is_transaction: envelope.add_transaction(event_opt) else: envelope.add_event(event_opt) for attachment in attachments or (): envelope.add_item(attachment.to_envelope_item()) self.transport.capture_envelope(envelope) else: # All other events go to the /store/ endpoint. self.transport.capture_event(event_opt) return event_id
def capture_event( self, event, # type: Event hint=None, # type: Optional[Hint] scope=None, # type: Optional[Scope] ): # type: (...) -> Optional[str] """Captures an event. :param event: A ready-made event that can be directly sent to Sentry. :param hint: Contains metadata about the event that can be read from `before_send`, such as the original exception object or a HTTP request object. :returns: An event ID. May be `None` if there is no DSN set or of if the SDK decided to discard the event for other reasons. In such situations setting `debug=True` on `init()` may help. """ if disable_capture_event.get(False): return None if self.transport is None: return None if hint is None: hint = {} event_id = event.get("event_id") hint = dict(hint or ()) # type: Hint if event_id is None: event["event_id"] = event_id = uuid.uuid4().hex if not self._should_capture(event, hint, scope): return None event_opt = self._prepare_event(event, hint, scope) if event_opt is None: return None # whenever we capture an event we also check if the session needs # to be updated based on that information. session = scope._session if scope else None if session: self._update_session_from_event(session, event) is_transaction = event_opt.get("type") == "transaction" if not is_transaction and not self._should_sample_error(event): return None attachments = hint.get("attachments") # this is outside of the `if` immediately below because even if we don't # use the value, we want to make sure we remove it before the event is # sent raw_tracestate = (event_opt.get("contexts", {}).get("trace", {}).pop("tracestate", "")) # Transactions or events with attachments should go to the /envelope/ # endpoint. if is_transaction or attachments: headers = { "event_id": event_opt["event_id"], "sent_at": format_timestamp(datetime.utcnow()), } tracestate_data = raw_tracestate and reinflate_tracestate( raw_tracestate.replace("sentry=", "")) if tracestate_data and has_tracestate_enabled(): headers["trace"] = tracestate_data envelope = Envelope(headers=headers) if is_transaction: envelope.add_transaction(event_opt) else: envelope.add_event(event_opt) for attachment in attachments or (): envelope.add_item(attachment.to_envelope_item()) self.transport.capture_envelope(envelope) else: # All other events go to the /store/ endpoint. self.transport.capture_event(event_opt) return event_id