Skip to content

Pr#83 branch3 DeepseekV3.1#3

Open
Konuralpkilinc wants to merge 2 commits intotargetfrom
PR#83-branch3
Open

Pr#83 branch3 DeepseekV3.1#3
Konuralpkilinc wants to merge 2 commits intotargetfrom
PR#83-branch3

Conversation

@Konuralpkilinc
Copy link
Copy Markdown

This PR adds support for the returnedObj expression in the APM Customize Enhance Plugin, allowing tags and logs to be populated from method return values. It also updates the plugin to use the V2 API for enhanced instrumentation.

Changes by File

  • CHANGES.md: Added release note for returnedObj expression support.
  • CustomizeExpressionTest.java: Updated package name and imports.
  • CustomizeInstanceInstrumentation.java: Migrated to V2 API, replacing ClassInstanceMethodsEnhancePluginDefine and InstanceMethodsInterceptPoint with their V2 counterparts.
  • CustomizeStaticInstrumentation.java: Similarly migrated static instrumentation to V2 API.
  • BaseInterceptorMethods.java: Enhanced to evaluate returnedObj expressions in afterMethod, adding support for return value context in tags and logs.
  • CustomizeInstanceInterceptor.java: Updated to extend V2 interceptor and pass MethodInvocationContext.
  • CustomizeStaticInterceptor.java: Similarly updated for static methods.
  • Customize-enhance-trace.md: Added documentation for returnedObj expression usage.
  • startup.sh: Minor script formatting fix.
  • customize_enhance.xml: Added example configurations using returnedObj.
  • expectedData.yaml: Added expected span data for new methods using return value expressions.
  • CustomizeController.java: Added calls to new methods demonstrating returnedObj usage.
  • TestService1.java: Implemented new methods returning values for testing.

deeployed-peer-dev[bot]

This comment was marked as outdated.

@Konuralpkilinc Konuralpkilinc changed the title Pr#83 branch3 Pr#83 branch3 DeepseekV3.1 Oct 28, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Deeployed-Peer Deeployed-Peer deleted a comment from deeployed-peer-dev bot Oct 29, 2025
@Konuralpkilinc
Copy link
Copy Markdown
Author

@deeployed-peer-dev review

@deeployed-peer-dev
Copy link
Copy Markdown

deeployed-peer-dev bot commented Oct 29, 2025

Walkthrough

This PR migrates the Customize Enhance Plugin to the V2 API and adds support for the returnedObj expression feature, enabling tags and logs to be populated from method return values. Test scenarios are updated to validate these changes.

Changes
Files Summary
CustomizeInstanceInstrumentation.java, CustomizeStaticInstrumentation.java Migrated instance and static instrumentation classes to V2 API, replacing base classes and updating method names for enhanced capabilities.
BaseInterceptorMethods.java, CustomizeInstanceInterceptor.java, CustomizeStaticInterceptor.java Added returnedObj expression support and migrated interceptors to V2 API, enabling return value context in tags/logs.
CustomizeController.java, TestService1.java, expectedData.yaml Updated test scenario with new methods to validate returnedObj feature, showing return values populating tags and logs.
CustomizeExpressionTest.java Updated package declaration and imports to align with new V2 API package structure.
startup.sh Fixed minor formatting issue by removing trailing space in Java command line.
Sequence Diagram
sequenceDiagram
    participant A as APM Agent
    participant CE as Customize Enhance Plugin
    participant T as Target Method
    participant C as Context

    A->>CE: Instrumentation (V2 API)
    CE->>T: Method Call
    T-->>CE: Return Value
    CE->>C: Evaluate returnedObj Expression
    C->>CE: Populate Tags/Logs
    CE-->>A: Enhanced Span Data
Loading

Uplevel your code reviews with Deeployed Peer!

Copy link
Copy Markdown

@deeployed-peer-dev deeployed-peer-dev bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commits Files that changed from the base of the PR and between Base and 86ff5ed commits: 13
Files Selected For Review: 10
  • apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/util/CustomizeExpressionTest.java with diff length 263.
  • apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/define/CustomizeInstanceInstrumentation.java with diff length 2438.
  • apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/define/CustomizeStaticInstrumentation.java with diff length 2327.
  • apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/interceptor/BaseInterceptorMethods.java with diff length 9156.
  • apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/interceptor/CustomizeInstanceInterceptor.java with diff length 2007.
  • apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/interceptor/CustomizeStaticInterceptor.java with diff length 1683.
  • test/plugin/scenarios/customize-scenario/bin/startup.sh with diff length 256.
  • test/plugin/scenarios/customize-scenario/config/expectedData.yaml with diff length 852.
  • test/plugin/scenarios/customize-scenario/src/main/java/test/apache/skywalking/apm/testcase/customize/controller/CustomizeController.java with diff length 237.
  • test/plugin/scenarios/customize-scenario/src/main/java/test/apache/skywalking/apm/testcase/customize/service/TestService1.java with diff length 282.
Files excluded from review due to unsupported file extensions: 3
  • CHANGES.md
  • docs/en/setup/service-agent/java-agent/Customize-enhance-trace.md
  • test/plugin/scenarios/customize-scenario/config/customize_enhance.xml
Review comments generated: (29)
  • Review: 15
  • LGTM: 14
  • Identified issue already discussed: 0

Tips

Chat with Deeployed Bot (@@deeployed-peer-dev)

  • Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
  • Invite the bot into a review comment chain by tagging @@deeployed-peer-dev in a reply.

Code suggestions

  • The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
  • You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.

Pausing incremental reviews

  • Add @deeployed-peer-dev: ignore anywhere in the PR description to pause further reviews from the bot.

*/

package org.apache.skywalking.apm.plugin.customize.util;
package org.apache.skywalking.apm.agent.core.util;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The package name has been updated to reflect the new location. This change aligns with the migration to the V2 API structure.

Suggested change
package org.apache.skywalking.apm.agent.core.util;
package org.apache.skywalking.apm.agent.core.util;

Comment on lines 21 to 22
import org.junit.Assert;
import org.junit.Test;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import for CustomizeExpression has been removed since it's now in the same package, making the import unnecessary.

Suggested change
import org.junit.Assert;
import org.junit.Test;
import org.junit.Assert;
import org.junit.Test;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FP_Hallucination

Comment on lines +59 to +101
void beforeMethod(Method method, Object[] allArguments, MethodInvocationContext miContext) {
Map<String, Object> configuration = CustomizeConfiguration.INSTANCE.getConfiguration(method);
String operationName = MethodConfiguration.getOperationName(configuration);
Map<String, Object> context = CustomizeExpression.evaluationContext(allArguments);
if (context == null || context.isEmpty()) {
ContextManager.createLocalSpan(operationName);
} else {
Map<String, Object> evalContext = CustomizeExpression.evaluationContext(allArguments);

Map<String, String> tags = MethodConfiguration.getTags(configuration);
Map<String, String> spanTags = new HashMap<String, String>();
Map<String, String> logs = MethodConfiguration.getLogs(configuration);
Map<String, String> spanLogs = new HashMap<String, String>();
Map<String, String> tags = MethodConfiguration.getTags(configuration);
Map<String, String> logs = MethodConfiguration.getLogs(configuration);
Map<String, String> spanTags = tags == null ? Collections.EMPTY_MAP : new HashMap<String, String>(tags.size());
Map<String, String> spanLogs = logs == null ? Collections.EMPTY_MAP : new HashMap<String, String>(logs.size());

if (evalContext == null || evalContext.isEmpty()) {
SpanDataHolder spanDataHolder = new SpanDataHolder(
ContextManager.createLocalSpan(operationName),
tags, logs, spanTags, spanLogs
);
miContext.setContext(spanDataHolder);
} else {
List<String> operationNameSuffixes = MethodConfiguration.getOperationNameSuffixes(configuration);
StringBuilder operationNameSuffix = new StringBuilder();
if (operationNameSuffixes != null && !operationNameSuffixes.isEmpty()) {
for (String expression : operationNameSuffixes) {
operationNameSuffix.append(Constants.OPERATION_NAME_SEPARATOR);
operationNameSuffix.append(CustomizeExpression.parseExpression(expression, context));
}
}
if (tags != null && !tags.isEmpty()) {
for (Map.Entry<String, String> expression : tags.entrySet()) {
spanTags.put(expression.getKey(), CustomizeExpression.parseExpression(expression.getValue(), context));
}
}
if (logs != null && !logs.isEmpty()) {
for (Map.Entry<String, String> entries : logs.entrySet()) {
String expression = logs.get(entries.getKey());
spanLogs.put(entries.getKey(), CustomizeExpression.parseExpression(expression, context));
operationNameSuffix.append(CustomizeExpression.parseExpression(expression, evalContext));
}
}
evalAndPopulate(evalContext, tags, spanTags);
evalAndPopulate(evalContext, logs, spanLogs);

operationName = operationNameSuffix.insert(0, operationName).toString();
AbstractSpan localSpan = ContextManager.createLocalSpan(operationName);

AbstractSpan span = ContextManager.createLocalSpan(operationName);
if (!spanTags.isEmpty()) {
for (Map.Entry<String, String> tag : spanTags.entrySet()) {
span.tag(Tags.ofKey(tag.getKey()), tag.getValue());
tagSpanTags(localSpan, spanTags);
tagSpanLogs(localSpan, spanLogs);

spanTags.clear();
spanLogs.clear();

SpanDataHolder spanDataHolder = new SpanDataHolder(
localSpan, tags, logs, spanTags, spanLogs
);
miContext.setContext(spanDataHolder);
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The beforeMethod method has been significantly refactored to use the V2 API and support returnedObj expressions. The logic is now split into two branches based on whether the evaluation context is empty. The code correctly handles the new SpanDataHolder pattern and properly manages span tags and logs.

Comment on lines +103 to +135
void afterMethod(Method method, Object ret, MethodInvocationContext miContext) {
if (!ContextManager.isActive()) {
return;
}
SpanDataHolder spanDataHolder = (SpanDataHolder) miContext.getContext();
if (spanDataHolder == null || spanDataHolder.localSpan == null) {
return;
}
AbstractSpan localSpan = spanDataHolder.localSpan;
if (ret == null) {
ContextManager.stopSpan(localSpan);
return;
}
Map<String, String> tags = spanDataHolder.tags;
Map<String, String> logs = spanDataHolder.logs;
Map<String, String> spanTags = spanDataHolder.spanTags;
Map<String, String> spanLogs = spanDataHolder.spanLogs;

try {
Map<String, Object> evalContext = CustomizeExpression.evaluationReturnContext(ret);

evalReturnAndPopulate(evalContext, tags, spanTags);
evalReturnAndPopulate(evalContext, logs, spanLogs);

tagSpanTags(localSpan, spanTags);
tagSpanLogs(localSpan, spanLogs);

spanTags.clear();
spanLogs.clear();
} finally {
ContextManager.stopSpan(localSpan);
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The afterMethod method now properly handles return values and evaluates returnedObj expressions. The method correctly checks for active context and uses the SpanDataHolder to manage span data. The implementation ensures that return value expressions are processed before stopping the span.

Comment on lines +141 to +151
private void evalAndPopulate(Map<String, Object> context, Map<String, String> exprMap, Map<String, String> toMap) {
if (exprMap != null && !exprMap.isEmpty()) {
for (Map.Entry<String, String> entry : exprMap.entrySet()) {
String expression = entry.getValue();
if (isReturnedObjExpression(expression)) {
continue;
}
toMap.put(entry.getKey(), CustomizeExpression.parseExpression(expression, context));
}
if (!spanLogs.isEmpty()) {
span.log(System.currentTimeMillis(), spanLogs);
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The evalAndPopulate method correctly skips returnedObj expressions during the beforeMethod phase, ensuring they're only processed in afterMethod. The logic properly iterates through expression maps and populates the target map with evaluated expressions.

MethodInterceptResult result) throws Throwable {
super.beforeMethod(method, allArguments);
MethodInvocationContext context) throws Throwable {
super.beforeMethod(method, allArguments, context);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The beforeMethod call is missing the objInst parameter that should be passed to the base class method.

Suggested change
super.beforeMethod(method, allArguments, context);
super.beforeMethod(objInst, method, allArguments, context);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FP_nitpick

Object ret) throws Throwable {
super.afterMethod(method);
Object ret, MethodInvocationContext context) throws Throwable {
super.afterMethod(method, ret, context);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The afterMethod call is missing the objInst parameter that should be passed to the base class method.

Suggested change
super.afterMethod(method, ret, context);
super.afterMethod(objInst, method, ret, context);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FP_nitpick

public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
Class<?>[] argumentsTypes, Throwable t, MethodInvocationContext context) {
super.handleMethodException(t);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The handleMethodException call is missing the objInst parameter that should be passed to the base class method.

Suggested change
super.handleMethodException(t);
super.handleMethodException(objInst, method, allArguments, argumentsTypes, t, context);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FP_Hallucination

Comment on lines 28 to 32
@Override
public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes,
MethodInterceptResult result) {
super.beforeMethod(method, allArguments);
MethodInvocationContext context) {
super.beforeMethod(method, allArguments, context);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The beforeMethod signature has been updated to include MethodInvocationContext context parameter, but the super call is missing the result parameter that was previously passed. This could break the expected behavior of the interceptor chain.

Suggested change
@Override
public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes,
MethodInterceptResult result) {
super.beforeMethod(method, allArguments);
MethodInvocationContext context) {
super.beforeMethod(method, allArguments, context);
}
public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes,
MethodInvocationContext context) {
super.beforeMethod(method, allArguments, context);
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FP_Hallucination

Comment on lines 34 to 39
@Override
public Object afterMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes,
Object ret) {
super.afterMethod(method);
Object ret, MethodInvocationContext context) {
super.afterMethod(method, ret, context);
return ret;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The afterMethod signature has been updated correctly, but the super call is missing the allArguments parameter that was previously passed. This could affect the evaluation of expressions that depend on method arguments.

Suggested change
@Override
public Object afterMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes,
Object ret) {
super.afterMethod(method);
Object ret, MethodInvocationContext context) {
super.afterMethod(method, ret, context);
return ret;
}
public Object afterMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes,
Object ret, MethodInvocationContext context) {
super.afterMethod(method, allArguments, ret, context);
return ret;
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FP_Hallucination

@Konuralpkilinc
Copy link
Copy Markdown
Author

Konuralpkilinc commented Oct 30, 2025

DeepseekV3.1
4 FP_Hallucination
2 FP_Nitpick
1 BP
3 FN

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants