Skip to content

Commit cbb951f

Browse files
committed
fix
1 parent 43905d5 commit cbb951f

8 files changed

Lines changed: 43 additions & 121 deletions

File tree

apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -291,10 +291,8 @@ public class ComponentsDefine {
291291

292292
public static final OfficialComponent SPRING_AI_OLLAMA = new OfficialComponent(176, "spring-ai-ollama");
293293

294-
public static final OfficialComponent SPRING_AI_OPENAI_SDK = new OfficialComponent(177, "spring-ai-openai-sdk");
294+
public static final OfficialComponent SPRING_AI_ZHIPU_AI = new OfficialComponent(177, "spring-ai-zhipu-ai");
295295

296-
public static final OfficialComponent SPRING_AI_ZHIPU_AI = new OfficialComponent(178, "spring-ai-zhipu-ai");
297-
298-
public static final OfficialComponent SPRING_AI = new OfficialComponent(179, "spring-ai");
296+
public static final OfficialComponent SPRING_AI = new OfficialComponent(178, "spring-ai");
299297

300298
}

apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelCallInterceptor.java

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,9 @@
2525
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
2626
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
2727
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
28-
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
29-
import org.apache.skywalking.apm.network.trace.component.OfficialComponent;
3028
import org.apache.skywalking.apm.plugin.spring.ai.v1.common.ChatModelMetadataResolver;
3129
import org.apache.skywalking.apm.plugin.spring.ai.v1.config.SpringAiPluginConfig;
3230
import org.apache.skywalking.apm.plugin.spring.ai.v1.contant.Constants;
33-
import org.apache.skywalking.apm.plugin.spring.ai.v1.enums.AiProviderEnum;
3431
import org.apache.skywalking.apm.plugin.spring.ai.v1.messages.InputMessages;
3532
import org.apache.skywalking.apm.plugin.spring.ai.v1.messages.OutputMessages;
3633
import org.springframework.ai.chat.metadata.ChatResponseMetadata;
@@ -47,20 +44,9 @@ public class ChatModelCallInterceptor implements InstanceMethodsAroundIntercepto
4744
@Override
4845
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
4946
ChatModelMetadataResolver.ApiMetadata apiMetadata = ChatModelMetadataResolver.getMetadata(objInst);
50-
String providerName = AiProviderEnum.UNKNOWN.getValue();
51-
OfficialComponent component = ComponentsDefine.SPRING_AI_UNKNOWN;
52-
String peer = null;
53-
54-
if (apiMetadata != null) {
55-
if (apiMetadata.getProviderName() != null) {
56-
providerName = apiMetadata.getProviderName();
57-
component = apiMetadata.getComponent();
58-
}
59-
peer = apiMetadata.getPeer();
60-
}
61-
AbstractSpan span = ContextManager.createExitSpan("Spring-ai/" + providerName + "/call", peer);
47+
AbstractSpan span = ContextManager.createExitSpan("Spring-ai/" + apiMetadata.getProviderName() + "/call", apiMetadata.getPeer());
6248
SpanLayer.asGenAI(span);
63-
span.setComponent(component);
49+
span.setComponent(apiMetadata.getComponent());
6450
Tags.GEN_AI_OPERATION_NAME.set(span, Constants.CHAT);
6551
Tags.GEN_AI_PROVIDER_NAME.set(span, apiMetadata.getProviderName());
6652

@@ -70,10 +56,18 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr
7056
return;
7157
}
7258

73-
Tags.GEN_AI_REQUEST_MODEL.set(span, chatOptions.getModel());
74-
Tags.GEN_AI_TEMPERATURE.set(span, String.valueOf(chatOptions.getTemperature()));
75-
Tags.GEN_AI_TOP_K.set(span, String.valueOf(chatOptions.getTopK()));
76-
Tags.GEN_AI_TOP_P.set(span, String.valueOf(chatOptions.getTopP()));
59+
if (chatOptions.getModel() != null) {
60+
Tags.GEN_AI_REQUEST_MODEL.set(span, chatOptions.getModel());
61+
}
62+
if (chatOptions.getTemperature() != null) {
63+
Tags.GEN_AI_TEMPERATURE.set(span, String.valueOf(chatOptions.getTemperature()));
64+
}
65+
if (chatOptions.getTopK() != null) {
66+
Tags.GEN_AI_TOP_K.set(span, String.valueOf(chatOptions.getTopK()));
67+
}
68+
if (chatOptions.getTopP() != null) {
69+
Tags.GEN_AI_TOP_P.set(span, String.valueOf(chatOptions.getTopP()));
70+
}
7771
}
7872

7973
@Override
@@ -83,11 +77,12 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA
8377
}
8478

8579
try {
86-
ChatResponse response = (ChatResponse) ret;
87-
if (response == null) {
88-
return null;
80+
if (!(ret instanceof ChatResponse)) {
81+
return ret;
8982
}
9083

84+
ChatResponse response = (ChatResponse) ret;
85+
9186
AbstractSpan span = ContextManager.activeSpan();
9287
ChatResponseMetadata metadata = response.getMetadata();
9388

apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,9 @@
2626
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
2727
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
2828
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
29-
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
30-
import org.apache.skywalking.apm.network.trace.component.OfficialComponent;
3129
import org.apache.skywalking.apm.plugin.spring.ai.v1.common.ChatModelMetadataResolver;
3230
import org.apache.skywalking.apm.plugin.spring.ai.v1.config.SpringAiPluginConfig;
3331
import org.apache.skywalking.apm.plugin.spring.ai.v1.contant.Constants;
34-
import org.apache.skywalking.apm.plugin.spring.ai.v1.enums.AiProviderEnum;
3532
import org.apache.skywalking.apm.plugin.spring.ai.v1.messages.InputMessages;
3633
import org.apache.skywalking.apm.plugin.spring.ai.v1.messages.OutputMessages;
3734
import org.springframework.ai.chat.metadata.ChatResponseMetadata;
@@ -54,21 +51,12 @@ public class ChatModelStreamInterceptor implements InstanceMethodsAroundIntercep
5451
@Override
5552
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
5653
ChatModelMetadataResolver.ApiMetadata apiMetadata = ChatModelMetadataResolver.getMetadata(objInst);
57-
String providerName = AiProviderEnum.UNKNOWN.getValue();
58-
OfficialComponent component = ComponentsDefine.SPRING_AI_UNKNOWN;
59-
String peer = null;
60-
61-
if (apiMetadata != null) {
62-
if (apiMetadata.getProviderName() != null) {
63-
providerName = apiMetadata.getProviderName();
64-
component = apiMetadata.getComponent();
65-
}
66-
peer = apiMetadata.getPeer();
67-
}
68-
AbstractSpan span = ContextManager.createExitSpan("Spring-ai/" + providerName + "/stream", peer);
54+
AbstractSpan span = ContextManager.createExitSpan("Spring-ai/" + apiMetadata.getProviderName() + "/stream", apiMetadata.getPeer());
6955
SpanLayer.asGenAI(span);
7056

71-
span.setComponent(component);
57+
span.setComponent(apiMetadata.getComponent());
58+
Tags.GEN_AI_OPERATION_NAME.set(span, Constants.CHAT);
59+
Tags.GEN_AI_PROVIDER_NAME.set(span, apiMetadata.getProviderName());
7260
SpanLayer.asGenAI(span);
7361

7462
Prompt prompt = (Prompt) allArguments[0];
@@ -81,8 +69,6 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr
8169
return;
8270
}
8371

84-
Tags.GEN_AI_OPERATION_NAME.set(span, Constants.CHAT);
85-
Tags.GEN_AI_PROVIDER_NAME.set(span, apiMetadata.getProviderName());
8672
Tags.GEN_AI_REQUEST_MODEL.set(span, chatOptions.getModel());
8773
Tags.GEN_AI_TEMPERATURE.set(span, String.valueOf(chatOptions.getTemperature()));
8874
Tags.GEN_AI_TOP_K.set(span, String.valueOf(chatOptions.getTopK()));
@@ -96,6 +82,7 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA
9682
if (!ContextManager.isActive()) {
9783
return ret;
9884
}
85+
9986
final AbstractSpan span = ContextManager.activeSpan();
10087
final ContextSnapshot snapshot = ContextManager.capture();
10188

apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/common/ChatModelMetadataResolver.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.skywalking.apm.network.trace.component.OfficialComponent;
2525
import org.apache.skywalking.apm.plugin.spring.ai.v1.enums.AiProviderEnum;
2626

27+
import javax.validation.constraints.NotNull;
2728
import java.util.HashMap;
2829
import java.util.Map;
2930

@@ -71,7 +72,7 @@ private static OfficialComponent matchComponent(AiProviderEnum provider) {
7172
case OLLAMA:
7273
return ComponentsDefine.SPRING_AI_OLLAMA;
7374
case OPENAI_SDK_OFFICIAL:
74-
return ComponentsDefine.SPRING_AI_OPENAI_SDK;
75+
return ComponentsDefine.SPRING_AI_OPENAI;
7576
case ZHIPU_AI:
7677
return ComponentsDefine.SPRING_AI_ZHIPU_AI;
7778
case UNKNOWN:
@@ -80,8 +81,12 @@ private static OfficialComponent matchComponent(AiProviderEnum provider) {
8081
}
8182
}
8283

84+
@NotNull
8385
public static ApiMetadata getMetadata(Object chatModelInstance) {
8486
ApiMetadata metadata = MODEL_METADATA_MAP.get(chatModelInstance.getClass().getName());
87+
if (metadata == null) {
88+
MODEL_METADATA_MAP.get(AiProviderEnum.UNKNOWN);
89+
}
8590
return metadata;
8691
}
8792

apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/ChatModelInstrumentation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public String getMethodsInterceptor() {
8484

8585
@Override
8686
public boolean isOverrideArgs() {
87-
return false;
87+
return true;
8888
}
8989
}
9090
};

test/plugin/scenarios/spring-ai-1.x-scenario/config/expectedData.yaml

Lines changed: 10 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ segmentItems:
2020

2121
- segmentId: not null
2222
spans:
23-
2423
- operationName: GET:/spring-ai-1.x-scenario/case/spring-ai-1.x-scenario-case
2524
parentSpanId: -1
2625
spanId: 0
@@ -36,6 +35,7 @@ segmentItems:
3635
parentSpanId: 0
3736
spanId: 1
3837
spanLayer: UNRECOGNIZED
38+
componentId: 173
3939
spanType: Exit
4040
peer: http://localhost:8080/spring-ai-1.x-scenario/llm/v1/chat/completions
4141
tags:
@@ -44,7 +44,15 @@ segmentItems:
4444
- { key: gen_ai.request.model, value: gpt-4.1-2025-04-14 }
4545
- { key: gen_ai.request.temperature, value: '0.7' }
4646
- { key: gen_ai.request.top_p, value: '0.9' }
47-
- { key: gen_ai.output.messages, value: "The weather in New York is currently sunny with a temperature of 10°C." }
47+
- { key: gen_ai.request.top_k, value: null }
48+
- { key: gen_ai.response.id, value: '' }
49+
- { key: gen_ai.response.model, value: gpt-4.1-2025-04-14 }
50+
- { key: gen_ai.usage.input_tokens, value: '52' }
51+
- { key: gen_ai.usage.output_tokens, value: '17' }
52+
- { key: gen_ai.client.token.usage, value: '69' }
53+
- { key: gen_ai.response.finish_reasons, value: STOP }
54+
- { key: gen_ai.input.messages, value: '[{"role":"system","parts":[{"type":"text","content":"You are a professional technical assistant.\\nStrictly use the provided context to answer questions.\\nIf the information is not in the context, say: \\\"I''m sorry, I don''t have that information in my knowledge base.\\\"\\nDo not use outside knowledge. Be concise.\\n"}]},{"role":"user","parts":[{"type":"text","content":"What''s the weather in New York?"}]}]' }
55+
- { key: gen_ai.output.messages, value: '[{"role":"assistant","parts":[{"type":"text","content":"The weather in New York is currently sunny with a temperature of 10°C."}],"finish_reason":"stop"}]' }
4856

4957
- operationName: Spring-ai/tool/call
5058
parentSpanId: 1
@@ -62,65 +70,3 @@ segmentItems:
6270
- { key: gen_ai.operation.name, value: execute_tool }
6371
- { key: gen_ai.tool.call.arguments, value: '{"arg0":"new york"}' }
6472
- { key: gen_ai.tool.call.result, value: '"Sunny, 10°C"' }
65-
66-
- operationName: Spring-ai/openai/stream
67-
parentSpanId: 0
68-
spanId: 4
69-
spanLayer: UNRECOGNIZED
70-
spanType: Exit
71-
peer: http://localhost:8080/spring-ai-1.x-scenario/llm/v1/chat/completions
72-
tags:
73-
- { key: gen_ai.operation.name, value: chat }
74-
- { key: gen_ai.provider.name, value: openai }
75-
- { key: gen_ai.request.model, value: gpt-4.1-2025-04-14 }
76-
- { key: gen_ai.stream.ttfr, value: '385' }
77-
- { key: gen_ai.response.id, value: chatcmpl-cb9fe83f-bc71-4e48-a26e-69c444e73d9d }
78-
79-
- operationName: /spring-ai-1.x-scenario/llm/v1/chat/completions
80-
parentSpanId: 0
81-
spanId: 5
82-
spanLayer: Http
83-
spanType: Exit
84-
componentId: 99
85-
tags:
86-
- { key: url, value: http://localhost:8080/spring-ai-1.x-scenario/llm/v1/chat/completions }
87-
- { key: http.method, value: POST }
88-
- { key: http.status_code, value: '200' }
89-
90-
- segmentId: not null
91-
spans:
92-
93-
- operationName: Spring-ai/tool/call
94-
parentSpanId: -1
95-
spanId: 0
96-
spanLayer: Unknown
97-
spanType: Local
98-
refs:
99-
- { parentSpanId: 4, type: CROSS_THREAD }
100-
101-
- operationName: Spring-ai/tool/execute/get_weather
102-
parentSpanId: 0
103-
spanId: 1
104-
spanLayer: UNRECOGNIZED
105-
spanType: Local
106-
tags:
107-
- { key: gen_ai.tool.name, value: get_weather }
108-
- { key: gen_ai.operation.name, value: execute_tool }
109-
- { key: gen_ai.tool.call.arguments, value: '{"arg0":"new york"}' }
110-
- { key: gen_ai.tool.call.result, value: '"Sunny, 10°C"' }
111-
112-
- segmentId: not null
113-
spans:
114-
115-
- operationName: /spring-ai-1.x-scenario/llm/v1/chat/completions
116-
parentSpanId: -1
117-
spanId: 0
118-
spanLayer: Http
119-
spanType: Exit
120-
componentId: 99
121-
refs:
122-
- { parentSpanId: 4, type: CROSS_THREAD }
123-
tags:
124-
- { key: url, value: http://localhost:8080/spring-ai-1.x-scenario/llm/v1/chat/completions }
125-
- { key: http.method, value: POST }
126-
- { key: http.status_code, value: '200' }

test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/CaseController.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,6 @@ public String testCase() throws Exception {
5454
.call()
5555
.content();
5656

57-
chatClient
58-
.prompt("What's the weather in New York?")
59-
.system(systemPrompt)
60-
.tools(weatherTool)
61-
.stream()
62-
.content()
63-
.doOnNext(System.out::println)
64-
.blockLast();
65-
6657
return "success";
6758
}
6859
}

test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/LLMMockController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public Object completions(@RequestBody JSONObject request, HttpServletResponse r
157157
"cached_tokens": 0
158158
},
159159
"total_tokens": 69
160-
}
160+
},
161161
"model": "gpt-4.1-2025-04-14",
162162
"object": "chat.completion"
163163
}

0 commit comments

Comments
 (0)