Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(replays): Add denylist feature handling for replay video #3803

Merged
merged 12 commits into from
Jul 10, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- Add support for `all` and `any` `RuleCondition`(s). ([#3791](https://github.com/getsentry/relay/pull/3791))
- Copy root span data from `contexts.trace.data` when converting transaction events into raw spans. ([#3790](https://github.com/getsentry/relay/pull/3790))
- Remove experimental double-write from spans to transactions. ([#3801](https://github.com/getsentry/relay/pull/3801))
- Add feature flag to disable replay-video events. ([#3803](https://github.com/getsentry/relay/pull/3803))

## 24.6.0

Expand Down
5 changes: 5 additions & 0 deletions relay-dynamic-config/src/feature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ pub enum Feature {
/// Serialized as `organizations:session-replay-combined-envelope-items`.
#[serde(rename = "organizations:session-replay-combined-envelope-items")]
SessionReplayCombinedEnvelopeItems,
/// Disables select organizations from processing mobile replay events.
///
/// Serialized as `organizations:session-replay-video-disabled`.
#[serde(rename = "organizations:session-replay-video-disabled")]
SessionReplayVideoDisabled,
/// Enables new User Feedback ingest.
///
/// TODO(jferg): rename to UserFeedbackIngest once old UserReport logic is deprecated.
Expand Down
19 changes: 19 additions & 0 deletions relay-server/src/services/processor/replay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub fn process(
let project_state = &state.project_state;
let replays_enabled = project_state.has_feature(Feature::SessionReplay);
let scrubbing_enabled = project_state.has_feature(Feature::SessionReplayRecordingScrubbing);
let replay_video_disabled = project_state.has_feature(Feature::SessionReplayVideoDisabled);

let meta = state.envelope().meta().clone();
let client_addr = meta.client_addr();
Expand Down Expand Up @@ -60,6 +61,13 @@ pub fn process(
return Ok(());
}

// If the replay video feature is not enabled check the envelope items for a
// replay video event.
if replay_video_disabled && count_replay_video_events(state) > 0 {
state.managed_envelope.drop_items_silently();
return Ok(());
}

for item in state.managed_envelope.envelope_mut().items_mut() {
// Set the combined payload header to the value of the combined feature.
item.set_replay_combined_payload(combined_envelope_items);
Expand Down Expand Up @@ -300,3 +308,14 @@ fn handle_replay_video_item(
)),
}
}

// Pre-processors

fn count_replay_video_events(state: &ProcessEnvelopeState<ReplayGroup>) -> usize {
state
.managed_envelope
.envelope()
.items()
.filter(|item| item.ty() == &ItemType::ReplayVideo)
.count()
}
57 changes: 56 additions & 1 deletion tests/integration/test_replay_videos.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ def test_replay_recording_with_video(
replay_id = "515539018c9b4260a6f999572f1661ee"
relay = relay_with_processing()
mini_sentry.add_basic_project_config(
project_id, extra={"config": {"features": ["organizations:session-replay"]}}
project_id,
extra={"config": {"features": ["organizations:session-replay"]}},
)
replay = generate_replay_sdk_event(replay_id)
replay_events_consumer = replay_events_consumer(timeout=10)
Expand Down Expand Up @@ -76,3 +77,57 @@ def test_replay_recording_with_video(
replay_recordings_consumer.assert_empty()
outcomes_consumer.assert_empty()
replay_events_consumer.assert_empty()


def test_replay_recording_with_video_denied(
mini_sentry,
relay_with_processing,
replay_recordings_consumer,
outcomes_consumer,
replay_events_consumer,
):
project_id = 42
replay_id = "515539018c9b4260a6f999572f1661ee"
relay = relay_with_processing()
mini_sentry.add_basic_project_config(
project_id,
extra={
"config": {
"features": [
"organizations:session-replay",
"organizations:session-replay-video-disabled",
]
}
},
)
replay = generate_replay_sdk_event(replay_id)
replay_events_consumer = replay_events_consumer(timeout=10)
replay_recordings_consumer = replay_recordings_consumer()
outcomes_consumer = outcomes_consumer()

_recording_payload = recording_payload(b"[]")
payload = msgpack.packb(
{
"replay_event": json.dumps(replay).encode(),
"replay_recording": _recording_payload,
"replay_video": b"hello, world!",
}
)

envelope = Envelope(
headers=[
[
"event_id",
replay_id,
],
["attachment_type", "replay_video"],
]
)
envelope.add_item(Item(payload=PayloadRef(bytes=payload), type="replay_video"))

relay.send_envelope(project_id, envelope)

# Assert all conumers are empty.
replay_recordings_consumer.assert_empty()
outcomes_consumer.assert_empty()
replay_events_consumer.assert_empty()
Loading