@@ -408,3 +408,189 @@ func benchSingleEndpoint(b *testing.B, tc testCase, alterConfig func(arguments *
408408 }, time .Minute , time .Second , "haven't seen expected number of lines" )
409409 }
410410}
411+
412+ func TestNewEntryHandler (t * testing.T ) {
413+ testCases := []struct {
414+ name string
415+ externalLabels model.LabelSet
416+ entryLabels model.LabelSet
417+ expectedLabels model.LabelSet
418+ }{
419+ {
420+ name : "filter meta labels without external labels" ,
421+ externalLabels : nil ,
422+ entryLabels : model.LabelSet {
423+ "normal_label" : "value1" ,
424+ "__meta_label" : "value2" ,
425+ "__another_meta" : "value3" ,
426+ "regular_label" : "value4" ,
427+ },
428+ expectedLabels : model.LabelSet {
429+ "normal_label" : "value1" ,
430+ "regular_label" : "value4" ,
431+ },
432+ },
433+ {
434+ name : "filter meta labels from both external and entry labels" ,
435+ externalLabels : model.LabelSet {
436+ "__external_meta" : "external_value" , // should be filtered
437+ "external_label" : "external_normal" ,
438+ },
439+ entryLabels : model.LabelSet {
440+ "normal_label" : "value1" ,
441+ "__meta_label" : "value2" , // should be filtered
442+ "regular_label" : "value4" ,
443+ },
444+ expectedLabels : model.LabelSet {
445+ "external_label" : "external_normal" , // external normal label preserved
446+ "normal_label" : "value1" , // entry normal label preserved
447+ "regular_label" : "value4" , // entry normal label preserved
448+ },
449+ },
450+ {
451+ name : "entry labels override external labels" ,
452+ externalLabels : model.LabelSet {
453+ "common_label" : "external_value" ,
454+ },
455+ entryLabels : model.LabelSet {
456+ "common_label" : "entry_value" , // should override external
457+ "entry_only" : "value1" ,
458+ },
459+ expectedLabels : model.LabelSet {
460+ "common_label" : "entry_value" , // entry takes precedence
461+ "entry_only" : "value1" ,
462+ },
463+ },
464+ {
465+ name : "empty labels" ,
466+ externalLabels : nil ,
467+ entryLabels : model.LabelSet {},
468+ expectedLabels : model.LabelSet {},
469+ },
470+ {
471+ name : "only meta labels" ,
472+ externalLabels : nil ,
473+ entryLabels : model.LabelSet {
474+ "__meta_only" : "value1" ,
475+ "__another_meta" : "value2" ,
476+ },
477+ expectedLabels : model.LabelSet {},
478+ },
479+ {
480+ name : "external meta labels with no entry labels" ,
481+ externalLabels : model.LabelSet {
482+ "__external_meta" : "external_value" , // should now be filtered
483+ "external_normal" : "normal_value" ,
484+ },
485+ entryLabels : model.LabelSet {},
486+ expectedLabels : model.LabelSet {
487+ "external_normal" : "normal_value" , // only normal external label preserved
488+ },
489+ },
490+ {
491+ name : "mixed scenario with overrides and filtering" ,
492+ externalLabels : model.LabelSet {
493+ "__external_meta" : "external_value" , // should now be filtered
494+ "shared_label" : "external_shared" ,
495+ },
496+ entryLabels : model.LabelSet {
497+ "normal_label" : "normal_value" ,
498+ "__meta_label" : "meta_value" , // should be filtered
499+ "shared_label" : "entry_shared" , // should override external
500+ "another_normal" : "another_value" ,
501+ },
502+ expectedLabels : model.LabelSet {
503+ "shared_label" : "entry_shared" , // entry takes precedence (original behavior)
504+ "normal_label" : "normal_value" , // entry normal preserved
505+ "another_normal" : "another_value" , // entry normal preserved
506+ },
507+ },
508+ {
509+ name : "labels starting with single underscore should be preserved" ,
510+ externalLabels : nil ,
511+ entryLabels : model.LabelSet {
512+ "_single_underscore" : "value1" ,
513+ "__double_underscore" : "value2" , // should be filtered
514+ "normal_label" : "value3" ,
515+ },
516+ expectedLabels : model.LabelSet {
517+ "_single_underscore" : "value1" ,
518+ "normal_label" : "value3" ,
519+ },
520+ },
521+ {
522+ name : "external labels with empty values" ,
523+ externalLabels : model.LabelSet {
524+ "empty_external" : "" ,
525+ "normal_external" : "external_value" ,
526+ },
527+ entryLabels : model.LabelSet {
528+ "entry_label" : "entry_value" ,
529+ },
530+ expectedLabels : model.LabelSet {
531+ "empty_external" : "" ,
532+ "normal_external" : "external_value" ,
533+ "entry_label" : "entry_value" ,
534+ },
535+ },
536+ {
537+ name : "only external labels" ,
538+ externalLabels : model.LabelSet {
539+ "external_only" : "external_value" ,
540+ "__external_meta" : "meta_value" , // should now be filtered
541+ },
542+ entryLabels : nil ,
543+ expectedLabels : model.LabelSet {
544+ "external_only" : "external_value" , // only normal external label preserved
545+ },
546+ },
547+ {
548+ name : "all meta labels filtered regardless of source" ,
549+ externalLabels : model.LabelSet {
550+ "__external_meta1" : "external_value1" , // should be filtered
551+ "__external_meta2" : "external_value2" , // should be filtered
552+ "external_normal" : "external_normal_value" ,
553+ },
554+ entryLabels : model.LabelSet {
555+ "__entry_meta1" : "entry_value1" , // should be filtered
556+ "__entry_meta2" : "entry_value2" , // should be filtered
557+ "entry_normal" : "entry_normal_value" ,
558+ },
559+ expectedLabels : model.LabelSet {
560+ "external_normal" : "external_normal_value" ,
561+ "entry_normal" : "entry_normal_value" ,
562+ },
563+ },
564+ }
565+
566+ for _ , tc := range testCases {
567+ t .Run (tc .name , func (t * testing.T ) {
568+ // Create a channel to capture the entry
569+ captureChannel := make (chan loki.Entry , 1 )
570+ mockHandler := loki .NewEntryHandler (captureChannel , func () {})
571+
572+ handler := newEntryHandler (mockHandler , tc .externalLabels )
573+
574+ testEntry := loki.Entry {
575+ Labels : tc .entryLabels ,
576+ Entry : push.Entry {
577+ Timestamp : time .Now (),
578+ Line : "test log line" ,
579+ },
580+ }
581+
582+ go func () {
583+ handler .Chan () <- testEntry
584+ }()
585+
586+ select {
587+ case capturedEntry := <- captureChannel :
588+ require .Equal (t , tc .expectedLabels , capturedEntry .Labels )
589+ case <- time .After (time .Second ):
590+ t .Fatalf ("timeout waiting for entry in test case: %s" , tc .name )
591+ }
592+
593+ handler .Stop ()
594+ })
595+ }
596+ }
0 commit comments