@@ -24,11 +24,13 @@ import {
24
24
CONDITIONS_KEY_NAME ,
25
25
CLIENT_FILTERS_KEY_NAME
26
26
} from "./featureManagement/constants.js" ;
27
- import { FM_PACKAGE_NAME } from "./requestTracing/constants.js" ;
27
+ import { FM_PACKAGE_NAME , AI_MIME_PROFILE , AI_CHAT_COMPLETION_MIME_PROFILE } from "./requestTracing/constants.js" ;
28
+ import { parseContentType , isJsonContentType , isFeatureFlagContentType , isSecretReferenceContentType } from "./common/contentType.js" ;
28
29
import { AzureKeyVaultKeyValueAdapter } from "./keyvault/AzureKeyVaultKeyValueAdapter.js" ;
29
30
import { RefreshTimer } from "./refresh/RefreshTimer.js" ;
30
31
import { RequestTracingOptions , getConfigurationSettingWithTrace , listConfigurationSettingsWithTrace , requestTracingEnabled } from "./requestTracing/utils.js" ;
31
32
import { FeatureFlagTracingOptions } from "./requestTracing/FeatureFlagTracingOptions.js" ;
33
+ import { AIConfigurationTracingOptions } from "./requestTracing/AIConfigurationTracingOptions.js" ;
32
34
import { KeyFilter , LabelFilter , SettingSelector } from "./types.js" ;
33
35
import { ConfigurationClientManager } from "./ConfigurationClientManager.js" ;
34
36
@@ -58,6 +60,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
58
60
#isFailoverRequest: boolean = false ;
59
61
#featureFlagTracing: FeatureFlagTracingOptions | undefined ;
60
62
#fmVersion: string | undefined ;
63
+ #aiConfigurationTracing: AIConfigurationTracingOptions | undefined ;
61
64
62
65
// Refresh
63
66
#refreshInProgress: boolean = false ;
@@ -97,6 +100,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
97
100
// enable request tracing if not opt-out
98
101
this . #requestTracingEnabled = requestTracingEnabled ( ) ;
99
102
if ( this . #requestTracingEnabled) {
103
+ this . #aiConfigurationTracing = new AIConfigurationTracingOptions ( ) ;
100
104
this . #featureFlagTracing = new FeatureFlagTracingOptions ( ) ;
101
105
}
102
106
@@ -178,7 +182,8 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
178
182
replicaCount : this . #clientManager. getReplicaCount ( ) ,
179
183
isFailoverRequest : this . #isFailoverRequest,
180
184
featureFlagTracing : this . #featureFlagTracing,
181
- fmVersion : this . #fmVersion
185
+ fmVersion : this . #fmVersion,
186
+ aiConfigurationTracing : this . #aiConfigurationTracing
182
187
} ;
183
188
}
184
189
@@ -416,9 +421,14 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
416
421
await this . #updateWatchedKeyValuesEtag( loadedSettings ) ;
417
422
}
418
423
424
+ if ( this . #requestTracingEnabled && this . #aiConfigurationTracing !== undefined ) {
425
+ // Reset old AI configuration tracing in order to track the information present in the current response from server.
426
+ this . #aiConfigurationTracing. reset ( ) ;
427
+ }
428
+
419
429
// process key-values, watched settings have higher priority
420
430
for ( const setting of loadedSettings ) {
421
- const [ key , value ] = await this . #processKeyValues ( setting ) ;
431
+ const [ key , value ] = await this . #processKeyValue ( setting ) ;
422
432
keyValues . push ( [ key , value ] ) ;
423
433
}
424
434
@@ -467,6 +477,11 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
467
477
const loadFeatureFlag = true ;
468
478
const featureFlagSettings = await this . #loadConfigurationSettings( loadFeatureFlag ) ;
469
479
480
+ if ( this . #requestTracingEnabled && this . #featureFlagTracing !== undefined ) {
481
+ // Reset old feature flag tracing in order to track the information present in the current response from server.
482
+ this . #featureFlagTracing. reset ( ) ;
483
+ }
484
+
470
485
// parse feature flags
471
486
const featureFlags = await Promise . all (
472
487
featureFlagSettings . map ( setting => this . #parseFeatureFlag( setting ) )
@@ -633,12 +648,35 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
633
648
throw new Error ( "All clients failed to get configuration settings." ) ;
634
649
}
635
650
636
- async #processKeyValues( setting : ConfigurationSetting < string > ) : Promise < [ string , unknown ] > {
651
+ async #processKeyValue( setting : ConfigurationSetting < string > ) : Promise < [ string , unknown ] > {
652
+ this . #setAIConfigurationTracing( setting ) ;
653
+
637
654
const [ key , value ] = await this . #processAdapters( setting ) ;
638
655
const trimmedKey = this . #keyWithPrefixesTrimmed( key ) ;
639
656
return [ trimmedKey , value ] ;
640
657
}
641
658
659
+ #setAIConfigurationTracing( setting : ConfigurationSetting < string > ) : void {
660
+ if ( this . #requestTracingEnabled && this . #aiConfigurationTracing !== undefined ) {
661
+ const contentType = parseContentType ( setting . contentType ) ;
662
+ // content type: "application/json; profile=\"https://azconfig.io/mime-profiles/ai\"""
663
+ if ( isJsonContentType ( contentType ) &&
664
+ ! isFeatureFlagContentType ( contentType ) &&
665
+ ! isSecretReferenceContentType ( contentType ) ) {
666
+ const profile = contentType ?. parameters [ "profile" ] ;
667
+ if ( profile === undefined ) {
668
+ return ;
669
+ }
670
+ if ( profile . includes ( AI_MIME_PROFILE ) ) {
671
+ this . #aiConfigurationTracing. usesAIConfiguration = true ;
672
+ }
673
+ if ( profile . includes ( AI_CHAT_COMPLETION_MIME_PROFILE ) ) {
674
+ this . #aiConfigurationTracing. usesAIChatCompletionConfiguration = true ;
675
+ }
676
+ }
677
+ }
678
+ }
679
+
642
680
async #processAdapters( setting : ConfigurationSetting < string > ) : Promise < [ string , unknown ] > {
643
681
for ( const adapter of this . #adapters) {
644
682
if ( adapter . canProcess ( setting ) ) {
@@ -675,6 +713,20 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
675
713
} ;
676
714
}
677
715
716
+ this . #setFeatureFlagTracing( featureFlag ) ;
717
+
718
+ return featureFlag ;
719
+ }
720
+
721
+ #createFeatureFlagReference( setting : ConfigurationSetting < string > ) : string {
722
+ let featureFlagReference = `${ this . #clientManager. endpoint . origin } /kv/${ setting . key } ` ;
723
+ if ( setting . label && setting . label . trim ( ) . length !== 0 ) {
724
+ featureFlagReference += `?label=${ setting . label } ` ;
725
+ }
726
+ return featureFlagReference ;
727
+ }
728
+
729
+ #setFeatureFlagTracing( featureFlag : any ) : void {
678
730
if ( this . #requestTracingEnabled && this . #featureFlagTracing !== undefined ) {
679
731
if ( featureFlag [ CONDITIONS_KEY_NAME ] &&
680
732
featureFlag [ CONDITIONS_KEY_NAME ] [ CLIENT_FILTERS_KEY_NAME ] &&
@@ -693,16 +745,6 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
693
745
this . #featureFlagTracing. usesSeed = true ;
694
746
}
695
747
}
696
-
697
- return featureFlag ;
698
- }
699
-
700
- #createFeatureFlagReference( setting : ConfigurationSetting < string > ) : string {
701
- let featureFlagReference = `${ this . #clientManager. endpoint . origin } /kv/${ setting . key } ` ;
702
- if ( setting . label && setting . label . trim ( ) . length !== 0 ) {
703
- featureFlagReference += `?label=${ setting . label } ` ;
704
- }
705
- return featureFlagReference ;
706
748
}
707
749
}
708
750
0 commit comments