diff --git a/lib/datadog/core/configuration.rb b/lib/datadog/core/configuration.rb index a08e40ae6a2..3442f9d9036 100644 --- a/lib/datadog/core/configuration.rb +++ b/lib/datadog/core/configuration.rb @@ -208,7 +208,11 @@ def components(allow_initialization: true) # Used internally to ensure a clean environment between test runs. def reset! safely_synchronize do |write_components| - @components.shutdown! if components? + if components? + @components.shutdown! + @temp_logger = nil # Reset to ensure instance and log level are reset for next run + end + write_components.call(nil) configuration.reset! end diff --git a/lib/datadog/tracing/contrib/aws/ext.rb b/lib/datadog/tracing/contrib/aws/ext.rb index fb5948db13c..2827596088c 100644 --- a/lib/datadog/tracing/contrib/aws/ext.rb +++ b/lib/datadog/tracing/contrib/aws/ext.rb @@ -18,7 +18,17 @@ module Ext TAG_OPERATION = 'aws.operation'.freeze TAG_OPERATION_COMMAND = 'command'.freeze TAG_PATH = 'path'.freeze - TAG_REGION = 'aws.region'.freeze + TAG_AWS_REGION = 'aws.region'.freeze + TAG_REGION = 'region'.freeze + TAG_AWS_SERVICE = 'aws_service'.freeze + TAG_AWS_ACCOUNT = 'aws_account'.freeze + TAG_QUEUE_NAME = 'queuename'.freeze + TAG_TOPIC_NAME = 'topicname'.freeze + TAG_TABLE_NAME = 'tablename'.freeze + TAG_STREAM_NAME = 'streamname'.freeze + TAG_RULE_NAME = 'rulename'.freeze + TAG_STATE_MACHINE_NAME = 'statemachinename'.freeze + TAG_BUCKET_NAME = 'bucketname'.freeze end end end diff --git a/lib/datadog/tracing/contrib/aws/instrumentation.rb b/lib/datadog/tracing/contrib/aws/instrumentation.rb index afd587dc547..aa2e841272d 100644 --- a/lib/datadog/tracing/contrib/aws/instrumentation.rb +++ b/lib/datadog/tracing/contrib/aws/instrumentation.rb @@ -33,6 +33,12 @@ def annotate!(span, context) span.span_type = Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND span.name = Ext::SPAN_COMMAND span.resource = context.safely(:resource) + aws_service = span.resource.split('.')[0] + span.set_tag(Ext::TAG_AWS_SERVICE, aws_service) + params = context.safely(:params) + if (handler = Datadog::Tracing::Contrib::Aws::SERVICE_HANDLERS[aws_service]) + handler.add_tags(span, params) + end span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_CLIENT) @@ -55,6 +61,7 @@ def annotate!(span, context) span.set_tag(Ext::TAG_AGENT, Ext::TAG_DEFAULT_AGENT) span.set_tag(Ext::TAG_OPERATION, context.safely(:operation)) span.set_tag(Ext::TAG_REGION, context.safely(:region)) + span.set_tag(Ext::TAG_AWS_REGION, context.safely(:region)) span.set_tag(Ext::TAG_PATH, context.safely(:path)) span.set_tag(Ext::TAG_HOST, context.safely(:host)) span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_METHOD, context.safely(:http_method)) diff --git a/lib/datadog/tracing/contrib/aws/parsed_context.rb b/lib/datadog/tracing/contrib/aws/parsed_context.rb index 4e828241652..95cb44c3c26 100644 --- a/lib/datadog/tracing/contrib/aws/parsed_context.rb +++ b/lib/datadog/tracing/contrib/aws/parsed_context.rb @@ -20,6 +20,10 @@ def operation context.operation_name end + def params + context.params + end + def status_code context.http_response.status_code end diff --git a/lib/datadog/tracing/contrib/aws/service/base.rb b/lib/datadog/tracing/contrib/aws/service/base.rb new file mode 100644 index 00000000000..c6b496c1df7 --- /dev/null +++ b/lib/datadog/tracing/contrib/aws/service/base.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Datadog + module Tracing + module Contrib + module Aws + module Service + # Base class for all AWS service-specific tag handlers. + class Base + def add_tags(span, params); end + end + end + end + end + end +end diff --git a/lib/datadog/tracing/contrib/aws/service/dynamodb.rb b/lib/datadog/tracing/contrib/aws/service/dynamodb.rb new file mode 100644 index 00000000000..d51210e115d --- /dev/null +++ b/lib/datadog/tracing/contrib/aws/service/dynamodb.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Datadog + module Tracing + module Contrib + module Aws + module Service + # DynamoDB tag handlers. + class DynamoDB < Base + def add_tags(span, params) + table_name = params[:table_name] + span.set_tag(Aws::Ext::TAG_TABLE_NAME, table_name) + end + end + end + end + end + end +end diff --git a/lib/datadog/tracing/contrib/aws/service/eventbridge.rb b/lib/datadog/tracing/contrib/aws/service/eventbridge.rb new file mode 100644 index 00000000000..484e2f1d7b9 --- /dev/null +++ b/lib/datadog/tracing/contrib/aws/service/eventbridge.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Datadog + module Tracing + module Contrib + module Aws + module Service + # EventBridge tag handlers. + class EventBridge < Base + def add_tags(span, params) + rule_name = params[:name] || params[:rule] + span.set_tag(Aws::Ext::TAG_RULE_NAME, rule_name) + end + end + end + end + end + end +end diff --git a/lib/datadog/tracing/contrib/aws/service/kinesis.rb b/lib/datadog/tracing/contrib/aws/service/kinesis.rb new file mode 100644 index 00000000000..ef48cfb515f --- /dev/null +++ b/lib/datadog/tracing/contrib/aws/service/kinesis.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module Datadog + module Tracing + module Contrib + module Aws + module Service + # Kinesis tag handlers. + class Kinesis < Base + def add_tags(span, params) + stream_arn = params[:stream_arn] + stream_name = params[:stream_name] + + if stream_arn + # example stream_arn: arn:aws:kinesis:us-east-1:123456789012:stream/my-stream + parts = stream_arn.split(':') + stream_name = parts[-1].split('/')[-1] + aws_account = parts[-2] + span.set_tag(Aws::Ext::TAG_AWS_ACCOUNT, aws_account) + end + + span.set_tag(Aws::Ext::TAG_STREAM_NAME, stream_name) + end + end + end + end + end + end +end diff --git a/lib/datadog/tracing/contrib/aws/service/s3.rb b/lib/datadog/tracing/contrib/aws/service/s3.rb new file mode 100644 index 00000000000..297ac00370d --- /dev/null +++ b/lib/datadog/tracing/contrib/aws/service/s3.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Datadog + module Tracing + module Contrib + module Aws + module Service + # S3 tag handlers. + class S3 < Base + def add_tags(span, params) + bucket_name = params[:bucket] + span.set_tag(Aws::Ext::TAG_BUCKET_NAME, bucket_name) + end + end + end + end + end + end +end diff --git a/lib/datadog/tracing/contrib/aws/service/sns.rb b/lib/datadog/tracing/contrib/aws/service/sns.rb new file mode 100644 index 00000000000..5b0f4dadf14 --- /dev/null +++ b/lib/datadog/tracing/contrib/aws/service/sns.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Datadog + module Tracing + module Contrib + module Aws + module Service + # SNS tag handlers. + class SNS < Base + def add_tags(span, params) + topic_arn = params[:topic_arn] + topic_name = params[:name] + if topic_arn + # example topic_arn: arn:aws:sns:us-west-2:123456789012:my-topic-name + parts = topic_arn.split(':') + topic_name = parts[-1] + aws_account = parts[-2] + span.set_tag(Aws::Ext::TAG_AWS_ACCOUNT, aws_account) + end + span.set_tag(Aws::Ext::TAG_TOPIC_NAME, topic_name) + end + end + end + end + end + end +end diff --git a/lib/datadog/tracing/contrib/aws/service/sqs.rb b/lib/datadog/tracing/contrib/aws/service/sqs.rb new file mode 100644 index 00000000000..a44abe85b95 --- /dev/null +++ b/lib/datadog/tracing/contrib/aws/service/sqs.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module Datadog + module Tracing + module Contrib + module Aws + module Service + # SQS tag handlers. + class SQS < Base + def add_tags(span, params) + queue_url = params[:queue_url] + queue_name = params[:queue_name] + if queue_url + _, _, _, aws_account, queue_name = queue_url.split('/') + span.set_tag(Aws::Ext::TAG_AWS_ACCOUNT, aws_account) + end + span.set_tag(Aws::Ext::TAG_QUEUE_NAME, queue_name) + end + end + end + end + end + end +end diff --git a/lib/datadog/tracing/contrib/aws/service/stepfunctions.rb b/lib/datadog/tracing/contrib/aws/service/stepfunctions.rb new file mode 100644 index 00000000000..d4a2220efc0 --- /dev/null +++ b/lib/datadog/tracing/contrib/aws/service/stepfunctions.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module Datadog + module Tracing + module Contrib + module Aws + module Service + # States tag handlers. + class States < Base + def add_tags(span, params) + state_machine_name = params[:name] + state_machine_arn = params[:state_machine_arn] + execution_arn = params[:execution_arn] + state_machine_account_id = '' + + if execution_arn + # 'arn:aws:states:us-east-1:123456789012:execution:example-state-machine:example-execution' + parts = execution_arn.split(':') + state_machine_name = parts[-2] + state_machine_account_id = parts[4] + end + + if state_machine_arn + # example statemachinearn: arn:aws:states:us-east-1:123456789012:stateMachine:MyStateMachine + parts = state_machine_arn.split(':') + state_machine_name ||= parts[-1] + state_machine_account_id = parts[-3] + end + span.set_tag(Aws::Ext::TAG_AWS_ACCOUNT, state_machine_account_id) + span.set_tag(Aws::Ext::TAG_STATE_MACHINE_NAME, state_machine_name) + end + end + end + end + end + end +end diff --git a/lib/datadog/tracing/contrib/aws/services.rb b/lib/datadog/tracing/contrib/aws/services.rb index ca55ddf3dbf..f2267988441 100644 --- a/lib/datadog/tracing/contrib/aws/services.rb +++ b/lib/datadog/tracing/contrib/aws/services.rb @@ -113,6 +113,16 @@ module Aws WorkSpaces XRay ].freeze + + SERVICE_HANDLERS = { + 'sqs' => Service::SQS.new, + 'sns' => Service::SNS.new, + 'dynamodb' => Service::DynamoDB.new, + 'kinesis' => Service::Kinesis.new, + 'eventbridge' => Service::EventBridge.new, + 'states' => Service::States.new, + 's3' => Service::S3.new + }.freeze end end end diff --git a/spec/datadog/tracing/contrib/aws/instrumentation_spec.rb b/spec/datadog/tracing/contrib/aws/instrumentation_spec.rb index c2caab25643..30a2e7612f2 100644 --- a/spec/datadog/tracing/contrib/aws/instrumentation_spec.rb +++ b/spec/datadog/tracing/contrib/aws/instrumentation_spec.rb @@ -27,7 +27,7 @@ Datadog.registry[:aws].reset_configuration! end - context 'with a core AWS SDK client', if: RUBY_VERSION >= '2.2.0' do + context 'with a core AWS SDK client' do before { hide_const('Aws::S3') } let(:client) { ::Aws::STS::Client.new(stub_responses: responses) } # STS is part of aws-sdk-core @@ -55,6 +55,7 @@ expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') expect(span.get_tag('aws.operation')).to eq('get_access_key_info') expect(span.get_tag('aws.region')).to eq('us-stubbed-1') + expect(span.get_tag('region')).to eq('us-stubbed-1') expect(span.get_tag('path')).to eq('') expect(span.get_tag('host')).to eq('sts.us-stubbed-1.amazonaws.com') expect(span.get_tag('http.method')).to eq('POST') @@ -106,6 +107,8 @@ expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') expect(span.get_tag('aws.operation')).to eq('list_buckets') expect(span.get_tag('aws.region')).to eq('us-stubbed-1') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('aws_service')).to eq('s3') expect(span.get_tag('path')).to eq('/') expect(span.get_tag('host')).to eq('s3.us-stubbed-1.amazonaws.com') expect(span.get_tag('http.method')).to eq('GET') @@ -130,6 +133,39 @@ end end + describe '#list_objects' do + subject!(:list_objects) { client.list_objects(bucket: 'bucketname', max_keys: 2) } + + let(:responses) do + { list_objects: {} } + end + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('s3.list_objects') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('list_objects') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('aws_service')).to eq('s3') + expect(span.get_tag('bucketname')).to eq('bucketname') + expect(span.get_tag('path')).to eq('/') + expect(span.get_tag('host')).to eq('bucketname.s3.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('GET') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('bucketname.s3.us-stubbed-1.amazonaws.com') + end + end + describe 'S3::Presigner' do let(:presigner) { ::Aws::S3::Presigner.new(client: client) } @@ -153,4 +189,871 @@ end end end + + context 'with an SQS client' do + let(:client) { ::Aws::SQS::Client.new(stub_responses: responses) } + + describe '#send_message' do + subject!(:send_message) do + client.send_message( + { + queue_url: 'https://sqs.us-stubbed-1.amazonaws.com/123456789012/MyQueueName', + message_body: 'Hello, world!' + } + ) + end + + let(:responses) do + { send_message: { + md5_of_message_body: 'msg body', + md5_of_message_attributes: 'msg attributes', + md5_of_message_system_attributes: 'message system attributes', + message_id: '123', + sequence_number: '456' + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('sqs.send_message') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('send_message') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('aws_service')).to eq('sqs') + expect(span.get_tag('aws_account')).to eq('123456789012') + expect(span.get_tag('queuename')).to eq('MyQueueName') + expect(span.get_tag('path')).to eq('/123456789012/MyQueueName') + expect(span.get_tag('host')).to eq('sqs.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('sqs.us-stubbed-1.amazonaws.com') + end + end + + describe '#send_message_batch' do + subject!(:send_message_batch) do + client.send_message_batch( + { + queue_url: 'https://sqs.us-stubbed-1.amazonaws.com/123456789012/MyQueueName', + entries: [ # required + { + id: 'String', # required + message_body: 'String', # required + delay_seconds: 1, + message_attributes: { + 'String' => { + string_value: 'String', + binary_value: 'data', + string_list_values: ['String'], + binary_list_values: ['data'], + data_type: 'String', # required + }, + }, + message_system_attributes: { + 'AWSTraceHeader' => { + string_value: 'String', + binary_value: 'data', + string_list_values: ['String'], + binary_list_values: ['data'], + data_type: 'String', # required + }, + }, + message_deduplication_id: 'String', + message_group_id: 'String', + }, + ], + } + ) + end + + let(:responses) do + { send_message_batch: { + successful: [], + failed: [] + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('sqs.send_message_batch') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('send_message_batch') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('aws_service')).to eq('sqs') + expect(span.get_tag('aws_account')).to eq('123456789012') + expect(span.get_tag('queuename')).to eq('MyQueueName') + expect(span.get_tag('path')).to eq('/123456789012/MyQueueName') + expect(span.get_tag('host')).to eq('sqs.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('sqs.us-stubbed-1.amazonaws.com') + end + end + + describe '#get_queue_url' do + subject!(:get_queue_url) do + client.get_queue_url( + { + queue_name: 'MyQueueName', + queue_owner_aws_account_id: '1234', + } + ) + end + + let(:responses) do + { get_queue_url: { + queue_url: 'myQueueURL' + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('sqs.get_queue_url') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('get_queue_url') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('aws_service')).to eq('sqs') + expect(span.get_tag('queuename')).to eq('MyQueueName') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('sqs.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('sqs.us-stubbed-1.amazonaws.com') + end + end + end + + context 'with an SNS client' do + let(:client) { ::Aws::SNS::Client.new(stub_responses: responses) } + + describe '#publish' do + subject!(:publish) do + client.publish( + { + topic_arn: 'arn:aws:sns:us-west-2:123456789012:my-topic-name', + message: 'Hello, world!' + } + ) + end + + let(:responses) do + { publish: { + message_id: '1234', + sequence_number: '5678' + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('sns.publish') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('publish') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('aws_service')).to eq('sns') + expect(span.get_tag('aws_account')).to eq('123456789012') + expect(span.get_tag('topicname')).to eq('my-topic-name') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('sns.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('sns.us-stubbed-1.amazonaws.com') + end + end + + describe '#create_topic' do + subject!(:create_topic) do + client.create_topic( + { + name: 'topicName', # required + attributes: { + 'attributeName' => 'attributeValue', + }, + tags: [ + { + key: 'TagKey', # required + value: 'TagValue', # required + }, + ] + } + ) + end + + let(:responses) do + { create_topic: { + + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('sns.create_topic') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('create_topic') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('aws_service')).to eq('sns') + expect(span.get_tag('topicname')).to eq('topicName') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('sns.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('sns.us-stubbed-1.amazonaws.com') + end + end + end + + context 'with an dynamodb client' do + let(:client) { ::Aws::DynamoDB::Client.new(stub_responses: responses) } + + describe '#get_item' do + subject!(:get_item) { client.get_item(table_name: 'my-table-name', key: { id: '1234' }) } + + let(:responses) do + { get_item: { + item: { + 'AlbumTitle' => 'Songs About Life', + 'Artist' => 'Acme Band', + 'SongTitle' => 'Happy Day', + } + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('dynamodb.get_item') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('get_item') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('aws_service')).to eq('dynamodb') + expect(span.get_tag('tablename')).to eq('my-table-name') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('dynamodb.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('dynamodb.us-stubbed-1.amazonaws.com') + end + end + end + + context 'with an kinesis client' do + let(:client) { ::Aws::Kinesis::Client.new(stub_responses: responses) } + + describe '#put_record' do + subject!(:put_record) do + client.put_record( + stream_name: 'my-stream-name', + partition_key: 'parition-1', + data: 'Hello world!' + ) + end + + let(:responses) do + { put_record: { + shard_id: '1234', + sequence_number: '5678', + encryption_type: 'NONE' + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('kinesis.put_record') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('put_record') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('aws_service')).to eq('kinesis') + expect(span.get_tag('streamname')).to eq('my-stream-name') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('kinesis.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('kinesis.us-stubbed-1.amazonaws.com') + end + end + + # aws-sdk >= (3.1.0)->aws-sdk-kinesis >= (1.45.0) resolves to a different host name + describe '#describe_stream_consumer', if: RUBY_VERSION >= '2.3.0' do + subject!(:describe_stream_consumer) do + client.describe_stream_consumer( + stream_arn: 'arn:aws:kinesis:us-east-1:123456789012:stream/my-stream', # required + consumer_name: 'cosumerName', # required + consumer_arn: 'consumerArn', # required + ) + end + let(:responses) do + { describe_stream_consumer: { + consumer_description: { + consumer_name: 'John Doe', + consumer_arn: 'consumerArn', + consumer_status: 'CREATING', + consumer_creation_timestamp: Time.new(2023, 3, 31, 12, 30, 0, '-04:00'), + stream_arn: 'streamArn' + } + } } + end + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('kinesis.describe_stream_consumer') + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('describe_stream_consumer') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('aws_service')).to eq('kinesis') + expect(span.get_tag('streamname')).to eq('my-stream') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('123456789012.control-kinesis.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('123456789012.control-kinesis.us-stubbed-1.amazonaws.com') + end + end + + # aws-sdk <= (3.0.2)->aws-sdk-kinesis >= (1.34.0) resolves to a different host name + describe '#describe_stream_consumer', if: RUBY_VERSION < '2.3.0' do + subject!(:describe_stream_consumer) do + client.describe_stream_consumer( + stream_arn: 'arn:aws:kinesis:us-east-1:123456789012:stream/my-stream', # required + consumer_name: 'cosumerName', # required + consumer_arn: 'consumerArn', # required + ) + end + let(:responses) do + { describe_stream_consumer: { + consumer_description: { + consumer_name: 'John Doe', + consumer_arn: 'consumerArn', + consumer_status: 'CREATING', + consumer_creation_timestamp: Time.new(2023, 3, 31, 12, 30, 0, '-04:00'), + stream_arn: 'streamArn' + } + } } + end + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('kinesis.describe_stream_consumer') + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('describe_stream_consumer') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('aws_service')).to eq('kinesis') + expect(span.get_tag('streamname')).to eq('my-stream') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('kinesis.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('kinesis.us-stubbed-1.amazonaws.com') + end + end + end + + context 'with an eventbridge client' do + let(:client) { ::Aws::EventBridge::Client.new(stub_responses: responses) } + + describe '#put_rule' do + subject!(:put_rule) do + client.put_rule( + { + name: 'RuleName', # required + tags: [ + { + key: 'TagKey', # required + value: 'TagValue', # required + }, + ], + } + ) + end + + let(:responses) do + { put_rule: { + rule_arn: 'my-rule-arn' + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('eventbridge.put_rule') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('put_rule') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('aws_service')).to eq('eventbridge') + expect(span.get_tag('rulename')).to eq('RuleName') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('events.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('events.us-stubbed-1.amazonaws.com') + end + end + + describe '#list_targets_by_rule' do + subject!(:list_targets_by_rule) do + client.list_targets_by_rule( + { + rule: 'RuleName', # required + } + ) + end + + let(:responses) do + { list_targets_by_rule: { + targets: [] + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('eventbridge.list_targets_by_rule') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('list_targets_by_rule') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('aws_service')).to eq('eventbridge') + expect(span.get_tag('rulename')).to eq('RuleName') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('events.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('events.us-stubbed-1.amazonaws.com') + end + end + end + + context 'with a stepfunction client' do + let(:client) { ::Aws::States::Client.new(stub_responses: responses) } + + describe '#start_execution' do + subject!(:start_execution) do + client.start_execution( + { + state_machine_arn: 'arn:aws:states:us-east-1:123456789012:stateMachine:MyStateMachine' # required + } + ) + end + + let(:responses) do + { start_execution: { + execution_arn: 'execution-arn', + start_date: Time.new(2023, 3, 31, 12, 30, 0, '-04:00') + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('states.start_execution') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('start_execution') + expect(span.get_tag('aws_service')).to eq('states') + expect(span.get_tag('aws_account')).to eq('123456789012') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('statemachinename')).to eq('MyStateMachine') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('states.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('states.us-stubbed-1.amazonaws.com') + end + end + + describe '#create_state_machine' do + subject!(:create_state_machine) do + client.create_state_machine( + { + name: 'my-state-machine-name', # required + definition: 'Definition', # required + role_arn: 'Arn', # required + } + ) + end + + let(:responses) do + { create_state_machine: { + state_machine_arn: 'arn', + creation_date: Time.new(2023, 3, 31, 12, 30, 0, '-04:00') + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('states.create_state_machine') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('create_state_machine') + expect(span.get_tag('aws_service')).to eq('states') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('statemachinename')).to eq('my-state-machine-name') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('states.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('states.us-stubbed-1.amazonaws.com') + end + end + + describe '#describe_state_machine' do + subject!(:describe_state_machine) do + client.describe_state_machine( + { + state_machine_arn: 'arn:aws:states:us-east-1:123456789012:stateMachine:my-state-machine-name', # required + } + ) + end + + let(:responses) do + { describe_state_machine: { + state_machine_arn: 'arn:aws:states:us-east-1:123456789012:stateMachine:example-state-machine', + name: 'example-state-machine', + status: 'ACTIVE', + definition: '{\'Comment\':\'An example state machine\', + \'StartAt\':\'HelloWorld\', + \'States\':{\'HelloWorld\':{\'Type\':\'Task\', + \'Resource\':\'arn:aws:lambda:us-east-1:123456789012:function:hello-world\', + \'End\':true}}}', + role_arn: 'arn:aws:iam::123456789012:role/StateExecutionRole', + type: 'STANDARD', + creation_date: Time.now + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('states.describe_state_machine') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('describe_state_machine') + expect(span.get_tag('aws_service')).to eq('states') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('statemachinename')).to eq('my-state-machine-name') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('states.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('states.us-stubbed-1.amazonaws.com') + end + end + + describe '#update_state_machine' do + subject!(:update_state_machine) do + client.update_state_machine( + { + state_machine_arn: 'arn:aws:states:us-east-1:123456789012:stateMachine:my-state-machine-name', # required + } + ) + end + + let(:responses) do + { update_state_machine: { + update_date: Time.new(2023, 3, 31, 12, 30, 0, '-04:00') + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('states.update_state_machine') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('update_state_machine') + expect(span.get_tag('aws_service')).to eq('states') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('statemachinename')).to eq('my-state-machine-name') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('states.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('states.us-stubbed-1.amazonaws.com') + end + end + + describe '#delete_state_machine' do + subject!(:delete_state_machine) do + client.delete_state_machine( + { + state_machine_arn: 'arn:aws:states:us-east-1:123456789012:stateMachine:my-state-machine-name', # required + } + ) + end + + let(:responses) do + { delete_state_machine: {} } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('states.delete_state_machine') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('delete_state_machine') + expect(span.get_tag('aws_service')).to eq('states') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('statemachinename')).to eq('my-state-machine-name') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('states.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('states.us-stubbed-1.amazonaws.com') + end + end + + describe '#describe_execution' do + subject!(:describe_execution) do + client.describe_execution( + { + execution_arn: 'arn:aws:states:us-east-1:123456789012:execution:example-state-machine:example-execution', + } + ) + end + + let(:responses) do + { describe_execution: { + execution_arn: 'string', + state_machine_arn: 'string', + name: 'string', + status: 'string', + start_date: Time.new(2023, 3, 31, 12, 30, 0, '-04:00'), + stop_date: Time.new(2023, 3, 31, 12, 30, 0, '-04:00'), + input: 'string', + input_details: { + included: true | false, + }, + output: 'string', + output_details: { + included: true | false, + }, + trace_header: 'string' + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('states.describe_execution') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('describe_execution') + expect(span.get_tag('aws_service')).to eq('states') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('statemachinename')).to eq('example-state-machine') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('states.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('states.us-stubbed-1.amazonaws.com') + end + end + + describe '#stop_execution' do + subject!(:stop_execution) do + client.stop_execution( + { + execution_arn: 'arn:aws:states:us-east-1:123456789012:execution:example-state-machine:example-execution', + } + ) + end + + let(:responses) do + { stop_execution: { + stop_date: Time.new(2023, 3, 31, 12, 30, 0, '-04:00'), + } } + end + + it 'generates a span' do + expect(span.name).to eq('aws.command') + expect(span.service).to eq('aws') + expect(span.span_type).to eq('http') + expect(span.resource).to eq('states.stop_execution') + + expect(span.get_tag('aws.agent')).to eq('aws-sdk-ruby') + expect(span.get_tag('aws.operation')).to eq('stop_execution') + expect(span.get_tag('aws_service')).to eq('states') + expect(span.get_tag('region')).to eq('us-stubbed-1') + expect(span.get_tag('statemachinename')).to eq('example-state-machine') + expect(span.get_tag('path')).to eq('') + expect(span.get_tag('host')).to eq('states.us-stubbed-1.amazonaws.com') + expect(span.get_tag('http.method')).to eq('POST') + expect(span.get_tag('http.status_code')).to eq('200') + expect(span.get_tag('span.kind')).to eq('client') + + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT)).to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION)) + .to eq('command') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE)) + .to eq('aws') + expect(span.get_tag(Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME)) + .to eq('states.us-stubbed-1.amazonaws.com') + end + end + end end diff --git a/spec/datadog/tracing/contrib/aws/parsed_context_spec.rb b/spec/datadog/tracing/contrib/aws/parsed_context_spec.rb index 2f2796fd528..ca71f5de4da 100644 --- a/spec/datadog/tracing/contrib/aws/parsed_context_spec.rb +++ b/spec/datadog/tracing/contrib/aws/parsed_context_spec.rb @@ -6,10 +6,18 @@ RSpec.describe Datadog::Tracing::Contrib::Aws::ParsedContext do subject(:parsed_context) { described_class.new(context) } - let(:context) { client.list_buckets.context } - - let(:client) { ::Aws::S3::Client.new(region: 'us-west-2', stub_responses: responses) } - let(:responses) { true } + let(:context) do + Seahorse::Client::RequestContext.new( + operation_name: :list_buckets, + client: double(class: 'Aws::S3::Client', config: double(region: 'us-west-2')), + http_request: Seahorse::Client::Http::Request.new( + endpoint: URI('http://us-west-2.amazonaws.com.com/') + ), + http_response: Seahorse::Client::Http::Response.new( + status_code: 200 + ) + ) + end describe '#new' do context 'given a context with typical values' do diff --git a/spec/datadog/tracing/contrib/aws/service/dynamobdb_spec.rb b/spec/datadog/tracing/contrib/aws/service/dynamobdb_spec.rb new file mode 100644 index 00000000000..2f4580dc7bd --- /dev/null +++ b/spec/datadog/tracing/contrib/aws/service/dynamobdb_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'rspec' +require 'lib/datadog/tracing/contrib/aws/service/base' +require 'lib/datadog/tracing/contrib/aws/service/dynamodb' + +RSpec.describe Datadog::Tracing::Contrib::Aws::Service::DynamoDB do + let(:span) { instance_double('Span') } + let(:params) { {} } + let(:dynamodb) { described_class.new } + + before do + allow(span).to receive(:set_tag) + end + + context 'with table_name provided' do + let(:table_name) { 'example-table' } + let(:params) { { table_name: table_name } } + + it 'sets the table_name tag' do + dynamodb.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_TABLE_NAME, table_name) + end + end + + context 'with no table_name provided' do + it 'does not set the table_name tag' do + dynamodb.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_TABLE_NAME, nil) + end + end +end diff --git a/spec/datadog/tracing/contrib/aws/service/eventbrige_spec.rb b/spec/datadog/tracing/contrib/aws/service/eventbrige_spec.rb new file mode 100644 index 00000000000..f9b8074fefa --- /dev/null +++ b/spec/datadog/tracing/contrib/aws/service/eventbrige_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require 'rspec' +require 'lib/datadog/tracing/contrib/aws/service/base' +require 'lib/datadog/tracing/contrib/aws/service/eventbridge' + +RSpec.describe Datadog::Tracing::Contrib::Aws::Service::EventBridge do + let(:span) { instance_double('Span') } + let(:params) { {} } + let(:event_bridge) { described_class.new } + + before do + allow(span).to receive(:set_tag) + end + + context 'with rule_name provided in params[:name]' do + let(:rule_name) { 'example-rule-name' } + let(:params) { { name: rule_name } } + + it 'sets the rule_name based on the params[:name]' do + event_bridge.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_RULE_NAME, rule_name) + end + end + + context 'with rule_name provided in params[:rule]' do + let(:rule_name) { 'example-rule-name' } + let(:params) { { rule: rule_name } } + + it 'sets the rule_name based on the params[:rule]' do + event_bridge.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_RULE_NAME, rule_name) + end + end + + context 'without rule_name provided' do + it 'does not set the rule_name tag' do + event_bridge.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_RULE_NAME, nil) + end + end +end diff --git a/spec/datadog/tracing/contrib/aws/service/kinesis_spec.rb b/spec/datadog/tracing/contrib/aws/service/kinesis_spec.rb new file mode 100644 index 00000000000..4d086afd64f --- /dev/null +++ b/spec/datadog/tracing/contrib/aws/service/kinesis_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require 'rspec' +require 'lib/datadog/tracing/contrib/aws/service/base' +require 'lib/datadog/tracing/contrib/aws/service/kinesis' + +RSpec.describe Datadog::Tracing::Contrib::Aws::Service::Kinesis do + let(:span) { instance_double('Span') } + let(:params) { {} } + let(:kinesis) { described_class.new } + + before do + allow(span).to receive(:set_tag) + end + + context 'with stream_arn provided' do + let(:stream_arn) { 'arn:aws:kinesis:us-east-1:123456789012:stream/my-stream' } + let(:params) { { stream_arn: stream_arn } } + + it 'sets the stream_name and aws_account based on the stream_arn' do + kinesis.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_AWS_ACCOUNT, '123456789012') + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_STREAM_NAME, 'my-stream') + end + end + + context 'with stream_name provided' do + let(:params) { { stream_name: 'my-stream' } } + + it 'sets the stream_name based on the provided stream_name' do + kinesis.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_STREAM_NAME, 'my-stream') + end + end + + context 'with neither stream_arn nor stream_name provided' do + it 'sets the stream_name to nil' do + kinesis.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_STREAM_NAME, nil) + end + end +end diff --git a/spec/datadog/tracing/contrib/aws/service/s3_spec.rb b/spec/datadog/tracing/contrib/aws/service/s3_spec.rb new file mode 100644 index 00000000000..baf2eb5c5a4 --- /dev/null +++ b/spec/datadog/tracing/contrib/aws/service/s3_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'rspec' +require 'lib/datadog/tracing/contrib/aws/service/base' +require 'lib/datadog/tracing/contrib/aws/service/s3' + +RSpec.describe Datadog::Tracing::Contrib::Aws::Service::S3 do + let(:span) { instance_double('Span') } + let(:params) { {} } + let(:s3) { described_class.new } + + before do + allow(span).to receive(:set_tag) + end + + context 'with bucket name provided' do + let(:params) { { bucket: 'my-bucket-name' } } + + it 'sets the bucket_name based on the provided bucket name' do + s3.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_BUCKET_NAME, 'my-bucket-name') + end + end + + context 'with no bucket name provided' do + it 'sets the bucket_name to nil' do + s3.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_BUCKET_NAME, nil) + end + end +end diff --git a/spec/datadog/tracing/contrib/aws/service/sns_spec.rb b/spec/datadog/tracing/contrib/aws/service/sns_spec.rb new file mode 100644 index 00000000000..f871b16b7c8 --- /dev/null +++ b/spec/datadog/tracing/contrib/aws/service/sns_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require 'rspec' +require 'lib/datadog/tracing/contrib/aws/service/base' +require 'lib/datadog/tracing/contrib/aws/service/sns' + +RSpec.describe Datadog::Tracing::Contrib::Aws::Service::SNS do + let(:span) { instance_double('Span') } + let(:params) { {} } + let(:sns) { described_class.new } + + before do + allow(span).to receive(:set_tag) + end + + context 'with topic_arn provided' do + let(:topic_arn) { 'arn:aws:sns:us-west-2:123456789012:my-topic-name' } + let(:params) { { topic_arn: topic_arn } } + + it 'sets the topic_name and aws_account based on the topic_arn' do + sns.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_AWS_ACCOUNT, '123456789012') + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_TOPIC_NAME, 'my-topic-name') + end + end + + context 'with name provided' do + let(:params) { { name: 'my-topic-name' } } + + it 'sets the topic_name based on the provided name' do + sns.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_TOPIC_NAME, 'my-topic-name') + end + end + + context 'with neither topic_arn nor name provided' do + it 'sets the topic_name to nil' do + sns.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_TOPIC_NAME, nil) + end + end +end diff --git a/spec/datadog/tracing/contrib/aws/service/sqs_spec.rb b/spec/datadog/tracing/contrib/aws/service/sqs_spec.rb new file mode 100644 index 00000000000..bf87bfb697a --- /dev/null +++ b/spec/datadog/tracing/contrib/aws/service/sqs_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'lib/datadog/tracing/contrib/aws/service/base' +require 'lib/datadog/tracing/contrib/aws/service/sqs' +require 'spec_helper' +require 'rspec' + +RSpec.describe Datadog::Tracing::Contrib::Aws::Service::SQS do + let(:span) { instance_double('Span') } + let(:params) { {} } + let(:sqs) { described_class.new } + + before do + allow(span).to receive(:set_tag) + end + + context 'when queue_url is present' do + let(:queue_url) { 'https://sqs.us-east-1.amazonaws.com/123456789012/MyQueueName' } + let(:params) { { queue_url: queue_url } } + + it 'sets AWS account and queue name tags' do + sqs.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_AWS_ACCOUNT, '123456789012') + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_QUEUE_NAME, 'MyQueueName') + end + end + + context 'when queue_name is present' do + let(:queue_name) { 'AnotherQueueName' } + let(:params) { { queue_name: queue_name } } + + it 'sets queue name tag' do + sqs.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_QUEUE_NAME, 'AnotherQueueName') + end + end +end diff --git a/spec/datadog/tracing/contrib/aws/service/stepfunctions_spec.rb b/spec/datadog/tracing/contrib/aws/service/stepfunctions_spec.rb new file mode 100644 index 00000000000..128d6f3202e --- /dev/null +++ b/spec/datadog/tracing/contrib/aws/service/stepfunctions_spec.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +require 'rspec' +require 'lib/datadog/tracing/contrib/aws/service/base' +require 'lib/datadog/tracing/contrib/aws/service/stepfunctions' + +RSpec.describe Datadog::Tracing::Contrib::Aws::Service::States do + let(:span) { instance_double('Span') } + let(:params) { {} } + let(:step_functions) { described_class.new } + + before do + allow(span).to receive(:set_tag) + end + + context 'with execution_arn provided' do + let(:execution_arn) { 'arn:aws:states:us-east-1:123456789012:execution:example-state-machine:example-execution' } + let(:params) { { execution_arn: execution_arn } } + + it 'sets the state_machine_name based on the execution_arn' do + step_functions.add_tags(span, params) + expect(span).to have_received(:set_tag).with( + Datadog::Tracing::Contrib::Aws::Ext::TAG_STATE_MACHINE_NAME, + 'example-state-machine' + ) + end + end + + context 'with state_machine_arn provided' do + let(:state_machine_arn) { 'arn:aws:states:us-east-1:123456789012:stateMachine:MyStateMachine' } + let(:params) { { state_machine_arn: state_machine_arn } } + + it 'sets the state_machine_name based on the state_machine_arn' do + step_functions.add_tags(span, params) + expect(span).to have_received(:set_tag).with( + Datadog::Tracing::Contrib::Aws::Ext::TAG_STATE_MACHINE_NAME, + 'MyStateMachine' + ) + end + + it 'sets the state_machine_account_id based on the state_machine_arn' do + step_functions.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_AWS_ACCOUNT, '123456789012') + end + end + + context 'with both execution_arn and state_machine_arn provided' do + let(:execution_arn) { 'arn:aws:states:us-east-1:987654321098:execution:example-state-machine:example-execution' } + let(:state_machine_arn) { 'arn:aws:states:us-east-1:123456789012:stateMachine:MyStateMachine' } + + it 'sets the state_machine_name and state_machine_account_id based on the state_machine_arn' do + params = { state_machine_arn: state_machine_arn } + step_functions.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_AWS_ACCOUNT, '123456789012') + expect(span).to have_received(:set_tag).with( + Datadog::Tracing::Contrib::Aws::Ext::TAG_STATE_MACHINE_NAME, + 'MyStateMachine' + ) + end + + it 'sets the state_machine_name and state_machine_account_id based on the execution_arn' do + params = { execution_arn: execution_arn } + step_functions.add_tags(span, params) + expect(span).to have_received(:set_tag).with(Datadog::Tracing::Contrib::Aws::Ext::TAG_AWS_ACCOUNT, '987654321098') + expect(span).to have_received(:set_tag).with( + Datadog::Tracing::Contrib::Aws::Ext::TAG_STATE_MACHINE_NAME, + 'example-state-machine' + ) + end + end +end