-
Notifications
You must be signed in to change notification settings - Fork 94
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(outcomes): Emit outcomes as client reports [INGEST-247] #1119
Conversation
…ient-reports-original
Outcome::RateLimited(_) => &mut client_report._server_rate_limited_events, | ||
_ => { | ||
// Cannot convert this outcome to a client report. | ||
return Ok(()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that only these three outcome types will be emitted. Everything else is silently dropped.
|
||
// TODO: timestamp validation? (min, max) | ||
let offset = timestamp.timestamp() as u64 / self.bucket_interval; | ||
let offset = msg.timestamp.timestamp() as u64 / self.bucket_interval; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume that we do not need to validate the timestamp here, because
- outcomes coming in via client reports have their own validation,
- all other outcomes are created by trusted relays.
@@ -121,6 +121,7 @@ pub struct LimitedProjectConfig { | |||
pub trusted_relays: Vec<PublicKey>, | |||
pub pii_config: Option<PiiConfig>, | |||
pub datascrubbing_settings: DataScrubbingConfig, | |||
pub dynamic_sampling: Option<SamplingConfig>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change enables dynamic sampling in external relays.
relay-server/src/actors/envelopes.rs
Outdated
type Result = Result<(), ()>; | ||
} | ||
|
||
impl Handler<SendClientReport> for EnvelopeManager { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since SendEnvelope is pub now, can't this live in the outcome actor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried that (that's why SendEnvelope
is public) but bumped into an issue I cannot remember. Is it OK if we keep it here to keep SendClientReport
consistent with SendMetrics
, and refactor both at a later time?
pub struct NonProcessingOutcomeProducer { | ||
producer: Option<Recipient<TrackOutcome>>, | ||
raw_producer: Option<Recipient<TrackRawOutcome>>, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be possible to replace this with
pub enum NonProcessingOutcomeProducer {
AsClientReports(Addr<ClientReportOutcomeProducer>),
AsOutcomes(Addr<HttpOutcomeProducer>),
Disabled,
}
and remove impl Handler<TrackOutcome> for HttpProducer>
alternatively we could fold all three actors into one
…ient-reports-original
relay-server/src/actors/envelopes.rs
Outdated
type Result = Result<(), ()>; | ||
} | ||
|
||
impl Handler<SendClientReport> for EnvelopeManager { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried that (that's why SendEnvelope
is public) but bumped into an issue I cannot remember. Is it OK if we keep it here to keep SendClientReport
consistent with SendMetrics
, and refactor both at a later time?
type Context = Context<Self>; | ||
|
||
fn started(&mut self, ctx: &mut Self::Context) { | ||
ctx.run_interval(self.flush_interval, Self::flush); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@untitaker In the end I decided to use run_interval
here. The outcomes for ClientReportOutcomeProducer
always come from the aggregator in predictable intervals, so I suppose there is no need for "flush when batch is full or too much time has passed" logic. Instead, just flush with the same interval as the aggregator.
relay-config/src/config.rs
Outdated
@@ -1008,7 +1090,7 @@ pub struct Outcomes { | |||
impl Default for Outcomes { | |||
fn default() -> Self { | |||
Outcomes { | |||
emit_outcomes: false, | |||
emit_outcomes: EmitOutcomes::None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we set the default to EmitOutcomes::AsClientReports
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think so, in that case we should write some warnings into the changelog imo
relay-config/src/config.rs
Outdated
@@ -1008,7 +1090,7 @@ pub struct Outcomes { | |||
impl Default for Outcomes { | |||
fn default() -> Self { | |||
Outcomes { | |||
emit_outcomes: false, | |||
emit_outcomes: EmitOutcomes::None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think so, in that case we should write some warnings into the changelog imo
if self.processing_enabled() { | ||
return EmitOutcomes::AsOutcomes; | ||
} | ||
self.values.outcomes.emit_outcomes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jjbayer this makes me think, maybe we should make the field in the config Option<EmitOutcomes>
so explicitly setting the value to anything takes precedence over this. but not entirely sure. can leave it out for now
@@ -162,6 +162,26 @@ impl fmt::Display for FilterStatKey { | |||
} | |||
} | |||
|
|||
impl<'a> TryFrom<&'a str> for FilterStatKey { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we have a macro for this? maybe just for serde impl
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should flip the default before we merge this, because people are not going to enable this explicitly. All other comments are optional.
…ient-reports-original
* master: test(outcomes): Fix sort order in flaky test (#1135) feat(outcomes): Aggregate more outcomes (#1134) ref(outcomes): Fold processing vs non-processing into single actor (#1133) build: Update symbolic to support UE5 (#1132) feat(metrics): Extract measurement ratings, port from frontend (#1130) feat(metrics): Another statsd metric to measure bucket duplication (#1128) feat(outcomes): Emit outcomes as client reports (#1119) fix: Move changelog line to right version (#1129) fix(dangerjs): Do not suggest to add JIRA ticket to changelog (#1125) feat(metrics): Tag metrics by transaction name [INGEST-542] (#1126)
Add the option to emit outcomes as client reports. This allows external relays to emit outcomes.
Main feature of this PR:
emit_outcomes
config flag can now have three states: true, false, or "client reports".TrackOutcome
is now sent to the outcome aggregator instead of the outcome producer.event_id
andremote_addr
from the outcome.event_id
after step 3, it is forwarded to the configured producer without aggregating.Also in this PR: