@@ -67,9 +67,24 @@ func TestNewClientReturnsErrorWhenSDKIsNil(t *testing.T) {
6767}
6868
6969func TestNewClient (t * testing.T ) {
70- client , err := NewClient (newMockSDK (nil , nil ))
70+ mockSDK := newMockSDK (nil , nil )
71+ client , err := NewClient (mockSDK )
7172 require .NoError (t , err )
7273 require .NotNil (t , client )
74+
75+ // Verify SDK info event was fired on construction.
76+ require .Len (t , mockSDK .events , 1 )
77+ evt := mockSDK .events [0 ]
78+ assert .Equal (t , "$ld:ai:sdk:info" , evt .eventName )
79+ assert .Equal (t , float64 (1 ), evt .metricValue )
80+ assert .Equal (t , "launchdarkly-go-server-sdk-ai" , evt .data .GetByKey ("aiSdkName" ).StringValue ())
81+ assert .Equal (t , Version , evt .data .GetByKey ("aiSdkVersion" ).StringValue ())
82+ assert .Equal (t , "go" , evt .data .GetByKey ("aiSdkLanguage" ).StringValue ())
83+
84+ // Verify the context is anonymous with kind ld_ai.
85+ assert .Equal (t , "ld-internal-tracking" , evt .context .Key ())
86+ assert .True (t , evt .context .Anonymous ())
87+ assert .Equal (t , ldcontext .Kind ("ld_ai" ), evt .context .Kind ())
7388}
7489
7590func TestEvalErrorReturnsDefault (t * testing.T ) {
@@ -302,12 +317,48 @@ func TestCanSetDefaultConfigFields(t *testing.T) {
302317 assert .Equal (t , datamodel .System , msg [1 ].Role )
303318}
304319
305- func TestConfigMethodTracking (t * testing.T ) {
320+ func TestCompletionConfigMethodTracking (t * testing.T ) {
321+ mockSDK := newMockSDK (nil , nil )
322+ client , err := NewClient (mockSDK )
323+ require .NoError (t , err )
324+ require .NotNil (t , client )
325+
326+ // Clear the SDK info event from construction.
327+ mockSDK .events = nil
328+
329+ defaultConfig := NewConfig ().WithEnabled (false ).Build ()
330+ context := ldcontext .New ("user-key" )
331+ configKey := "test-config-key"
332+
333+ config , tracker := client .CompletionConfig (configKey , context , defaultConfig , nil )
334+
335+ require .NotNil (t , config )
336+ require .NotNil (t , tracker )
337+
338+ expectedData := ldvalue .ObjectBuild ().Set ("configKey" , ldvalue .String (configKey )).Build ()
339+ expectedEvents := []mockEvent {
340+ {
341+ eventName : "$ld:ai:usage:completion-config" ,
342+ context : context ,
343+ metricValue : 1 ,
344+ data : expectedData ,
345+ },
346+ }
347+
348+ assert .ElementsMatch (t , expectedEvents , mockSDK .events )
349+ }
350+
351+ // TestDeprecatedConfigDelegatesToCompletionConfig verifies the deprecated Config method delegates
352+ // to CompletionConfig and emits the same usage event.
353+ func TestDeprecatedConfigDelegatesToCompletionConfig (t * testing.T ) {
306354 mockSDK := newMockSDK (nil , nil )
307355 client , err := NewClient (mockSDK )
308356 require .NoError (t , err )
309357 require .NotNil (t , client )
310358
359+ // Clear the SDK info event from construction.
360+ mockSDK .events = nil
361+
311362 defaultConfig := NewConfig ().WithEnabled (false ).Build ()
312363 context := ldcontext .New ("user-key" )
313364 configKey := "test-config-key"
@@ -317,20 +368,21 @@ func TestConfigMethodTracking(t *testing.T) {
317368 require .NotNil (t , config )
318369 require .NotNil (t , tracker )
319370
371+ expectedData := ldvalue .ObjectBuild ().Set ("configKey" , ldvalue .String (configKey )).Build ()
320372 expectedEvents := []mockEvent {
321373 {
322- eventName : "$ld:ai:config:function:single " ,
374+ eventName : "$ld:ai:usage:completion-config " ,
323375 context : context ,
324376 metricValue : 1 ,
325- data : ldvalue . String ( configKey ) ,
377+ data : expectedData ,
326378 },
327379 }
328380
329381 assert .ElementsMatch (t , expectedEvents , mockSDK .events )
330382}
331383
332384// TestJudgeConfigMethodTracking verifies that JudgeConfig emits only the judge metric,
333- // not the config metric, so judge evaluations are not double-counted on the dashboard.
385+ // not the completion- config metric, so judge evaluations are not double-counted on the dashboard.
334386func TestJudgeConfigMethodTracking (t * testing.T ) {
335387 json := []byte (`{
336388 "_ldMeta": {"variationKey": "1", "enabled": true},
@@ -343,6 +395,9 @@ func TestJudgeConfigMethodTracking(t *testing.T) {
343395 require .NoError (t , err )
344396 require .NotNil (t , client )
345397
398+ // Clear the SDK info event from construction.
399+ mockSDK .events = nil
400+
346401 defaultConfig := Disabled ()
347402 context := ldcontext .New ("user-key" )
348403 configKey := "judge-config-key"
@@ -353,16 +408,17 @@ func TestJudgeConfigMethodTracking(t *testing.T) {
353408 require .NotNil (t , tracker )
354409
355410 // Only the judge metric should be emitted; evaluateConfig does not emit any metric.
411+ expectedData := ldvalue .ObjectBuild ().Set ("configKey" , ldvalue .String (configKey )).Build ()
356412 expectedEvents := []mockEvent {
357413 {
358- eventName : "$ld:ai:judge:function:single " ,
414+ eventName : "$ld:ai:usage:judge-config " ,
359415 context : context ,
360416 metricValue : 1 ,
361- data : ldvalue . String ( configKey ) ,
417+ data : expectedData ,
362418 },
363419 }
364420 assert .ElementsMatch (t , expectedEvents , mockSDK .events ,
365- "JudgeConfig must not emit $ld:ai:config:function:single to avoid double-counting" )
421+ "JudgeConfig must not emit $ld:ai:usage:completion-config to avoid double-counting" )
366422}
367423
368424func TestCanSetModelParameters (t * testing.T ) {
0 commit comments