Skip to content

[BUG]: aws-sdk: Default service plugin never subscribes — services outside the known list (STS, Secrets Manager, …) produce no spans #10444

Description

@aakashkulkarni

Tracer Version(s)

5.109.0 and 6.16.0 (reproduced on both)

Node.js Version(s)

24.14.0

Bug Report

AWS SDK v3 calls to any service that is not in the aws-sdk instrumentation's known list — e.g. STS AssumeRole / GetCallerIdentity, Secrets Manager GetSecretValue — never produce an aws.request span. Only the underlying http.request appears. SQS / SNS / S3 / DynamoDB etc. work as expected.

Cause: the instrumentation and the plugin disagree on which channel unknown services use.

  • packages/datadog-instrumentations/src/aws-sdk.js — getChannelSuffix() returns 'default' for any service not in KNOWN_CHANNEL_SUFFIXES (or CHANNEL_SUFFIX_ALIASES), so wrapSmithySend publishes on apm:aws:request:start:default.
  • packages/datadog-plugin-aws-sdk/src/services/default.js is class Default extends BaseAwsSdkPlugin {} with no static id, so it inherits the base class's static id = 'aws'.
  • packages/datadog-plugin-aws-sdk/src/base.js — get serviceIdentifier() is this.constructor.id.toLowerCase(), and the constructor subscribes to apm:aws:request:start:${this.serviceIdentifier}. The Default plugin therefore subscribes to …:aws.

Nothing subscribes to …:default, so the publish goes nowhere. Confirmed at runtime: dc.channel('apm:aws:request:start:default').hasSubscribers === false while …:aws and …:sqs are true.

Suggested fix: static id = 'default' on Default (or publish unknown services on :aws), plus a test that a service outside the known list yields an aws.request span.

Reproduction Code

// package.json: { "type": "module" }; deps: dd-trace, @aws-sdk/client-sqs, @aws-sdk/client-sts
// run: node --import dd-trace/initialize.mjs repro.mjs
import dc from 'node:diagnostics_channel';
import tracer from 'dd-trace';
import { SQSClient, GetQueueUrlCommand } from '@aws-sdk/client-sqs';
import { STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts';

console.log('subscribers default/aws/sqs:',
  dc.channel('apm:aws:request:start:default').hasSubscribers,
  dc.channel('apm:aws:request:start:aws').hasSubscribers,
  dc.channel('apm:aws:request:start:sqs').hasSubscribers);

// Names of the spans created while fn runs (in-process; no Agent needed).
const spans = async (fn) => {
  let names = [];
  await tracer.trace('p', async (s) => {
    const t = s.context()._trace, before = t.started.length;
    try { await fn(); } catch {}
    names = t.started.slice(before).map((x) => x.context()._name);
  });
  return names;
};

const dead = 'http://127.0.0.1:9';
const credentials = { accessKeyId: 'x', secretAccessKey: 'y' };
console.log('SQS:', await spans(() => new SQSClient({ region: 'us-east-1', endpoint: dead, credentials, maxAttempts: 1 })
  .send(new GetQueueUrlCommand({ QueueName: 'q' }))));
console.log('STS:', await spans(() => new STSClient({ region: 'us-east-1', endpoint: dead, credentials, maxAttempts: 1 })
  .send(new GetCallerIdentityCommand({}))));
setTimeout(() => process.exit(0), 100);

Output on 6.16.0 (identical on 5.109.0):

subscribers default/aws/sqs: false true true
SQS: [ 'aws.request', 'http.request', 'tcp.connect' ]
STS: [ 'http.request', 'tcp.connect' ]

Error Logs

No response

Tracer Config

DD_TRACE_ENABLED=true DD_TRACE_AGENT_URL=http://127.0.0.1:9 — no Agent is needed to reproduce; spans are observed in-process.

Operating System

macOS (Darwin 27); not platform-specific.

Bundling

No bundling

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions