Is your feature request related to a problem? Please describe.
The AWS SDK v2 instrumentation currently traces Amazon RDS Data API calls as generic AWS RPC client spans. For example, ExecuteStatement produces a span similar to:
name: RdsData.ExecuteStatement
kind: CLIENT
rpc.system: aws-api
rpc.service: RdsData
rpc.method: ExecuteStatement
This preserves the AWS operation identity, request ID, HTTP attributes, and error information, but does not describe the SQL operation using the database semantic conventions. In particular, the span has no:
db.system.name
db.namespace
db.query.text
db.query.summary
db.operation.batch.size
Applications using the RDS Data API therefore do not get the query naming, sanitization, database metrics, or analysis available when the same SQL is executed through the JDBC instrumentation.
Describe the solution you'd like
Enrich the existing AWS SDK client span for RDS Data API SQL operations using the shared SQL instrumentation APIs from opentelemetry-instrumentation-api-incubator, following the same abstraction boundary as JDBC:
SqlClientAttributesGetter
SqlClientAttributesExtractor
DbClientSpanNameExtractor
DbClientMetrics
- the database client exception event extractor
The initial implementation should cover the currently supported SQL execution operations:
ExecuteStatement
BatchExecuteStatement
Whether to include the deprecated ExecuteSql operation in the initial implementation is an open question described under Additional context.
Transaction-control operations should remain generic AWS RPC spans in the initial change:
BeginTransaction
CommitTransaction
RollbackTransaction
These operations do not contain SQL text, and JDBC transaction spans are currently experimental.
Enrich the existing AWS span
The implementation should enrich the existing AWS SDK span rather than create a nested database span. One RDS Data API request represents one logical remote database operation, so a second child span would duplicate the operation and its duration. This is also consistent with the AWS SDK DynamoDB instrumentation, which adds database attributes and metrics to the existing AWS SDK span.
The existing AWS RPC, request ID, HTTP, URL, and error attributes should remain on the span.
Map request data through AWS SDK core APIs
The RDS Data API request can be inspected through SdkRequest.getValueForField without linking against generated rdsdata classes at runtime:
| Database concept |
RDS Data API request field |
| Raw query text |
sql |
Deprecated ExecuteSql query text |
sqlStatements |
| Database namespace |
database |
| Batch size |
number of entries in parameterSets |
Parameterized ExecuteStatement |
non-empty parameters |
Parameterized BatchExecuteStatement |
at least one non-empty nested parameter set |
The implementation should not capture:
- SQL parameter values
- secret ARNs
- resource ARNs as database addresses
- transaction IDs
- database users or connection strings
The schema request field should initially be ignored. It is unsupported for the modern operations and is ambiguous across Aurora MySQL and Aurora PostgreSQL.
Use a conservative database system and SQL dialect
The request does not identify whether the target cluster uses Aurora MySQL or Aurora PostgreSQL, and the resource ARN does not encode the engine. The proposed value is therefore:
db.system.name = other_sql
other_sql matches the semantic-convention definition for a target known to use SQL when the concrete DBMS product is unavailable to the instrumentation. RDS Data is a transport rather than a DBMS, so an RDS Data-specific database-system identifier should not be introduced.
The SQL dialect should use DOUBLE_QUOTES_ARE_STRING_LITERALS, as JDBC does when the database system is unknown. This avoids potentially exposing double-quoted sensitive literals, at the cost of occasionally sanitizing quoted identifiers.
Reuse JDBC-aligned query sanitization and summarization
The shared SQL extractor should retain its default sanitization behavior:
- Non-parameterized SQL is sanitized.
- Parameterized SQL retains its query template under stable database semantic conventions.
- Parameter values are never captured.
db.query.summary is generated by the same SQL analyzer used by JDBC.
For example:
SELECT * FROM customers WHERE email = 'person@example.com'
would produce approximately:
db.query.text: SELECT * FROM customers WHERE email = ?
db.query.summary: SELECT customers
while:
SELECT * FROM customers WHERE email = :email
with a corresponding RDS Data API parameter would retain the parameterized query text without recording the value of :email.
SqlClientAttributesExtractorBuilder.setSingleOperationAndCollection(true) should not be enabled. Aurora MySQL and PostgreSQL support SQL that references multiple operations or collections in a single non-batch query, so deriving db.operation.name or db.collection.name from arbitrary SQL would conflict with the SQL semantic-convention guidance. This also matches the current JDBC instrumentation. The generated db.query.summary provides the low-cardinality operation and target description instead.
Model BatchExecuteStatement using parameter-set count
For BatchExecuteStatement, each parameter set represents one database operation. The shared database instrumentation should therefore model:
| Parameter-set count |
Result |
0 |
Empty batch; db.operation.batch.size = 0 |
1 |
Single operation; no batch-size attribute or BATCH prefix |
2+ |
Batch operation; emit db.operation.batch.size and prefix the summary with BATCH |
For example, two parameter sets executing:
INSERT INTO customers (id) VALUES (:id)
would produce:
db.query.summary: BATCH INSERT customers
db.operation.batch.size: 2
Preserve the existing AWS operation span name in legacy-only mode
Using DbClientSpanNameExtractor unconditionally would rename existing spans and could disrupt dashboards or alerts based on AWS operation names. The proposed compatibility behavior is:
| Database semantic-convention mode |
Span name |
| Legacy-only (current 2.x default) |
Preserve RdsData.<AWS operation> |
Stable-only (database) |
Use db.query.summary |
Dual emit (database/dup) |
Use the stable query-summary name |
Legacy-only mode would still gain JDBC-aligned legacy database attributes such as sanitized db.statement, db.operation, db.name, and db.system through the shared extractor.
For example, stable database semantic conventions could change an ExecuteStatement span from:
to:
Add database metrics and error semantics
The enriched instrumenter should add:
db.client.operation.duration through DbClientMetrics
- database client error semantics and exception event naming
No database-native status code appears to be available from the RDS Data API response. error.type should therefore fall back to the relevant AWS SDK exception class rather than using the HTTP status code as a database status code.
Avoid an RDS Data runtime dependency
Production code should continue depending only on AWS SDK core APIs. Request recognition can use the existing string-based AwsSdkRequest mechanism with exact suffixes:
rdsdata.model.ExecuteStatementRequest
rdsdata.model.BatchExecuteStatementRequest
rdsdata.model.ExecuteSqlRequest
The rdsdata.model. prefix is important because DynamoDB has operations with the same request class names for PartiQL. The generated RDS Data SDK module should only be a test dependency. AWS SDK v2 2.5.54 is the first release containing both ExecuteStatement and BatchExecuteStatement.
Test without live AWS infrastructure
The tests should not require a live RDS or Aurora instance, Docker, or LocalStack. They can follow the existing AWS SDK test pattern by configuring the generated RDS Data client with a local MockWebServerExtension endpoint and static test credentials.
This exercises SDK request marshalling, signing, execution interceptors, sync and async behavior, response handling, and emitted telemetry without making AWS calls. The tests would validate instrumentation behavior rather than whether Aurora accepts or executes a particular SQL statement.
Use isolated AWS SDK 2.5.54+ test suites so that adding the RDS Data dependency does not transitively raise the repository's AWS SDK 2.2.0 floor for existing tests. Run the suites in legacy-only and stable-only database-semconv modes for library instrumentation, javaagent instrumentation, and library autoconfigure.
Test coverage should include:
- synchronous and asynchronous clients
ExecuteStatement and BatchExecuteStatement
ExecuteSql if included in the accepted scope
- legacy-only AWS operation names and stable query-summary names
- literal sanitization and parameterized query text
- batch sizes
0, 1, and 2
- database namespace extraction
- stable database metrics
- errors and
error.type
- retained AWS RPC, HTTP, and request ID attributes
- absence of parameter values, secrets, transaction IDs, and ARNs
- transaction-control operations remaining generic AWS spans
Proposed implementation outline
- Add an RDS Data request type and exact mappings for the accepted SQL operations.
- Add an AWS SDK-core-only
SqlClientAttributesGetter for RDS Data requests.
- Add an RDS Data instrumenter using the shared SQL extractor, name extractor, metrics, and database exception conventions.
- Route only the selected SQL request classes to that instrumenter.
- Preserve transaction and other RDS Data API calls as generic AWS spans.
- Add isolated AWS SDK
2.5.54+ test suites for library, javaagent, and library autoconfigure.
- Run the tests under legacy-only and stable-only database semantic conventions at minimum and latest AWS SDK versions.
Describe alternatives you've considered
Create a nested database span
This would preserve the outer AWS RPC span unchanged, but it would represent one logical RDS Data API operation twice and duplicate its duration. There is no independent lower-level database operation observable to the client, so enriching the existing span is more accurate.
Add instrumentation to an individual RDS Data API wrapper library
This could provide SQL spans for that library's consumers, but would not help other AWS SDK users and would duplicate parsing, sanitization, and semantic-convention behavior already available in the upstream instrumentation.
Implement a separate SQL parser or regular-expression-based span naming
This would risk diverging from JDBC on comments, quoted identifiers, joins, CTEs, nested queries, multi-statement SQL, sanitization, and summary cardinality. Reusing the shared SQL analyzer keeps the behavior aligned.
Rename spans unconditionally
This would provide query-summary names in all modes, but would break existing dashboards and alerts that use RdsData.<operation>. Restricting the rename to stable database semantic conventions provides an explicit migration path.
Infer the Aurora engine from the resource ARN
Aurora cluster ARNs do not encode whether the engine is MySQL or PostgreSQL. Determining the engine would require an additional RDS API request or user-provided ARN-to-engine configuration, adding latency, permissions, caching, and configuration complexity. other_sql is a safer default.
Enrich transaction-control operations in the same change
These requests have no SQL text, and the comparable JDBC transaction instrumentation is experimental. Keeping them generic avoids expanding the initial semantic-convention scope.
Additional context
Open questions
-
Is other_sql the appropriate db.system.name?
The instrumentation cannot determine whether the request targets Aurora MySQL or Aurora PostgreSQL without an additional API call or user-provided mapping. other_sql appears preferable to inventing an RDS Data-specific DBMS identifier because RDS Data is a transport.
-
Should query-summary span naming be limited to stable database semantic conventions?
The proposal preserves RdsData.<operation> in legacy-only mode and uses the SQL summary in stable-only and dual-emission modes. Maintainer feedback on this compatibility policy would be useful.
-
Should the deprecated ExecuteSql operation be included?
ExecuteSql has existed since AWS SDK v2 2.1.1, but is deprecated, supported only for Aurora Serverless v1, and replaced by ExecuteStatement and BatchExecuteStatement.
It can technically use the same instrumentation by reading sqlStatements and passing the complete semicolon-separated value to the shared SQL analyzer. The analyzer already handles multi-statement text and can produce a sanitized query and a summary such as:
SELECT customers; UPDATE orders
It should be treated as one multi-statement query, not as a batch. Possible scopes are:
- include it in the initial change for existing Serverless v1 users;
- limit the initial change to the two supported operations and add it separately;
- intentionally leave it as a generic AWS RPC span.
-
Should transaction operations remain generic in the initial change?
The proposal leaves them unchanged until there is agreement on whether RDS Data API transaction spans should follow JDBC's experimental transaction instrumentation.
References
Disclaimer
Yes I used AI to analyse the existing JDBC instrumentation and devise this approach for enriching the RDS Data API.
Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.
Is your feature request related to a problem? Please describe.
The AWS SDK v2 instrumentation currently traces Amazon RDS Data API calls as generic AWS RPC client spans. For example,
ExecuteStatementproduces a span similar to:This preserves the AWS operation identity, request ID, HTTP attributes, and error information, but does not describe the SQL operation using the database semantic conventions. In particular, the span has no:
db.system.namedb.namespacedb.query.textdb.query.summarydb.operation.batch.sizeApplications using the RDS Data API therefore do not get the query naming, sanitization, database metrics, or analysis available when the same SQL is executed through the JDBC instrumentation.
Describe the solution you'd like
Enrich the existing AWS SDK client span for RDS Data API SQL operations using the shared SQL instrumentation APIs from
opentelemetry-instrumentation-api-incubator, following the same abstraction boundary as JDBC:SqlClientAttributesGetterSqlClientAttributesExtractorDbClientSpanNameExtractorDbClientMetricsThe initial implementation should cover the currently supported SQL execution operations:
ExecuteStatementBatchExecuteStatementWhether to include the deprecated
ExecuteSqloperation in the initial implementation is an open question described under Additional context.Transaction-control operations should remain generic AWS RPC spans in the initial change:
BeginTransactionCommitTransactionRollbackTransactionThese operations do not contain SQL text, and JDBC transaction spans are currently experimental.
Enrich the existing AWS span
The implementation should enrich the existing AWS SDK span rather than create a nested database span. One RDS Data API request represents one logical remote database operation, so a second child span would duplicate the operation and its duration. This is also consistent with the AWS SDK DynamoDB instrumentation, which adds database attributes and metrics to the existing AWS SDK span.
The existing AWS RPC, request ID, HTTP, URL, and error attributes should remain on the span.
Map request data through AWS SDK core APIs
The RDS Data API request can be inspected through
SdkRequest.getValueForFieldwithout linking against generatedrdsdataclasses at runtime:sqlExecuteSqlquery textsqlStatementsdatabaseparameterSetsExecuteStatementparametersBatchExecuteStatementThe implementation should not capture:
The
schemarequest field should initially be ignored. It is unsupported for the modern operations and is ambiguous across Aurora MySQL and Aurora PostgreSQL.Use a conservative database system and SQL dialect
The request does not identify whether the target cluster uses Aurora MySQL or Aurora PostgreSQL, and the resource ARN does not encode the engine. The proposed value is therefore:
other_sqlmatches the semantic-convention definition for a target known to use SQL when the concrete DBMS product is unavailable to the instrumentation. RDS Data is a transport rather than a DBMS, so an RDS Data-specific database-system identifier should not be introduced.The SQL dialect should use
DOUBLE_QUOTES_ARE_STRING_LITERALS, as JDBC does when the database system is unknown. This avoids potentially exposing double-quoted sensitive literals, at the cost of occasionally sanitizing quoted identifiers.Reuse JDBC-aligned query sanitization and summarization
The shared SQL extractor should retain its default sanitization behavior:
db.query.summaryis generated by the same SQL analyzer used by JDBC.For example:
would produce approximately:
while:
with a corresponding RDS Data API parameter would retain the parameterized query text without recording the value of
:email.SqlClientAttributesExtractorBuilder.setSingleOperationAndCollection(true)should not be enabled. Aurora MySQL and PostgreSQL support SQL that references multiple operations or collections in a single non-batch query, so derivingdb.operation.nameordb.collection.namefrom arbitrary SQL would conflict with the SQL semantic-convention guidance. This also matches the current JDBC instrumentation. The generateddb.query.summaryprovides the low-cardinality operation and target description instead.Model
BatchExecuteStatementusing parameter-set countFor
BatchExecuteStatement, each parameter set represents one database operation. The shared database instrumentation should therefore model:0db.operation.batch.size = 01BATCHprefix2+db.operation.batch.sizeand prefix the summary withBATCHFor example, two parameter sets executing:
would produce:
Preserve the existing AWS operation span name in legacy-only mode
Using
DbClientSpanNameExtractorunconditionally would rename existing spans and could disrupt dashboards or alerts based on AWS operation names. The proposed compatibility behavior is:RdsData.<AWS operation>database)db.query.summarydatabase/dup)Legacy-only mode would still gain JDBC-aligned legacy database attributes such as sanitized
db.statement,db.operation,db.name, anddb.systemthrough the shared extractor.For example, stable database semantic conventions could change an
ExecuteStatementspan from:to:
Add database metrics and error semantics
The enriched instrumenter should add:
db.client.operation.durationthroughDbClientMetricsNo database-native status code appears to be available from the RDS Data API response.
error.typeshould therefore fall back to the relevant AWS SDK exception class rather than using the HTTP status code as a database status code.Avoid an RDS Data runtime dependency
Production code should continue depending only on AWS SDK core APIs. Request recognition can use the existing string-based
AwsSdkRequestmechanism with exact suffixes:The
rdsdata.model.prefix is important because DynamoDB has operations with the same request class names for PartiQL. The generated RDS Data SDK module should only be a test dependency. AWS SDK v22.5.54is the first release containing bothExecuteStatementandBatchExecuteStatement.Test without live AWS infrastructure
The tests should not require a live RDS or Aurora instance, Docker, or LocalStack. They can follow the existing AWS SDK test pattern by configuring the generated RDS Data client with a local
MockWebServerExtensionendpoint and static test credentials.This exercises SDK request marshalling, signing, execution interceptors, sync and async behavior, response handling, and emitted telemetry without making AWS calls. The tests would validate instrumentation behavior rather than whether Aurora accepts or executes a particular SQL statement.
Use isolated AWS SDK
2.5.54+ test suites so that adding the RDS Data dependency does not transitively raise the repository's AWS SDK2.2.0floor for existing tests. Run the suites in legacy-only and stable-only database-semconv modes for library instrumentation, javaagent instrumentation, and library autoconfigure.Test coverage should include:
ExecuteStatementandBatchExecuteStatementExecuteSqlif included in the accepted scope0,1, and2error.typeProposed implementation outline
SqlClientAttributesGetterfor RDS Data requests.2.5.54+ test suites for library, javaagent, and library autoconfigure.Describe alternatives you've considered
Create a nested database span
This would preserve the outer AWS RPC span unchanged, but it would represent one logical RDS Data API operation twice and duplicate its duration. There is no independent lower-level database operation observable to the client, so enriching the existing span is more accurate.
Add instrumentation to an individual RDS Data API wrapper library
This could provide SQL spans for that library's consumers, but would not help other AWS SDK users and would duplicate parsing, sanitization, and semantic-convention behavior already available in the upstream instrumentation.
Implement a separate SQL parser or regular-expression-based span naming
This would risk diverging from JDBC on comments, quoted identifiers, joins, CTEs, nested queries, multi-statement SQL, sanitization, and summary cardinality. Reusing the shared SQL analyzer keeps the behavior aligned.
Rename spans unconditionally
This would provide query-summary names in all modes, but would break existing dashboards and alerts that use
RdsData.<operation>. Restricting the rename to stable database semantic conventions provides an explicit migration path.Infer the Aurora engine from the resource ARN
Aurora cluster ARNs do not encode whether the engine is MySQL or PostgreSQL. Determining the engine would require an additional RDS API request or user-provided ARN-to-engine configuration, adding latency, permissions, caching, and configuration complexity.
other_sqlis a safer default.Enrich transaction-control operations in the same change
These requests have no SQL text, and the comparable JDBC transaction instrumentation is experimental. Keeping them generic avoids expanding the initial semantic-convention scope.
Additional context
Open questions
Is
other_sqlthe appropriatedb.system.name?The instrumentation cannot determine whether the request targets Aurora MySQL or Aurora PostgreSQL without an additional API call or user-provided mapping.
other_sqlappears preferable to inventing an RDS Data-specific DBMS identifier because RDS Data is a transport.Should query-summary span naming be limited to stable database semantic conventions?
The proposal preserves
RdsData.<operation>in legacy-only mode and uses the SQL summary in stable-only and dual-emission modes. Maintainer feedback on this compatibility policy would be useful.Should the deprecated
ExecuteSqloperation be included?ExecuteSqlhas existed since AWS SDK v22.1.1, but is deprecated, supported only for Aurora Serverless v1, and replaced byExecuteStatementandBatchExecuteStatement.It can technically use the same instrumentation by reading
sqlStatementsand passing the complete semicolon-separated value to the shared SQL analyzer. The analyzer already handles multi-statement text and can produce a sanitized query and a summary such as:It should be treated as one multi-statement query, not as a batch. Possible scopes are:
Should transaction operations remain generic in the initial change?
The proposal leaves them unchanged until there is agreement on whether RDS Data API transaction spans should follow JDBC's experimental transaction instrumentation.
References
ExecuteSqlAPIDisclaimer
Yes I used AI to analyse the existing JDBC instrumentation and devise this approach for enriching the RDS Data API.
Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding
+1orme too, to help us triage it. Learn more here.