Skip to content

fix(relay): Correctly serialize UUID without hypens#4673

Merged
iambriccardo merged 33 commits intomasterfrom
riccardo/fix/wrong-uuid
Apr 16, 2025
Merged

fix(relay): Correctly serialize UUID without hypens#4673
iambriccardo merged 33 commits intomasterfrom
riccardo/fix/wrong-uuid

Conversation

@iambriccardo
Copy link
Contributor

@iambriccardo iambriccardo commented Apr 14, 2025

This PR fixes a problem where the trace_id was serialized differently in the _dsc and other parts of the event payload. The issue stemmed from the fact that Uuid is, by default, serialized with hyphens.

The solution is to use the TraceId type across the DSC and other parts of the code (relay-monitors) to ensure consistent implementation. The new TraceId is also using a Uuid inside even though the format is a subset of a uuid v4.

fn pseudo_random_from_uuid(id: Uuid) -> f64 {
let big_seed = id.as_u128();
let mut generator = Pcg32::new((big_seed >> 64) as u64, big_seed as u64);
fn pseudo_random_from_seed(seed: u128) -> f64 {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Decided to just remove our dependence from the Uuid and simply use u128.

Copy link
Member

Choose a reason for hiding this comment

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

This can stay as uuid now, since the trace id just wraps one now? That should make sure we don't accidentally mess up the seed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I was thinking of keeping it since it makes the whole thing depend on a much simpler piece of code, but if you feel like reducing the surface for possible errors, I can revert.

/// - The trace ID string is not exactly 32 characters
///
/// Otherwise, it returns the trace ID as an u128 integer.
pub fn as_u128(&self) -> u128 {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This conversion assumes that for each byte we can take out a hex value from 0-15. This is not super efficient because we could technically represent the same data with 16 bytes instead of 32, but for the sake of simplicity (given the Empty, IntoValue and ProcessValue), we will keep the type as a String. We might want to make this more efficient in the future.

Copy link
Member

Choose a reason for hiding this comment

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

As discussed, probably worth switching all of this now to [u8; 16] like EventId

let jsons = [
r#"{
"trace_id": "00000000-0000-0000-0000-000000000000",
"trace_id": "67e5504410b1426f9247bb680e5fe0c8",
Copy link
Member

Choose a reason for hiding this comment

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

Haven't taken a full look, so maybe it's there already, it would be good if we keep at least one test with the old format.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A trace id is not valid if it's made up of only zeros: https://www.w3.org/TR/trace-context/#trace-id.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will keep some tests with the -.

#[serde(default, serialize_with = "uuid_simple")]
pub check_in_id: Uuid,
#[serde(default)]
pub check_in_id: TraceId,
Copy link
Member

Choose a reason for hiding this comment

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

I don't know if we can change that, check ins may actually use a uuid here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Isn't out format compatible with a UUID? But yeah, I should use a different type name, it was my bad for keeping TraceId.

I am also fine to keep Uuid.

Copy link
Member

Choose a reason for hiding this comment

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

Oh it was not even serialized with hyphens before, right? Then it's safe to switch, nice. Maybe just make it a type alias to CheckInId, that should be fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, this is why it had the simple serializer. Because the simple variant has no -.

/// - The trace ID string is not exactly 32 characters
///
/// Otherwise, it returns the trace ID as an u128 integer.
pub fn as_u128(&self) -> u128 {
Copy link
Member

Choose a reason for hiding this comment

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

As discussed, probably worth switching all of this now to [u8; 16] like EventId

fn test_untrimmable_fields() {
let original_description = "a".repeat(819163);
let original_trace_id = TraceId("b".repeat(48));
let original_trace_id = TraceId::parse_str(&"b".repeat(32)).unwrap();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have to make this valid, otherwise it will not compile.

)),
timestamp: Timestamp(end_timestamp).into(),
trace_id: TraceId(trace_id).into(),
trace_id: TraceId::parse_str_annotated(&trace_id),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I decided to implement annotated in case of errors instead of using Result, so that we can have in the payload the errors.

My only worry is what will happen upstream in case no trace_id is set.

@iambriccardo iambriccardo marked this pull request as ready for review April 16, 2025 07:29
@iambriccardo iambriccardo requested a review from a team as a code owner April 16, 2025 07:29
contexts.add(TraceContext {
trace_id: Annotated::new(TraceId("4c79f60c11214eb38604f4ae0781bfb2".into())),
trace_id: Annotated::new(
TraceId::parse_str("3c79f60c11214eb38604f4ae0781bfb2").unwrap(),
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
TraceId::parse_str("3c79f60c11214eb38604f4ae0781bfb2").unwrap(),
"3c79f60c11214eb38604f4ae0781bfb2".parse().unwrap(),

Since it implements FromStr

Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a particular reason to change the ID itself here?

match value {
Annotated(Some(Value::String(mut value)), mut meta) => {
if !is_hex_string(&value, 32) || value.bytes().all(|x| x == b'0') {
Annotated(Some(Value::String(value)), mut meta) => match FromStr::from_str(&value) {
Copy link
Member

Choose a reason for hiding this comment

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

Usually you'd just value.parse() here, instead of going through the trait

fn pseudo_random_from_uuid(id: Uuid) -> f64 {
let big_seed = id.as_u128();
let mut generator = Pcg32::new((big_seed >> 64) as u64, big_seed as u64);
fn pseudo_random_from_seed(seed: u128) -> f64 {
Copy link
Member

Choose a reason for hiding this comment

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

This can stay as uuid now, since the trace id just wraps one now? That should make sure we don't accidentally mess up the seed

contexts.add(TraceContext {
trace_id: Annotated::new(TraceId("4c79f60c11214eb38604f4ae0781bfb2".into())),
trace_id: Annotated::new(
TraceId::parse_str("3c79f60c11214eb38604f4ae0781bfb2").unwrap(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a particular reason to change the ID itself here?

),
trace_id: TraceId(
"ff62a8b040f340bda5d830223def1d81",
ff62a8b0-40f3-40bd-a5d8-30223def1d81,
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are -s being introduced in these snapshots?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is because we are now using a Uuid whose debug/display impl renders with -. This is the drawback of using the Uuid type instead of a custom type that does the validation.

Copy link
Member

Choose a reason for hiding this comment

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

We could overwrite the debug impl, I think I like that, then the snapshots would be matching.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, I will do this! Good idea, so that it keeps being consistent, should we also use the ""? Might be unnecessary but idk

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, duh, I missed that this is Debug, not serialization. Still, I would also agree with overriding the Debug impl.

Copy link
Member

Choose a reason for hiding this comment

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

TraceId(abcd...) should be fine, don't really see a need for the " but nbd either way

@iambriccardo
Copy link
Contributor Author

@loewenheim that was my bad, it was messed up during a codebase wide rename.

@iambriccardo iambriccardo enabled auto-merge (squash) April 16, 2025 11:06
@iambriccardo iambriccardo merged commit bb5c0c9 into master Apr 16, 2025
31 checks passed
@iambriccardo iambriccardo deleted the riccardo/fix/wrong-uuid branch April 16, 2025 11:09
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