Skip to content

Commit 28537fa

Browse files
authored
fix(adk): separate FailoverChatModel trace span from inner model span (#1040)
* fix(adk): separate FailoverChatModel trace span from inner model span When ModelFailoverConfig is enabled, the failover proxy model was creating a trace span with the same identity as the inner model, causing duplicate "ChatModel" entries in the trace view even without actual failover retries. Fix: Use callbacks.ReuseHandlers to give the failover proxy its own distinct RunInfo (Type="FailoverChatModel") as the outer span, and create a proper child RunInfo for the target model. This produces a clear trace hierarchy: FailoverChatModel (wrapper span) └── ChatModel [ep-xxx] (actual model span) * fix(adk): separate FailoverChatModel trace span from inner model span When ModelFailoverConfig is enabled, the failover proxy model was creating a trace span with the same identity as the inner model, causing duplicate "ChatModel" entries in the trace view even without actual failover retries. Fix: Use callbacks.ReuseHandlers to give the failover proxy its own distinct RunInfo (Type="FailoverChatModel") as the outer span, and create a proper child RunInfo for the target model. This produces a clear trace hierarchy: FailoverChatModel (wrapper span) └── ChatModel [ep-xxx] (actual model span)
1 parent a19b7e4 commit 28537fa

1 file changed

Lines changed: 28 additions & 7 deletions

File tree

adk/failover_chatmodel.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,31 +59,41 @@ func getFailoverHasMoreAttempts(ctx context.Context) bool {
5959
type typedFailoverProxyModel[M MessageType] struct {
6060
}
6161

62-
func (m *typedFailoverProxyModel[M]) prepareCallbacks(ctx context.Context) (context.Context, model.BaseModel[M], error) {
62+
func (m *typedFailoverProxyModel[M]) prepareTarget(ctx context.Context) (model.BaseModel[M], string, error) {
6363
target, ok := typedGetFailoverCurrentModel[M](ctx)
6464
if !ok {
65-
return nil, nil, errors.New("failover current model not found in context")
65+
return nil, "", errors.New("failover current model not found in context")
6666
}
6767

68-
typ, _ := components.GetType(target)
69-
ctx = callbacks.EnsureRunInfo(ctx, typ, components.ComponentOfChatModel)
68+
targetType, _ := components.GetType(target)
7069

7170
if !components.IsCallbacksEnabled(target) {
7271
target = typedCallbackInjectionModelWrapper[M]{}.wrapModel(target)
7372
}
7473

75-
return ctx, target, nil
74+
return target, targetType, nil
7675
}
7776

7877
func (m *typedFailoverProxyModel[M]) Generate(ctx context.Context, input []M, opts ...model.Option) (M, error) {
79-
nCtx, target, err := m.prepareCallbacks(ctx)
78+
target, targetType, err := m.prepareTarget(ctx)
8079
if err != nil {
8180
var zero M
8281
return zero, err
8382
}
8483

84+
// Override compose-level RunInfo with FailoverChatModel identity for the outer span.
85+
ctx = callbacks.ReuseHandlers(ctx, &callbacks.RunInfo{
86+
Type: "FailoverChatModel",
87+
Component: components.ComponentOfChatModel,
88+
})
8589
ctx = callbacks.OnStart(ctx, input)
8690

91+
// Create child RunInfo for the target model.
92+
nCtx := callbacks.ReuseHandlers(ctx, &callbacks.RunInfo{
93+
Type: targetType,
94+
Component: components.ComponentOfChatModel,
95+
})
96+
8797
result, err := target.Generate(nCtx, input, opts...)
8898
if err != nil {
8999
callbacks.OnError(ctx, err)
@@ -96,13 +106,24 @@ func (m *typedFailoverProxyModel[M]) Generate(ctx context.Context, input []M, op
96106
}
97107

98108
func (m *typedFailoverProxyModel[M]) Stream(ctx context.Context, input []M, opts ...model.Option) (*schema.StreamReader[M], error) {
99-
nCtx, target, err := m.prepareCallbacks(ctx)
109+
target, targetType, err := m.prepareTarget(ctx)
100110
if err != nil {
101111
return nil, err
102112
}
103113

114+
// Override compose-level RunInfo with FailoverChatModel identity for the outer span.
115+
ctx = callbacks.ReuseHandlers(ctx, &callbacks.RunInfo{
116+
Type: "FailoverChatModel",
117+
Component: components.ComponentOfChatModel,
118+
})
104119
ctx = callbacks.OnStart(ctx, input)
105120

121+
// Create child RunInfo for the target model.
122+
nCtx := callbacks.ReuseHandlers(ctx, &callbacks.RunInfo{
123+
Type: targetType,
124+
Component: components.ComponentOfChatModel,
125+
})
126+
106127
result, err := target.Stream(nCtx, input, opts...)
107128
if err != nil {
108129
callbacks.OnError(ctx, err)

0 commit comments

Comments
 (0)