Skip to content

feat(profiling): Support profiles tagged for many transactions#1444

Merged
phacops merged 11 commits intomasterfrom
pierre/profiling-multi-transactions
Sep 12, 2022
Merged

feat(profiling): Support profiles tagged for many transactions#1444
phacops merged 11 commits intomasterfrom
pierre/profiling-multi-transactions

Conversation

@phacops
Copy link
Copy Markdown
Contributor

@phacops phacops commented Aug 31, 2022

In order to support concurrent transactions for mobile platforms (cocoa, android), we want to start tagging profiles for many transactions. This would be a workaround before we move to a proper continuous profiling architecture, where we stream chunks of profiles.

In this workaround, a profile will be collected as long as 1 transaction is still running. All transaction metadata will be collected and sent over in a transactions array and relay will duplicate the profile data for each transaction, filter samples/events that are not for that transaction and sent it over to Kafka as a regular profile (attached to 1 transaction only) so the rest of the pipeline doesn't need to be changed.

This PR implements this workaround, looping around transaction metadata, duplicating the profile data, filtering and adding an item of type Profile to the envelope in order to be sent to Kafka afterwards. In case a profile comes with no transaction metadata it's rejected. If a profile comes in the old format, it's processed as usual.

Other platforms are not concerned by this workaround.

@phacops phacops requested a review from a team as a code owner August 31, 2022 19:25
@phacops phacops requested a review from a team August 31, 2022 19:25
}

impl TransactionMetadata {
pub fn valid(self) -> bool {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn valid(self) -> bool {
pub fn valid(&self) -> bool {

I don't think valid needs to take ownership of the instance here.

It's just reading and checking if it's valid.

This way you won't have to clone every time just to check if the TransactionMetadata is valid as currently done here

}

for transaction in &profile.transactions {
if !transaction.clone().valid() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to my previous comment.

If you change the valid method to take a reference to the instance here we don't need to clone each transactions just to check their validity.

}

for transaction in profile.transactions.iter() {
if !transaction.clone().valid() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here too, changing the valid method to accept a reference to the instance here we don't need to clone each transactions to check their validity.

@phacops phacops requested a review from viglia September 6, 2022 16:16
Copy link
Copy Markdown
Contributor

@iker-barriocanal iker-barriocanal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some code for the android and cocoa profiles seem very similar, at some point we may want to do something about that.

!self.id.is_nil()
&& !self.trace_id.is_nil()
&& !self.name.is_empty()
&& self.relative_start_ns < self.relative_end_ns
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also require relative cpu start time to be smaller than end time, when they exist (for android)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To keep it simple, I'll check relative_cpu_start_ms <= relative_cpu_end_ms as I don't have the platform available in that struct to make the check Android only.

}

fn set_transaction(&mut self, transaction: &TransactionMetadata) {
self.transaction_name = transaction.name.clone();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why clone the string?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that's the only I thought I could copy the value. Copy trait can't be implemented for the TransactionMetadata type and since I'm passing a shared reference, that's kind of the only way the compiler would let me off the hook. Do you have another suggestion?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, sounds good to me. I was just curious.

}

fn substract_to_timestamp(time: Time, duration: Duration) -> Time {
match time {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dang how many different times hahah

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For real, this time struct for Android is driving me crazy.

match serde_json::to_vec(&profile) {
Ok(payload) => Ok(payload),
Err(_) => Err(ProfileError::CannotSerializePayload),
Ok(items)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point, outside the for loop, all new profiles have empty transactions. Should we also clear the transactions for the current profile?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current profile is discarded so I don't think it matters.

@phacops phacops requested review from a team and iker-barriocanal September 8, 2022 23:48
@phacops
Copy link
Copy Markdown
Contributor Author

phacops commented Sep 8, 2022

Indeed, they are very similar. I think that's fine for now, we're already planning to rewrite profiling to properly decouple profiles from transactions and this code will end up deprecated.

Copy link
Copy Markdown
Contributor

@iker-barriocanal iker-barriocanal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

}

fn set_transaction(&mut self, transaction: &TransactionMetadata) {
self.transaction_name = transaction.name.clone();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, sounds good to me. I was just curious.

@phacops phacops merged commit 241bf0e into master Sep 12, 2022
@phacops phacops deleted the pierre/profiling-multi-transactions branch September 12, 2022 12:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants