@@ -619,3 +619,104 @@ func TestQuerierWithChunksStorage(t *testing.T) {
619619	assertServiceMetricsPrefixes (t , Querier , querier )
620620	assertServiceMetricsPrefixes (t , TableManager , tableManager )
621621}
622+ 
623+ func  TestHashCollisionHandling (t  * testing.T ) {
624+ 	s , err  :=  e2e .NewScenario (networkName )
625+ 	require .NoError (t , err )
626+ 	defer  s .Close ()
627+ 
628+ 	require .NoError (t , writeFileToSharedDir (s , cortexSchemaConfigFile , []byte (cortexSchemaConfigYaml )))
629+ 	flags  :=  mergeFlags (ChunksStorageFlags , map [string ]string {})
630+ 
631+ 	// Start dependencies. 
632+ 	dynamo  :=  e2edb .NewDynamoDB ()
633+ 
634+ 	consul  :=  e2edb .NewConsul ()
635+ 	require .NoError (t , s .StartAndWaitReady (consul , dynamo ))
636+ 
637+ 	tableManager  :=  e2ecortex .NewTableManager ("table-manager" , ChunksStorageFlags , "" )
638+ 	require .NoError (t , s .StartAndWaitReady (tableManager ))
639+ 
640+ 	// Wait until the first table-manager sync has completed, so that we're 
641+ 	// sure the tables have been created. 
642+ 	require .NoError (t , tableManager .WaitSumMetrics (e2e .Greater (0 ), "cortex_table_manager_sync_success_timestamp_seconds" ))
643+ 
644+ 	// Start Cortex components for the write path. 
645+ 	distributor  :=  e2ecortex .NewDistributor ("distributor" , consul .NetworkHTTPEndpoint (), flags , "" )
646+ 	ingester  :=  e2ecortex .NewIngester ("ingester" , consul .NetworkHTTPEndpoint (), flags , "" )
647+ 	require .NoError (t , s .StartAndWaitReady (distributor , ingester ))
648+ 
649+ 	// Wait until the distributor has updated the ring. 
650+ 	require .NoError (t , distributor .WaitSumMetrics (e2e .Equals (512 ), "cortex_ring_tokens_total" ))
651+ 
652+ 	// Push a series for each user to Cortex. 
653+ 	now  :=  time .Now ()
654+ 
655+ 	c , err  :=  e2ecortex .NewClient (distributor .HTTPEndpoint (), "" , "" , "" , "user-0" )
656+ 	require .NoError (t , err )
657+ 
658+ 	var  series  []prompb.TimeSeries 
659+ 	var  expectedVector  model.Vector 
660+ 	// Generate two series which collide on fingerprints and fast fingerprints. 
661+ 	tsMillis  :=  e2e .TimeToMilliseconds (now )
662+ 	metric1  :=  []prompb.Label {
663+ 		{Name : "A" , Value : "K6sjsNNczPl" },
664+ 		{Name : labels .MetricName , Value : "fingerprint_collision" },
665+ 	}
666+ 	metric2  :=  []prompb.Label {
667+ 		{Name : "A" , Value : "cswpLMIZpwt" },
668+ 		{Name : labels .MetricName , Value : "fingerprint_collision" },
669+ 	}
670+ 
671+ 	series  =  append (series , prompb.TimeSeries {
672+ 		Labels : metric1 ,
673+ 		Samples : []prompb.Sample {
674+ 			{Value : float64 (0 ), Timestamp : tsMillis },
675+ 		},
676+ 	})
677+ 	expectedVector  =  append (expectedVector , & model.Sample {
678+ 		Metric :    prompbLabelsToModelMetric (metric1 ),
679+ 		Value :     model .SampleValue (float64 (0 )),
680+ 		Timestamp : model .Time (tsMillis ),
681+ 	})
682+ 	series  =  append (series , prompb.TimeSeries {
683+ 		Labels : metric2 ,
684+ 		Samples : []prompb.Sample {
685+ 			{Value : float64 (1 ), Timestamp : tsMillis },
686+ 		},
687+ 	})
688+ 	expectedVector  =  append (expectedVector , & model.Sample {
689+ 		Metric :    prompbLabelsToModelMetric (metric2 ),
690+ 		Value :     model .SampleValue (float64 (1 )),
691+ 		Timestamp : model .Time (tsMillis ),
692+ 	})
693+ 
694+ 	res , err  :=  c .Push (series )
695+ 	require .NoError (t , err )
696+ 	require .Equal (t , 200 , res .StatusCode )
697+ 
698+ 	querier  :=  e2ecortex .NewQuerier ("querier" , consul .NetworkHTTPEndpoint (), flags , "" )
699+ 	require .NoError (t , s .StartAndWaitReady (querier ))
700+ 
701+ 	// Wait until the querier has updated the ring. 
702+ 	require .NoError (t , querier .WaitSumMetrics (e2e .Equals (512 ), "cortex_ring_tokens_total" ))
703+ 
704+ 	// Query the series. 
705+ 	c , err  =  e2ecortex .NewClient ("" , querier .HTTPEndpoint (), "" , "" , "user-0" )
706+ 	require .NoError (t , err )
707+ 
708+ 	result , err  :=  c .Query ("fingerprint_collision" , now )
709+ 	require .NoError (t , err )
710+ 	require .Equal (t , model .ValVector , result .Type ())
711+ 	require .Equal (t , expectedVector , result .(model.Vector ))
712+ }
713+ 
714+ func  prompbLabelsToModelMetric (pbLabels  []prompb.Label ) model.Metric  {
715+ 	metric  :=  model.Metric {}
716+ 
717+ 	for  _ , l  :=  range  pbLabels  {
718+ 		metric [model .LabelName (l .Name )] =  model .LabelValue (l .Value )
719+ 	}
720+ 
721+ 	return  metric 
722+ }
0 commit comments