Skip to content

Tag DynamoDB and S3 client spans with the owning AWS account - #12602

Open
pedramsafaei wants to merge 5 commits into
DataDog:masterfrom
pedramsafaei:pedramsafaei/aws-account-identity-tags
Open

pedramsafaei wants to merge 5 commits into
DataDog:masterfrom
pedramsafaei:pedramsafaei/aws-account-identity-tags

Conversation

@pedramsafaei

@pedramsafaei pedramsafaei commented Sep 22, 2026 •

Copy link
Copy Markdown

What Does This Do

Tags DynamoDB and S3 client spans (AWS SDK v1 and v2) with the AWS account that owns the addressed resource, using only information the tracer already holds. No additional network calls.

Case New tags Source of the account
DynamoDB, TableName is an ARN aws_account, aws.table.arn (existing aws.table.name / tablename / peer.service are unchanged) the ARN
DynamoDB, bare TableName (SDK v2) aws_account the credentials signing the request
S3, ExpectedBucketOwner set and the request succeeds aws_account the request field, applied from the successful response

Why the bare-name case is sound: DynamoDB documents that "If you only provide the table name parameter instead of a complete ARN, the API operation will be performed on the table in the account to which the requestor belongs" (Cross-account access with resource-based policies). Cross-account access requires either the full ARN as TableName (account is then in the request) or credentials from a role in the owning account (account is then in the credentials). Either way the account owning the signing credentials is the table owner whenever the name is bare.

Why ExpectedBucketOwner is sound: S3 rejects the request with 403 when it does not match the bucket owner, so on a successful response it is authoritative. The tag is applied from the response hook (v2: carried in an ExecutionAttribute from onSdkRequest to onSdkResponse, set only on a 2xx; v1: set in afterResponse, which does not run for errors), so a rejected owner is never tagged on the error span.

Where the caller account comes from on SDK v2: AwsSignerExecutionAttribute.AWS_CREDENTIALS is read in onSdkRequest, and AwsCredentialsIdentity.accountId() (added in SDK 2.26, populated by the STS, SSO, profile, process and container credential providers) is called through a MethodHandle looked up by name per credentials class, because the AwsCredentialsIdentity interface itself does not exist at the 2.2.0 floor the instrumentation compiles against. The handle is held in a ClassValue (the same GenericClassValue the v1 GetterAccess uses) rather than a static map, so a credentials class from an application class loader is never pinned by instrumentation state. Fatal errors (VirtualMachineError, ThreadDeath) thrown by the lookup are rethrown; anything else means the account is absent for that request. On SDKs older than 2.26 the credentials carry no account and no account is tagged for a bare name. Only aws_account is added in that case; no table ARN is synthesized from it, so aws.table.arn only ever carries a value that was in the request.

SDK v1 does not expose the signing credentials to request handlers (and HandlerContextKey does not exist at the 1.11.0 floor), so v1 covers the ARN and ExpectedBucketOwner cases only.

The tag name aws_account is what dd-trace-py already emits for the SNS and SQS account it derives from TopicArn and QueueUrl, and it is the dimension tag on the aws.dynamodb.* integration metrics, so a span and the metrics for the same table join without translation. It is also on the allow list of the Agent's credit card obfuscator (see below).

Implementation:

  • aws-java-common: new AwsArn value type that parses an ARN once (partition, service, Region, account, resource), plus AwsAccountIdentity (twelve-digit account validation). Both are pure java.lang with no agent dependencies. The SDK's own software.amazon.awssdk.arns.Arn is not used because the arns module is not a dependency of aws-core at the 2.2.0 floor these instrumentations compile against, and SDK v1 has no equivalent. Both SDK modules take aws-java-common as an implementation project(...) dependency and register the classes in helperClassNames() so they are injected alongside the decorators, the same pattern as elasticsearch-common and kafka-common. (Initially placed in agent-bootstrap; moved here per review, since bootstrap is loaded for every JVM and this is AWS-specific.)
  • aws-java-sdk-2.2: onDynamoDbTable replaces the plain setTableName call; callerAccount / credentialsAccountId read the credentials; ExpectedBucketOwner handled in the S3 branch.
  • aws-java-sdk-1.11: GetterAccess gains getExpectedBucketOwner; the decorator handles the ARN form of TableName and ExpectedBucketOwner.
  • internal-api: the two tag constants. No new configuration.

