@@ -427,22 +427,33 @@ pub struct InstrumentationScope {
427427 attributes : Vec < KeyValue > ,
428428}
429429
430- // Uniqueness for InstrumentationScope does not depend on attributes
431- impl Eq for InstrumentationScope { }
432-
433430impl PartialEq for InstrumentationScope {
434431 fn eq ( & self , other : & Self ) -> bool {
435432 self . name == other. name
436433 && self . version == other. version
437434 && self . schema_url == other. schema_url
435+ && {
436+ let mut self_attrs = self . attributes . clone ( ) ;
437+ let mut other_attrs = other. attributes . clone ( ) ;
438+ self_attrs. sort_unstable_by ( |a, b| a. key . cmp ( & b. key ) ) ;
439+ other_attrs. sort_unstable_by ( |a, b| a. key . cmp ( & b. key ) ) ;
440+ self_attrs == other_attrs
441+ }
438442 }
439443}
440444
445+ impl Eq for InstrumentationScope { }
446+
441447impl hash:: Hash for InstrumentationScope {
442448 fn hash < H : hash:: Hasher > ( & self , state : & mut H ) {
443449 self . name . hash ( state) ;
444450 self . version . hash ( state) ;
445451 self . schema_url . hash ( state) ;
452+ let mut sorted_attrs = self . attributes . clone ( ) ;
453+ sorted_attrs. sort_unstable_by ( |a, b| a. key . cmp ( & b. key ) ) ;
454+ for attribute in sorted_attrs {
455+ attribute. hash ( state) ;
456+ }
446457 }
447458}
448459
@@ -561,3 +572,69 @@ impl InstrumentationScopeBuilder {
561572 }
562573 }
563574}
575+
576+ #[ cfg( test) ]
577+ mod tests {
578+ use std:: hash:: { Hash , Hasher } ;
579+
580+ use crate :: { InstrumentationScope , KeyValue } ;
581+
582+ #[ test]
583+ fn instrumentation_scope_equality ( ) {
584+ let scope1 = InstrumentationScope :: builder ( "my-crate" )
585+ . with_version ( "v0.1.0" )
586+ . with_schema_url ( "https://opentelemetry.io/schemas/1.17.0" )
587+ . with_attributes ( [ KeyValue :: new ( "k" , "v" ) ] )
588+ . build ( ) ;
589+ let scope2 = InstrumentationScope :: builder ( "my-crate" )
590+ . with_version ( "v0.1.0" )
591+ . with_schema_url ( "https://opentelemetry.io/schemas/1.17.0" )
592+ . with_attributes ( [ KeyValue :: new ( "k" , "v" ) ] )
593+ . build ( ) ;
594+ assert_eq ! ( scope1, scope2) ;
595+ }
596+
597+ #[ test]
598+ fn instrumentation_scope_equality_attributes_diff_order ( ) {
599+ let scope1 = InstrumentationScope :: builder ( "my-crate" )
600+ . with_version ( "v0.1.0" )
601+ . with_schema_url ( "https://opentelemetry.io/schemas/1.17.0" )
602+ . with_attributes ( [ KeyValue :: new ( "k1" , "v1" ) , KeyValue :: new ( "k2" , "v2" ) ] )
603+ . build ( ) ;
604+ let scope2 = InstrumentationScope :: builder ( "my-crate" )
605+ . with_version ( "v0.1.0" )
606+ . with_schema_url ( "https://opentelemetry.io/schemas/1.17.0" )
607+ . with_attributes ( [ KeyValue :: new ( "k2" , "v2" ) , KeyValue :: new ( "k1" , "v1" ) ] )
608+ . build ( ) ;
609+ assert_eq ! ( scope1, scope2) ;
610+
611+ // assert hash are same for both scopes
612+ let mut hasher1 = std:: collections:: hash_map:: DefaultHasher :: new ( ) ;
613+ scope1. hash ( & mut hasher1) ;
614+ let mut hasher2 = std:: collections:: hash_map:: DefaultHasher :: new ( ) ;
615+ scope2. hash ( & mut hasher2) ;
616+ assert_eq ! ( hasher1. finish( ) , hasher2. finish( ) ) ;
617+ }
618+
619+ #[ test]
620+ fn instrumentation_scope_equality_different_attributes ( ) {
621+ let scope1 = InstrumentationScope :: builder ( "my-crate" )
622+ . with_version ( "v0.1.0" )
623+ . with_schema_url ( "https://opentelemetry.io/schemas/1.17.0" )
624+ . with_attributes ( [ KeyValue :: new ( "k1" , "v1" ) , KeyValue :: new ( "k2" , "v2" ) ] )
625+ . build ( ) ;
626+ let scope2 = InstrumentationScope :: builder ( "my-crate" )
627+ . with_version ( "v0.1.0" )
628+ . with_schema_url ( "https://opentelemetry.io/schemas/1.17.0" )
629+ . with_attributes ( [ KeyValue :: new ( "k2" , "v3" ) , KeyValue :: new ( "k4" , "v5" ) ] )
630+ . build ( ) ;
631+ assert_ne ! ( scope1, scope2) ;
632+
633+ // assert hash are same for both scopes
634+ let mut hasher1 = std:: collections:: hash_map:: DefaultHasher :: new ( ) ;
635+ scope1. hash ( & mut hasher1) ;
636+ let mut hasher2 = std:: collections:: hash_map:: DefaultHasher :: new ( ) ;
637+ scope2. hash ( & mut hasher2) ;
638+ assert_ne ! ( hasher1. finish( ) , hasher2. finish( ) ) ;
639+ }
640+ }
0 commit comments