@@ -12,6 +12,13 @@ use std::sync::Arc;
12
12
use std:: time:: Duration ;
13
13
use std:: { fmt, mem} ;
14
14
15
+ use crate :: envelope:: ItemType ;
16
+ #[ cfg( feature = "processing" ) ]
17
+ use crate :: service:: ServiceError ;
18
+ use crate :: services:: processor:: { EnvelopeProcessor , SubmitClientReports } ;
19
+ use crate :: services:: upstream:: { Method , SendQuery , UpstreamQuery , UpstreamRelay } ;
20
+ use crate :: statsd:: RelayCounters ;
21
+ use crate :: utils:: SleepHandle ;
15
22
use chrono:: { DateTime , SecondsFormat , Utc } ;
16
23
use relay_base_schema:: organization:: OrganizationId ;
17
24
use relay_base_schema:: project:: ProjectId ;
@@ -29,13 +36,6 @@ use relay_statsd::metric;
29
36
use relay_system:: { Addr , FromMessage , Interface , NoResponse , Service } ;
30
37
use serde:: { Deserialize , Serialize } ;
31
38
32
- #[ cfg( feature = "processing" ) ]
33
- use crate :: service:: ServiceError ;
34
- use crate :: services:: processor:: { EnvelopeProcessor , SubmitClientReports } ;
35
- use crate :: services:: upstream:: { Method , SendQuery , UpstreamQuery , UpstreamRelay } ;
36
- use crate :: statsd:: RelayCounters ;
37
- use crate :: utils:: SleepHandle ;
38
-
39
39
/// Defines the structure of the HTTP outcomes requests
40
40
#[ derive( Debug , Default , Deserialize , Serialize ) ]
41
41
pub struct SendOutcomes {
@@ -205,6 +205,9 @@ impl Outcome {
205
205
/// Returns the `reason` code field of this outcome.
206
206
pub fn to_reason ( & self ) -> Option < Cow < ' _ , str > > {
207
207
match self {
208
+ Outcome :: Invalid ( DiscardReason :: TooLarge ( too_large_reason) ) => Some ( Cow :: Owned (
209
+ format ! ( "too_large:{}" , too_large_reason. as_str( ) ) ,
210
+ ) ) ,
208
211
Outcome :: Invalid ( discard_reason) => Some ( Cow :: Borrowed ( discard_reason. name ( ) ) ) ,
209
212
Outcome :: Filtered ( filter_key) => Some ( filter_key. clone ( ) . name ( ) ) ,
210
213
Outcome :: FilteredSampling ( rule_ids) => Some ( Cow :: Owned ( format ! ( "Sampled:{rule_ids}" ) ) ) ,
@@ -356,7 +359,7 @@ pub enum DiscardReason {
356
359
EmptyEnvelope ,
357
360
358
361
/// (Relay) The event payload exceeds the maximum size limit for the respective endpoint.
359
- TooLarge ,
362
+ TooLarge ( DiscardItemType ) ,
360
363
361
364
/// (Legacy) A store request was received with an invalid method.
362
365
///
@@ -476,7 +479,7 @@ impl DiscardReason {
476
479
DiscardReason :: AuthVersion => "auth_version" ,
477
480
DiscardReason :: AuthClient => "auth_client" ,
478
481
DiscardReason :: NoData => "no_data" ,
479
- DiscardReason :: TooLarge => "too_large" ,
482
+ DiscardReason :: TooLarge ( discard ) => discard . as_str ( ) ,
480
483
DiscardReason :: DisallowedMethod => "disallowed_method" ,
481
484
DiscardReason :: ContentType => "content_type" ,
482
485
DiscardReason :: MultiProjectId => "multi_project_id" ,
@@ -524,6 +527,149 @@ impl fmt::Display for DiscardReason {
524
527
}
525
528
}
526
529
530
+ /// Similar to [`ItemType`] but it does not have any additional information in the
531
+ /// Unknown variant so that it can derive [`Copy`] and be used from [`DiscardReason`].
532
+ /// The variants should be the same as [`ItemType`].
533
+ #[ derive( Copy , Clone , Debug , Eq , Hash , Ord , PartialEq , PartialOrd ) ]
534
+ pub enum DiscardItemType {
535
+ /// Event payload encoded in JSON.
536
+ Event ,
537
+ /// Transaction event payload encoded in JSON.
538
+ Transaction ,
539
+ /// Security report event payload encoded in JSON.
540
+ Security ,
541
+ /// Raw payload of an arbitrary attachment.
542
+ Attachment ,
543
+ /// Multipart form data collected into a stream of JSON tuples.
544
+ FormData ,
545
+ /// Security report as sent by the browser in JSON.
546
+ RawSecurity ,
547
+ /// NEL report as sent by the browser.
548
+ Nel ,
549
+ /// Raw compressed UE4 crash report.
550
+ UnrealReport ,
551
+ /// User feedback encoded as JSON.
552
+ UserReport ,
553
+ /// Session update data.
554
+ Session ,
555
+ /// Aggregated session data.
556
+ Sessions ,
557
+ /// Individual metrics in text encoding.
558
+ Statsd ,
559
+ /// Buckets of preaggregated metrics encoded as JSON.
560
+ MetricBuckets ,
561
+ /// Client internal report (eg: outcomes).
562
+ ClientReport ,
563
+ /// Profile event payload encoded as JSON.
564
+ Profile ,
565
+ /// Replay metadata and breadcrumb payload.
566
+ ReplayEvent ,
567
+ /// Replay Recording data.
568
+ ReplayRecording ,
569
+ /// Replay Video data.
570
+ ReplayVideo ,
571
+ /// Monitor check-in encoded as JSON.
572
+ CheckIn ,
573
+ /// A log from the [OTEL Log format](https://opentelemetry.io/docs/specs/otel/logs/data-model/#log-and-event-record-definition)
574
+ OtelLog ,
575
+ /// A log for the log product, not internal logs.
576
+ Log ,
577
+ /// A standalone span.
578
+ Span ,
579
+ /// A standalone OpenTelemetry span serialized as JSON.
580
+ OtelSpan ,
581
+ /// An OTLP TracesData container.
582
+ OtelTracesData ,
583
+ /// UserReport as an Event
584
+ UserReportV2 ,
585
+ /// ProfileChunk is a chunk of a profiling session.
586
+ ProfileChunk ,
587
+ /// A new item type that is yet unknown by this version of Relay.
588
+ ///
589
+ /// By default, items of this type are forwarded without modification. Processing Relays and
590
+ /// Relays explicitly configured to do so will instead drop those items. This allows
591
+ /// forward-compatibility with new item types where we expect outdated Relays.
592
+ Unknown ,
593
+ // Keep `Unknown` last in the list. Add new items above `Unknown`.
594
+ }
595
+
596
+ impl DiscardItemType {
597
+ /// Returns the enum variant as string representation in snake case.
598
+ ///
599
+ /// For example, `DiscardItemType::UserReportV2` gets converted into `user_report_v2`.
600
+ pub fn as_str ( & self ) -> & ' static str {
601
+ match self {
602
+ Self :: Unknown => "unknown" ,
603
+ Self :: Event => "event" ,
604
+ Self :: Transaction => "transaction" ,
605
+ Self :: Security => "security" ,
606
+ Self :: Attachment => "attachment" ,
607
+ Self :: FormData => "form_data" ,
608
+ Self :: RawSecurity => "raw_security" ,
609
+ Self :: Nel => "nel" ,
610
+ Self :: UnrealReport => "unreal_report" ,
611
+ Self :: UserReport => "user_report" ,
612
+ Self :: Session => "session" ,
613
+ Self :: Sessions => "sessions" ,
614
+ Self :: Statsd => "statsd" ,
615
+ Self :: MetricBuckets => "metric_buckets" ,
616
+ Self :: ClientReport => "client_report" ,
617
+ Self :: Profile => "profile" ,
618
+ Self :: ReplayEvent => "replay_event" ,
619
+ Self :: ReplayRecording => "replay_recording" ,
620
+ Self :: ReplayVideo => "replay_video" ,
621
+ Self :: CheckIn => "check_in" ,
622
+ Self :: OtelLog => "otel_log" ,
623
+ Self :: Log => "log" ,
624
+ Self :: Span => "span" ,
625
+ Self :: OtelSpan => "otel_span" ,
626
+ Self :: OtelTracesData => "otel_traces_data" ,
627
+ Self :: UserReportV2 => "user_report_v2" ,
628
+ Self :: ProfileChunk => "profile_chunk" ,
629
+ }
630
+ }
631
+ }
632
+
633
+ impl From < & ItemType > for DiscardItemType {
634
+ fn from ( value : & ItemType ) -> Self {
635
+ match value {
636
+ ItemType :: Event => DiscardItemType :: Event ,
637
+ ItemType :: Transaction => DiscardItemType :: Transaction ,
638
+ ItemType :: Security => DiscardItemType :: Security ,
639
+ ItemType :: Attachment => DiscardItemType :: Attachment ,
640
+ ItemType :: FormData => DiscardItemType :: FormData ,
641
+ ItemType :: RawSecurity => DiscardItemType :: RawSecurity ,
642
+ ItemType :: Nel => DiscardItemType :: Nel ,
643
+ ItemType :: UnrealReport => DiscardItemType :: UnrealReport ,
644
+ ItemType :: UserReport => DiscardItemType :: UserReport ,
645
+ ItemType :: Session => DiscardItemType :: Session ,
646
+ ItemType :: Sessions => DiscardItemType :: Sessions ,
647
+ ItemType :: Statsd => DiscardItemType :: Statsd ,
648
+ ItemType :: MetricBuckets => DiscardItemType :: MetricBuckets ,
649
+ ItemType :: ClientReport => DiscardItemType :: ClientReport ,
650
+ ItemType :: Profile => DiscardItemType :: Profile ,
651
+ ItemType :: ReplayEvent => DiscardItemType :: ReplayEvent ,
652
+ ItemType :: ReplayRecording => DiscardItemType :: ReplayRecording ,
653
+ ItemType :: ReplayVideo => DiscardItemType :: ReplayVideo ,
654
+ ItemType :: CheckIn => DiscardItemType :: CheckIn ,
655
+ ItemType :: OtelLog => DiscardItemType :: OtelLog ,
656
+ ItemType :: Log => DiscardItemType :: Log ,
657
+ ItemType :: Span => DiscardItemType :: Span ,
658
+ ItemType :: OtelSpan => DiscardItemType :: OtelSpan ,
659
+ ItemType :: OtelTracesData => DiscardItemType :: OtelTracesData ,
660
+ ItemType :: UserReportV2 => DiscardItemType :: UserReportV2 ,
661
+ ItemType :: ProfileChunk => DiscardItemType :: ProfileChunk ,
662
+ ItemType :: Unknown ( _) => DiscardItemType :: Unknown ,
663
+ }
664
+ }
665
+ }
666
+
667
+ impl From < ItemType > for DiscardItemType {
668
+ fn from ( value : ItemType ) -> Self {
669
+ From :: from ( & value)
670
+ }
671
+ }
672
+
527
673
/// Raw representation of an outcome for serialization.
528
674
///
529
675
/// The JSON serialization of this structure is placed on the Kafka topic and used in the HTTP
@@ -754,7 +900,10 @@ impl ClientReportOutcomeProducer {
754
900
Outcome :: FilteredSampling ( _) => & mut client_report. filtered_sampling_events ,
755
901
Outcome :: RateLimited ( _) => & mut client_report. rate_limited_events ,
756
902
_ => {
757
- // Cannot convert this outcome to a client report.
903
+ relay_log:: debug!(
904
+ "Outcome '{}' cannot be converted to client report" ,
905
+ msg. outcome
906
+ ) ;
758
907
return ;
759
908
}
760
909
} ;
@@ -1076,4 +1225,20 @@ mod tests {
1076
1225
MatchedRuleIds ( [ 1000 , 1004 , 1400 , 1500 , 0 ] . map( RuleId ) . into( ) )
1077
1226
) ;
1078
1227
}
1228
+
1229
+ #[ test]
1230
+ fn test_outcome_discard_reason ( ) {
1231
+ assert_eq ! (
1232
+ Some ( Cow :: from( "too_large:attachment" ) ) ,
1233
+ Outcome :: Invalid ( DiscardReason :: TooLarge ( DiscardItemType :: Attachment ) ) . to_reason( )
1234
+ ) ;
1235
+ assert_eq ! (
1236
+ Some ( Cow :: from( "too_large:unknown" ) ) ,
1237
+ Outcome :: Invalid ( DiscardReason :: TooLarge ( DiscardItemType :: Unknown ) ) . to_reason( )
1238
+ ) ;
1239
+ assert_eq ! (
1240
+ Some ( Cow :: from( "too_large:unreal_report" ) ) ,
1241
+ Outcome :: Invalid ( DiscardReason :: TooLarge ( DiscardItemType :: UnrealReport ) ) . to_reason( )
1242
+ ) ;
1243
+ }
1079
1244
}
0 commit comments