Motivation

aws.table.name says which table, not whose. Two accounts can each own an orders table in the same Region, and the span alone cannot tell them apart, which breaks any account-aware dependency map and any join to the AWS integration metrics (which are keyed by account). The ARN and the signing credentials already carry the answer; the tracer was discarding it.

Compatibility: no existing tag changes value. A TableName given as an ARN is still emitted verbatim as aws.table.name, tablename and peer.service, as today; the ARN and account are additions. (An earlier revision replaced those with the bare table name; that was reverted since it would have changed peer.service, and with it service maps and monitors, for callers that already pass ARNs.)

Additional Notes

Testing

  • AwsArnTest and AwsAccountIdentityTest (aws-java-common, JUnit 5, 23 + 10 cases): ARN parsing across partitions and resource shapes, malformed ARNs, twelve-digit account validation.
  • AwsSdkClientDecoratorCredentialsTest (aws-java-sdk-2.2, JUnit 5, 5 cases): the accountId() lookup against credentials classes that declare the method (the suite's SDK predates it): account read; class without the method (AwsBasicCredentials 2.2.0) ignored; empty and malformed values ignored; a provider that throws is treated as absent; an OutOfMemoryError propagates.
  • Aws2ClientTest (forkedTest, 37 + 37 across the V0/V1 naming forks + 23 legacy): new feature methods for an ARN TableName (asserts the exact tag set: aws.table.arn and aws_account added, name tags and peer.service unchanged) and for a bare name with credentials that carry no account (asserts no account tags are invented).
  • S3BucketOwnerForkedTest (JUnit 5, 4 cases, in the payloadTaggingTest source set because its S3 model, 2.18.40, has ExpectedBucketOwner; the base suite pins S3 2.2.0 which predates the field): owner set and accepted, owner absent, owner malformed, owner rejected with 403 (no aws_account on the error span). Uses path-style addressing so the bucket is not resolved as somebucket.localhost, which works on hosts whose resolver maps *.localhost to loopback and not on CI runners.
  • AWS1ClientTest (24 + 24 forked + 17 legacy): new row with an ARN TableName.
  • spotlessApply clean on all touched modules.

How the end-to-end test was run

  • Environment: an EKS cluster (managed node group, EC2 nodes) running the Datadog Helm chart with the node Agent's trace receiver; a real DynamoDB table, Kinesis stream, SNS topic, Step Functions state machine, Lambda function, S3 bucket and RDS for PostgreSQL instance in the same account; IRSA credentials on the workload's service account.
  • Workload: a small Java 21 application (AWS SDK for Java v2 2.29.52, PostgreSQL JDBC 42.7.4) that once per cycle calls SNS Publish, Kinesis PutRecord, Step Functions StartExecution + DescribeExecution, Lambda Invoke, DynamoDB GetItem (by name and by ARN), S3 GetObject and a JDBC SELECT 1, all inside one traced method so the client spans share a trace.
  • Two deployments of the same container image, differing only in the dd-java-agent.jar copied into it: the released 1.66.0 tracer (before) and the jar built from this branch with ./gradlew :dd-java-agent:shadowJar (after). Same node pool, same DD_ENV, distinct DD_VERSION so the two runs are separable in Span Search.
  • Verification: the Datadog Span Search API (/api/v2/spans/events/search) was queried for each run's client spans and the per-span attributes compared key by key; the raw responses are retained. Where the change enables a join to the AWS integration metrics, the corresponding /api/v1/query was run against the same org and the returned scope recorded.

Live before/after on a real EKS workload

A Java 21 workload using AWS SDK v2 2.29.52 under IRSA on an EKS cluster ran GetItem against a real table twice per cycle (once by bare name, once by ARN) and GetObject with ExpectedBucketOwner against a real bucket, once with the stock dd-java-agent 1.66.0 and once with the jar from this branch, same image, same node pool. Spans as returned by the Span Search API (account masked). Captured on an earlier revision of this branch: the current revision leaves aws.table.name / tablename at the value given and does not synthesize aws.table.arn for a bare name; aws_account, which is what the join below uses, is unchanged.

DynamoDb.GetItem, bare TableName, IRSA credentials
  before: aws.table.name=datadog-context-trace-fixture
  after : aws.table.name=datadog-context-trace-fixture
          + aws_account=123456789012
  (account came from AwsCredentialsIdentity.accountId(), which the STS web identity provider populates)

DynamoDb.GetItem, TableName given as the ARN
  before: aws.table.name=arn:aws:dynamodb:us-east-1:123456789012:table/datadog-context-trace-fixture
          tablename=arn:aws:dynamodb:us-east-1:123456789012:table/datadog-context-trace-fixture
  after : aws.table.name=arn:aws:dynamodb:us-east-1:123456789012:table/datadog-context-trace-fixture
          tablename=arn:aws:dynamodb:us-east-1:123456789012:table/datadog-context-trace-fixture
          + aws.table.arn=arn:aws:dynamodb:us-east-1:123456789012:table/datadog-context-trace-fixture
          + aws_account=123456789012

S3.GetObject with ExpectedBucketOwner
  before: aws.bucket.name=<bucket>
  after : aws.bucket.name=<bucket>  + aws_account=123456789012

The join this enables, against the same org's AWS integration metrics:

sum:aws.dynamodb.successful_request_latency{tablename:datadog-context-trace-fixture} by {tablename,aws_account,region}
  -> scope: aws_account:123456789012,region:us-east-1,tablename:datadog-context-trace-fixture

Obfuscator note for reviewers

The first live run also emitted the S3 owner under a second key, aws.bucket.owner, and it arrived at Datadog as ?. The Agent's credit card obfuscator redacts any 12-digit value whose key is not on its allow list; aws_account is on that list, aws.bucket.owner was not. This PR therefore emits the account under aws_account only. Anyone adding a new account-bearing key in the tracer should expect the same behaviour (see also DataDog/datadog-agent#56242, which adds cloud.account.id and aws.account.id to that allow list).

Design notes

  • The DynamoDB enrichment is gated on the DynamoDB service name. Other request models that also carry a TableName member (Timestream, Keyspaces, Athena) keep the pre-existing plain aws.table.name / tablename tags and never receive an account.
  • Nothing is inferred into an ARN. Earlier revisions synthesized aws.table.arn for a bare name from the credentials account, the client Region and a Region-to-partition table; that table and the synthesized ARN are gone. aws_account alone is what the join with the AWS integration metrics needs.
  • An earlier revision could also decode the account from the access key ID behind an opt-in flag. Removed: the encoding is undocumented, the audience (SDK < 2.26) is shrinking, and a plausible-but-wrong account is worse than none. No configuration is added by this PR.
  • aws_account is only set where the account is provable: an ARN in the request, credentials whose account is asserted by the SDK, or an owner the caller asserted and S3 enforces. A bare S3 bucket name is deliberately not attributed to the caller, since bucket policies allow cross-account access by name.
  • Kinesis StreamName and Lambda FunctionName follow the same "bare name resolves in the requestor's account" rule and could get the same treatment; left for a follow-up to keep this change reviewable.

Contributor Checklist

  • Format the title according to the contribution guidelines
  • Assign the type: and (comp: or inst:) labels in addition to any other useful labels — suggested inst: aws sdk, inst: aws dynamodb, inst: aws s3, type: feature (external contributor, cannot set labels)
  • Avoid using close, fix, or any linking keywords when referencing an issue
  • Update the CODEOWNERS file on source file addition, migration, or deletion — the new files sit under dd-java-agent/instrumentation/aws-java/ (aws-java-common/ and aws-java-sdk-2.2/src/payloadTaggingTest/java/), covered by the existing @DataDog/apm-serverless directory entry
  • Update public documentation with any new configuration flags or behaviors — no new configuration; the only behavior change is two additional tags on DynamoDB and S3 client spans
  • Once approved, use merge queue to merge the PR

Suggested labels (cannot set as an external contributor): inst: aws sdk, inst: aws dynamodb, inst: aws s3, type: feature.

@pedramsafaei
pedramsafaei marked this pull request as ready for review September 23, 2026 16:03
@pedramsafaei
pedramsafaei requested review from a team as code owners September 23, 2026 16:03
@pedramsafaei
pedramsafaei requested review from PerfectSlayer, mhlidd and vandonr and removed request for a team September 23, 2026 16:03

@mhlidd mhlidd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM from SDK Capabilities POV

@pedramsafaei
pedramsafaei force-pushed the pedramsafaei/aws-account-identity-tags branch from 574076d to e1b9ef2 Compare September 24, 2026 07:12

@PerfectSlayer PerfectSlayer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looking good from platform POV. Thanks for the follow up changes!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks like we could use AWS SDK provided ARN parser for a good chunk of the work here, any reason to reimplement it ourselves here ?
https://docs.aws.amazon.com/java/api/latest/software/amazon/awssdk/arns/Arn.html

Also, if we want to keep our own implem, I think we should parse it once in an object. Here we end up checking several times if an ARN is valid for instance when we retrieve multiple values.

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.

The arns module is not a dependency of aws-core at the 2.2.0 floor this instrumentation compiles against (checked the 2.2.0 POM), and SDK v1 has no equivalent, so depending on it would break loading on older v2 and be unusable from the v1 module. Agreed on parsing once though pushed a new change that replaces the per-field helpers with an AwsArn value type parsed in a single pass, and both decorators call parse once.

tableName = resource.substring("table/".length());
int slash = tableName.indexOf('/');
if (slash > 0) {
tableName = tableName.substring(0, slash);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

doing the substring once with beginning and end would be more efficient (it'd save an intermediary string)

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.

Done. The extraction moved into AwsArn.dynamoDbTableName() and does one substring(begin, end).

String account = AwsAccountIdentity.accountFromArn(tableName);
String resource = AwsAccountIdentity.resourceFromArn(tableName);
if (resource != null && resource.startsWith("table/")) {
span.setTag(InstrumentationTags.AWS_TABLE_ARN, tableName);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

isn't it weird that if we found that the tableName is an ARN but the resource doesn't start with "table/" then we don't save it in the "AWS_TABLE_ARN" tag ?

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.

no it is intentional, but it deserved to be explicit. An ARN whose resource is not a table (a backup or export ARN, or a mistaken value) is not a table ARN, so tagging it as aws.table.arn would be wrong so in that case the raw value stays as the table name exactly as before this PR. In the new commit I pushed that decision lives in AwsArn.dynamoDbTableName() returning null, with a comment at both call sites.

}
String expectedBucketOwner = access.getExpectedBucketOwner(originalRequest);
if (AwsAccountIdentity.isAccountId(expectedBucketOwner)) {
// Asserted by the caller and enforced by S3 (403 on mismatch), so authoritative when set.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if it's authoritative when set, why do we need to check if the returned value is an account ID ?

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.

Fair, the comment was misleading. It is authoritative for requests S3 accepts, but the span is tagged before the response is known, and S3 rejects a malformed owner (400) or a wrong one (403). Without the check a request the application got wrong would stamp aws_account=not-an-account on its error span. Kept the check and reworded the comment in the new commit the "malformed owner" test should cover it.

Comment on lines +308 to +315
if (resource != null && resource.startsWith("table/")) {
name = resource.substring("table/".length());
int slash = name.indexOf('/');
if (slash > 0) {
// arn:...:table/<name>/index/<index> and similar sub-resources
name = name.substring(0, slash);
}
tableArn = tableName;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

looks like this duplicated part could go in the common helper

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.

done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

new tests should be written in java using jUnit, not in groovy (except if strongly interconnected with existing tests, but I don't think it's the case here ?)

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.

Done. Now the only Groovy changes are new rows in the existing Aws2ClientTest and AWS1ClientTest.


// Owning account of the addressed resource. aws_account matches the tag dd-trace-py sets and the
// dimension tag on the AWS integration metrics.
public static final String AWS_ACCOUNT = "aws_account";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why not with a dot ?

Suggested change
public static final String AWS_ACCOUNT = "aws_account";
public static final String AWS_ACCOUNT = "aws.account";

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.

Three reasons, all about the join. aws_account is the exact dimension tag on the aws.dynamodb.* and aws.s3.* integration metrics, so span and metric join without a rename and it is the key dd-trace-py already emits for the SNS and SQS account and also it is on the Agent credit-card obfuscator's allow list, whereas any other key carrying a 12-digit value is rewritten to ? at intake today (that happened live with aws.bucket.owner, see the obfuscator note in the description). aws.account would arrive as ? until DataDog/datadog-agent#56242 lands. Happy to also emit aws.account once that merges if you want the dotted form.

@pedramsafaei
pedramsafaei force-pushed the pedramsafaei/aws-account-identity-tags branch from e1b9ef2 to 383c14b Compare September 24, 2026 18:37

@vandonr vandonr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ok looks good (2 minor comments)
I'll need to duplicate this PR under my own account to be able to run the CI, I'll take care of this next week :)

*
* @return the 12-digit account, or {@code null} when the key does not have the expected shape.
*/
public static String accountFromAccessKeyId(final String accessKeyId) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it'd be nicer to untangle the base 32 parsing from actually getting the access key ID

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.

Done

}

/** {@code true} when the value has the shape of an ARN, without fully parsing it. */
public static boolean isArn(final String value) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we can remove this as it's only used in tests, and checking AwsArn.parse(...) != null is actually a stricter check

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.

Agreed, done

@pedramsafaei
pedramsafaei force-pushed the pedramsafaei/aws-account-identity-tags branch from 383c14b to a9e1606 Compare September 25, 2026 15:53
@pedramsafaei
pedramsafaei force-pushed the pedramsafaei/aws-account-identity-tags branch from a9e1606 to 2b35c67 Compare September 28, 2026 16:01
DynamoDB and S3 client spans named the table or bucket but never the
account that owns it, so two accounts each holding an "orders" table
produced indistinguishable spans. The owning account is available to
the tracer without any extra call in three situations, and this change
uses all of them:

DynamoDB, TableName given as an ARN. The ARN carries partition, Region
and account. Spans now get aws.table.arn and aws_account, and
aws.table.name / tablename / peer.service carry the bare table name
instead of the raw ARN.

DynamoDB, bare TableName. DynamoDB documents that a bare name is
resolved in the requestor's own account ("If you only provide the table
name parameter instead of a complete ARN, the API operation will be
performed on the table in the account to which the requestor belongs"),
so the account owning the signing credentials is the table owner. On
SDK v2 the account is read from the credentials object
(AwsCredentialsIdentity.accountId(), SDK 2.26+, populated by the STS,
SSO, profile, process and container credential providers) through a
reflective, per-class cached getter so the instrumentation still loads
against 2.2.0. Spans get aws_account and a synthesized aws.table.arn
built from the client Region, account and table name. SDK v1 does not
expose the signing credentials to request handlers, so v1 only handles
the ARN form. The enrichment is gated on the DynamoDB service so
other request models with a TableName member (Timestream, Keyspaces)
keep the plain table name tags.

S3, ExpectedBucketOwner. When the caller sets it, S3 rejects the
request with 403 on a mismatch, so it names the owner whenever the
request succeeds. Spans get aws_account on both SDKs, applied from the
successful response so a rejected owner is never tagged.

For older v2 SDKs whose credentials carry no account, the account can
optionally be decoded from the access key ID, which encodes it in its
trailing base32 characters for keys issued since March 2019 (older keys
carry no account and are rejected by a format marker check). That
encoding is not part of the documented AWS API surface, so it is behind
dd.trace.aws.account.from.access.key.enabled
(DD_TRACE_AWS_ACCOUNT_FROM_ACCESS_KEY_ENABLED), default false.

aws_account is the tag name dd-trace-py already uses for the SNS and
SQS account it derives from TopicArn and QueueUrl, and the dimension
tag on the aws.dynamodb.* integration metrics, so the span joins to the
metrics for the same table without translation. It is also on the
allow list of the Agent's credit card obfuscator; a 12-digit account
under any other key is redacted to "?" by default, which is why no
second account-bearing key is introduced.

ARNs are parsed once into a new AwsArn value type (the SDK's own
software.amazon.awssdk.arns.Arn is not available at the 2.2.0 floor nor
to SDK v1), which also owns the table-name extraction shared by both
decorators. Partition mapping, table ARN assembly and access key decoding
live in AwsAccountIdentity. Both sit in the aws-java-common module and
are registered as injected helper classes by both SDK instrumentations.
@pedramsafaei
pedramsafaei force-pushed the pedramsafaei/aws-account-identity-tags branch from 2b35c67 to 9e8bb14 Compare September 29, 2026 19:46
vandonr added a commit that referenced this pull request Sep 30, 2026
Use GenericClassValue for the optional accountId method handle so credentials classes and their application class loaders can be unloaded. Retain compatibility with the SDK 2.2.0 floor and cover present, absent, malformed, and failing providers.

Adapted from Pedram Safaei's changes in PR #12602 (9e8bb14).
Review: #12665 (comment)

Co-authored-by: Pedram Safaei <pedramsafaei@users.noreply.github.com>
vandonr added a commit that referenced this pull request Sep 30, 2026
Keep the credentials-derived aws_account for bare table names, but only emit aws.table.arn from request ARNs. Remove the region-to-partition table and ARN builder, and preserve service-gating regression coverage.

Adapted from Pedram Safaei's changes in PR #12602 (9e8bb14).
Review: #12665 (comment)

Co-authored-by: Pedram Safaei <pedramsafaei@users.noreply.github.com>
vandonr added a commit that referenced this pull request Sep 30, 2026
Remove the undocumented access-key decoder and its opt-in configuration, including configuration metadata and decoder tests. Older SDKs without accountId now leave the credentials account absent.

Adapted from Pedram Safaei's changes in PR #12602 (9e8bb14).
Review: #12665 (comment)

Co-authored-by: Pedram Safaei <pedramsafaei@users.noreply.github.com>
vandonr added a commit that referenced this pull request Sep 30, 2026
Rethrow VirtualMachineError and ThreadDeath while treating other provider and lookup failures, including LinkageError, as an unavailable account. Include method-handle lookup inside the error boundary and cover fatal and recoverable provider errors.

Adapted from Pedram Safaei's changes in PR #12602 (9e8bb14).
Review: #12665 (comment)

Co-authored-by: Pedram Safaei <pedramsafaei@users.noreply.github.com>
vandonr added a commit that referenced this pull request Sep 30, 2026
Keep aws.table.name, tablename, and peer.service unchanged for ARN TableName values on both SDK versions. Retain validation before adding aws.table.arn, reject other services and empty table names, and cover the behavior with unit and integration tests.

Adapted from Pedram Safaei's changes in PR #12602 (9e8bb14).
Review: #12665 (comment)

Co-authored-by: Pedram Safaei <pedramsafaei@users.noreply.github.com>
pedramsafaei and others added 3 commits October 20, 2026 18:54
Resolve conflicts with the instrumentation-helper and tag-registry changes
on master:

- AwsSdkModule (SDK v1 and v2): drop the manually listed helperClassNames();
  helper classes are now discovered automatically, so AwsAccountIdentity and
  AwsArn no longer need to be listed.
- GetterAccess and AwsSdkClientDecorator (SDK v1): keep both the existing
  ExpectedBucketOwner getter / aws_account handling and master's new
  StateMachineArn, ExecutionArn and FunctionName getters and Lambda identity
  tagging.
- InstrumentationTags: keep both the aws_account / aws.table.arn constants and
  master's new ARN/function constants.
- Register aws.table.arn and aws_account in tag-conventions.yaml so the new
  tag constants are covered by the generated tag registry.
Declaring aws_account under both aws.s3 and aws.dynamodb (both client-direction
span types sharing the aws.client parent) makes the tag-registry generator fail:
a tag may be declared only once per direction. Declare it once on the shared
aws.client parent so every AWS service span type inherits the same tag identity.
A tag declared on two concrete span types that share a parent direction
has no single identity, so the generator must reject it; declaring it
once on the shared parent lets both siblings inherit one tag. Cover both
the rejection and the shared-parent resolution.

This branch has not been deployed

No deployments
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.

4 participants