Skip to content

otel_apm_service_map: Added support for deriving remote service and remote operation#6539

Merged
kkondaka merged 4 commits intoopensearch-project:mainfrom
kkondaka:otel-apm-fields
Feb 24, 2026
Merged

otel_apm_service_map: Added support for deriving remote service and remote operation#6539
kkondaka merged 4 commits intoopensearch-project:mainfrom
kkondaka:otel-apm-fields

Conversation

@kkondaka
Copy link
Copy Markdown
Collaborator

Description

otel_apm_service_map: Added support for deriving remote service and remote operation.
Derives operation differently for server and client spans based on various attributes.

Issues Resolved

Resolves #[Issue number to be closed when this PR is merged]

Check List

  • [ X] New functionality includes testing.
  • New functionality has a documentation issue. Please link to it in this PR.
    • New functionality has javadoc added
  • [X ] Commits are signed with a real name per the DCO

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

…emote operation

Signed-off-by: Krishna Kondaka <krishkdk@amazon.com>
"Amazon S3", "AWS::S3",
"s3", "AWS::S3");

public static Pair<String,String> computeRemoteOperationAndService(final Map<String, Object> spanAttributes) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this need to be public? If so, lets return a model instead of a Pair.

}

private static String deriveServiceFromNetwork(final Map<String, Object> spanAttributes, final String urlString) {
final String[][] addressPortPairs = {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This also can come from a configuration file.

String remoteService = null;

// RPC attributes
final String rpcService = getStringAttribute(spanAttributes, "rpc.service");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is a lot in here that can change or be added to. Let's find a way to avoid requiring code changes for these. Perhaps using a resources file that has the mappings. Then the code can read the file for these mappings.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@dlvenable it's not just about the list of things but the logic to extract the derived fields is not same. We cannot capture the logic in the resource file, right?

return spanName != null ? spanName : "UnknownOperation";
}

private static final Map<String, String> AWS_SERVICE_MAPPINGS = Map.of(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's put this into a file as well.

if (isServerSpan(span)) {
operationName = computeOperationName(span.getName(), spanAttributes);
} else if (isClientSpan(span) || isProducerSpan(span)) {
final Pair<String, String> remoteOperationAndService = computeRemoteOperationAndService(spanAttributes);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this change going to affect service_map as well? Is that ok?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It is just adding an attribute. Not going to change any thing in the service map

}
}

private static boolean isServerSpan(Span span) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

These would be better as default methods in the Span interface.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Span is in data-prepper-api and it doesn't import io.opentelemetry.proto.trace.v1.Span. And this method should actually be. comparing with io.opentelemetry.proto.trace.v1.Span.SpanKind.SPAN_KIND_SERVER. I will keep it here for now. If needed we can refactor to a different file under otel-proto-common in future

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That reasoning makes sense and we probably should not add this to the package. Once we get the EventFactory fully working we can probably solve this because we won't need to have it in data-prepper-api.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@kkondaka can we make changes for environment detection as well. there are more clauses for cloud specific environemnt?

Signed-off-by: Krishna Kondaka <krishkdk@amazon.com>

for (final Span span : spans) {
if (span != null && SPAN_KIND_SERVER.equals(span.getKind())) {
System.out.println("--checking-----SERVER SPAN---"+isServerSpan(span));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Remove println. This is probably failing the build.

}
}

private static boolean isServerSpan(Span span) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That reasoning makes sense and we probably should not add this to the package. Once we get the EventFactory fully working we can probably solve this because we won't need to have it in data-prepper-api.


package org.opensearch.dataprepper.plugins.otel.common;

public class RemoteOperationAndService {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can these classes be package protected? If so, let's start there and open only as needed.

}


public Map<String, String> getAwsServiceMappingsFromResources() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should have it's own class and it's own unit testing. This makes it more general purpose for extension.

return reader.lines()
.filter(line -> line.contains(","))
.collect(Collectors.toMap(
line -> line.split(",", 2)[0].trim(),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Add some error handling if the line doesn't split as expected.

Also, only split once and re-use that array.

return new AddressPortAttributeKeys(str);
}

public List<AddressPortAttributeKeys> getAddressPortAttributeKeysList() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This also should have its own class and its own unit tests. This makes is ready for expansion.

@@ -0,0 +1,12 @@
AmazonDynamoDBv2,AWS::DynamoDB
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Rename to aws_service_mappings.

final String address;
final String port;
public AddressPortAttributeKeys(final String str) {
this.address = str.split(",")[0];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Split once and re-use the array. Also, add error handling with a useful error message if there are not exactly two elements in the array.

return remoteService;
}

public boolean isNull() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This code would be clearer if you return Optional<RemoteOperationAndService> instead of having an isNull method.

An approach to make the call simple would be a static helper like this:

Optional<RemoteOperationAndService> fromNullableFields(final String operation, final String service) {
  if(operation == null || service == null)
    return Optional.empty();
  return Optional.of(new RemoteOperationAndService(operation, service);
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

We can't return empty if one of them is NULL. But we need to know that one of them is null so that we can set it to default value

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Maybe the name is little misleading. I will rename it.

Signed-off-by: Krishna Kondaka <krishkdk@amazon.com>
dlvenable
dlvenable previously approved these changes Feb 24, 2026
Signed-off-by: Krishna Kondaka <krishkdk@amazon.com>
@kkondaka kkondaka merged commit fa41484 into opensearch-project:main Feb 24, 2026
138 of 142 checks passed
opensearch-trigger-bot bot pushed a commit that referenced this pull request Feb 24, 2026
…emote operation (#6539)

* otel_apm_service_map: Added support for deriving remote service and remote operation

Signed-off-by: Krishna Kondaka <krishkdk@amazon.com>

* Addressed review comments

Signed-off-by: Krishna Kondaka <krishkdk@amazon.com>

* Addressed review comments

Signed-off-by: Krishna Kondaka <krishkdk@amazon.com>

* Fixed license header check failures

Signed-off-by: Krishna Kondaka <krishkdk@amazon.com>

---------

Signed-off-by: Krishna Kondaka <krishkdk@amazon.com>
(cherry picked from commit fa41484)
kkondaka added a commit that referenced this pull request Feb 24, 2026
…emote operation (#6539) (#6565)

* otel_apm_service_map: Added support for deriving remote service and remote operation



* Addressed review comments



* Addressed review comments



* Fixed license header check failures



---------


(cherry picked from commit fa41484)

Signed-off-by: Krishna Kondaka <krishkdk@amazon.com>
Co-authored-by: Krishna Kondaka <krishkdk@amazon.com>
@dlvenable dlvenable added this to the v2.14 milestone Feb 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants