@@ -23,13 +23,16 @@ use super::noop::NoopSyncInstrument;
2323const INSTRUMENT_NAME_MAX_LENGTH : usize = 255 ;
2424// maximum length of instrument unit name
2525const INSTRUMENT_UNIT_NAME_MAX_LENGTH : usize = 63 ;
26+ #[ cfg( not( feature = "experimental_metrics_disable_name_validation" ) ) ]
2627const INSTRUMENT_NAME_ALLOWED_NON_ALPHANUMERIC_CHARS : [ char ; 4 ] = [ '_' , '.' , '-' , '/' ] ;
2728
2829// instrument validation error strings
2930const INSTRUMENT_NAME_EMPTY : & str = "instrument name must be non-empty" ;
3031const INSTRUMENT_NAME_LENGTH : & str = "instrument name must be less than 256 characters" ;
32+ #[ cfg( not( feature = "experimental_metrics_disable_name_validation" ) ) ]
3133const INSTRUMENT_NAME_INVALID_CHAR : & str =
3234 "characters in instrument name must be ASCII and belong to the alphanumeric characters, '_', '.', '-' and '/'" ;
35+ #[ cfg( not( feature = "experimental_metrics_disable_name_validation" ) ) ]
3336const INSTRUMENT_NAME_FIRST_ALPHABETIC : & str =
3437 "instrument name must start with an alphabetic character" ;
3538const INSTRUMENT_UNIT_LENGTH : & str = "instrument unit must be less than 64 characters" ;
@@ -572,6 +575,33 @@ fn validate_bucket_boundaries(boundaries: &[f64]) -> MetricResult<()> {
572575 Ok ( ( ) )
573576}
574577
578+ // Regex pattern for Windows Performance Counter names
579+ // #[cfg(feature = "experimental_metrics_disable_name_validation")]
580+ // fn is_valid_windows_perf_counter_name(name: &str) -> bool {
581+ // let pattern = r"^\\[A-Za-z0-9_ ]+\\[A-Za-z0-9_ /%-]+$";
582+ // let re = Regex::new(pattern).unwrap();
583+ // re.is_match(name)
584+ // }
585+
586+ #[ cfg( feature = "experimental_metrics_disable_name_validation" ) ]
587+ fn validate_instrument_name ( name : & str ) -> MetricResult < ( ) > {
588+ if name. is_empty ( ) {
589+ return Err ( MetricError :: InvalidInstrumentConfiguration (
590+ INSTRUMENT_NAME_EMPTY ,
591+ ) ) ;
592+ }
593+ if name. len ( ) > INSTRUMENT_NAME_MAX_LENGTH {
594+ return Err ( MetricError :: InvalidInstrumentConfiguration (
595+ INSTRUMENT_NAME_LENGTH ,
596+ ) ) ;
597+ }
598+
599+ // No name restrictions when name validation is disabled,
600+ // except for empty names and length
601+ Ok ( ( ) )
602+ }
603+
604+ #[ cfg( not( feature = "experimental_metrics_disable_name_validation" ) ) ]
575605fn validate_instrument_name ( name : & str ) -> MetricResult < ( ) > {
576606 if name. is_empty ( ) {
577607 return Err ( MetricError :: InvalidInstrumentConfiguration (
@@ -583,6 +613,7 @@ fn validate_instrument_name(name: &str) -> MetricResult<()> {
583613 INSTRUMENT_NAME_LENGTH ,
584614 ) ) ;
585615 }
616+
586617 if name. starts_with ( |c : char | !c. is_ascii_alphabetic ( ) ) {
587618 return Err ( MetricError :: InvalidInstrumentConfiguration (
588619 INSTRUMENT_NAME_FIRST_ALPHABETIC ,
@@ -676,12 +707,17 @@ mod tests {
676707 use crate :: metrics:: MetricError ;
677708
678709 use super :: {
679- validate_instrument_name, validate_instrument_unit, INSTRUMENT_NAME_FIRST_ALPHABETIC ,
680- INSTRUMENT_NAME_INVALID_CHAR , INSTRUMENT_NAME_LENGTH , INSTRUMENT_UNIT_INVALID_CHAR ,
681- INSTRUMENT_UNIT_LENGTH ,
710+ validate_instrument_name, validate_instrument_unit, INSTRUMENT_NAME_EMPTY ,
711+ INSTRUMENT_NAME_LENGTH , INSTRUMENT_UNIT_INVALID_CHAR , INSTRUMENT_UNIT_LENGTH ,
712+ } ;
713+
714+ #[ cfg( not( feature = "experimental_metrics_disable_name_validation" ) ) ]
715+ use super :: {
716+ INSTRUMENT_NAME_EMPTY , INSTRUMENT_NAME_FIRST_ALPHABETIC , INSTRUMENT_NAME_INVALID_CHAR ,
682717 } ;
683718
684719 #[ test]
720+ #[ cfg( not( feature = "experimental_metrics_disable_name_validation" ) ) ]
685721 fn instrument_name_validation ( ) {
686722 // (name, expected error)
687723 let instrument_name_test_cases = vec ! [
@@ -694,6 +730,45 @@ mod tests {
694730 ( "allow/slash" , "" ) ,
695731 ( "allow_under_score" , "" ) ,
696732 ( "allow.dots.ok" , "" ) ,
733+ ( "" , INSTRUMENT_NAME_EMPTY ) ,
734+ ( "\\ allow\\ slash /sec" , INSTRUMENT_NAME_FIRST_ALPHABETIC ) ,
735+ ( "\\ allow\\ $$slash /sec" , INSTRUMENT_NAME_FIRST_ALPHABETIC ) ,
736+ ( "/not / allowed" , INSTRUMENT_NAME_FIRST_ALPHABETIC ) ,
737+ ] ;
738+ for ( name, expected_error) in instrument_name_test_cases {
739+ let assert = |result : Result < _ , MetricError > | {
740+ if expected_error. is_empty ( ) {
741+ assert ! ( result. is_ok( ) ) ;
742+ } else {
743+ assert ! ( matches!(
744+ result. unwrap_err( ) ,
745+ MetricError :: InvalidInstrumentConfiguration ( msg) if msg == expected_error
746+ ) ) ;
747+ }
748+ } ;
749+
750+ assert ( validate_instrument_name ( name) . map ( |_| ( ) ) ) ;
751+ }
752+ }
753+
754+ #[ test]
755+ #[ cfg( feature = "experimental_metrics_disable_name_validation" ) ]
756+ fn instrument_name_validation ( ) {
757+ // (name, expected error)
758+ let instrument_name_test_cases = vec ! [
759+ ( "validateName" , "" ) ,
760+ ( "_startWithNoneAlphabet" , "" ) ,
761+ ( "utf8char锈" , "" ) ,
762+ ( "a" . repeat( 255 ) . leak( ) , "" ) ,
763+ ( "a" . repeat( 256 ) . leak( ) , INSTRUMENT_NAME_LENGTH ) ,
764+ ( "invalid name" , "" ) ,
765+ ( "allow/slash" , "" ) ,
766+ ( "allow_under_score" , "" ) ,
767+ ( "allow.dots.ok" , "" ) ,
768+ ( "" , INSTRUMENT_NAME_EMPTY ) ,
769+ ( "\\ allow\\ slash /sec" , "" ) ,
770+ ( "\\ allow\\ $$slash /sec" , "" ) ,
771+ ( "/not / allowed" , "" ) ,
697772 ] ;
698773 for ( name, expected_error) in instrument_name_test_cases {
699774 let assert = |result : Result < _ , MetricError > | {
0 commit comments