AWS SDK for Rubyでhttp_wire_traceオプションを使ってAPIとの通信内容を出力する
タグ: rubyaws / 初版公開: 2018-09-17

概要

  • AWS SDK for Rubyではhttp_wire_traceオプションを利用するとAWS SDKがAPIと通信した内容を出力することができます。デバッグ時に便利です。
  • http_wire_traceオプションはリソースやクライアントの初期化時に指定するかAWS.configでグローバルに指定することもできます。
  • 使い方は言語毎に異なりますが、少なくともPythonのboto3でも通信内容の出力は可能で、他の言語のSDKにも同様の機能があるようです。

前提ソフトウェア・ハードウェア

ソフトウェアバージョン備考
Ruby2.5.1p57-
aws-sdk-core3.27.0-
aws-sdk-sns1.5.0-

Amazon SNSのpublishで通信内容を出力する例

AWS SDKを使ってコードを書いているとAWSのAPIとの通信内容を確認してデバッグしたくなることがあります。 そのような時はhttp_wire_traceオプションを使うと便利です。

通信内容を出力しないサンプルコード

とあるAmazon SNSのトピックにPublishアクションを実行する以下のコードを例に通信内容を出力してみます。 このコードを実行すると、通常は何も出力されずに正常終了します。

require 'aws-sdk-sns'

topic = Aws::SNS::Topic.new(arn: 'arn:aws:sns:ap-northeast-1:9999999999999:some_topic')

topic.publish(message: 'Hello!')

通信内容を出力するよう改変したサンプルコード

ここでAws::SNS::Topicの初期化時にhttp_wire_trace: trueオプションを指定してみます。 これでtopicに代入されたAws::SNS::Topicインスタンスで行った操作は通信内容が出力されるようになります。

require 'aws-sdk-sns'

topic = Aws::SNS::Topic.new(
  arn: 'arn:aws:sns:ap-northeast-1:9999999999999:some_topic',
  http_wire_trace: true # http_wire_trace: true を追加した
)

topic.publish(message: 'Hello!')

プログラムは正常終了しますが、以下の標準出力がされるようになります。 クレデンシャルなど機微な情報が含まれることに注意が必要です。

opening connection to sns.ap-northeast-1.amazonaws.com:443...
opened
starting SSL for sns.ap-northeast-1.amazonaws.com:443...
SSL established
<- "POST / HTTP/1.1\r\nContent-Type: application/x-www-form-urlencoded; charset=utf-8\r\nAccept-Encoding: \r\nUser-Agent: aws-sdk-ruby3/3.27.0 ruby/2.5.1 x86_64-linux-gnu aws-sdk-sns/1.5.0\r\nHost: sns.ap-northeast-1.amazonaws.com\r\nX-Amz-Date: 20180917T114946Z\r\nX-Amz-Content-Sha256: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r\nAuthorization: AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXXX/20180917/ap-northeast-1/sns/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amzignature=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r\nContent-Length: 120\r\nAccept: */*\r\n\r\n"
-> "HTTP/1.1 200 OK\r\n"
-> "x-amzn-RequestId: XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXXXX\r\n"
-> "Content-Type: text/xml\r\n"
-> "Content-Length: 294\r\n"
-> "Date: Mon, 17 Sep 2018 11:49:46 GMT\r\n"
-> "\r\n"
reading 294 bytes...
-> ""
-> "<PublishResponse xmlns=\"http://sns.amazonaws.com/doc/2010-03-31/\">\n  <PublishResult>\n    <MessageId>XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</MessageId>\n  </PublishResult>\n  <ResponseMetadata>\n    <RequestId>XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXXXX</RequestId>\n  </ResponseMetadata>\n</PublishResponse>\n"
read 294 bytes
Conn keep-alive

同様の出力をする他のサンプルコード

クライアントやリソースのインスタンスに設定したhttp_wire_traceは受け継がれていきます。 以下の2つの例ではAws::SNS::Topicインスタンスそのものにはオプションを指定していませんがtopic.publishで通信内容が出力されます。

require 'aws-sdk-sns'

sns = Aws::SNS::Resource.new(http_wire_trace: true) # Aws::SNS::Resourceでhttp_wire_trace: trueを指定

topic = sns.topic('arn:aws:sns:ap-northeast-1:9999999999999:some_topic') # Aws::SNS::ResourceからTopicを作成

topic.publish(message: 'Hello!')
require 'aws-sdk-sns'

sns_client = Aws::SNS::Client.new(http_wire_trace: true) # Aws::SNS::Clientでhttp_wire_trace: trueを指定

topic = Aws::SNS::Topic.new(arn: 'arn:aws:sns:ap-northeast-1:9999999999999:some_topic', client: sns_client) # Aws::SNS::Clientを渡してTopicを初期化

topic.publish(message: 'Hello!')

もし全てのAWSとの通信部分で出力したい場合はAws.confighttp_wire_traceを指定すれば良いです。

require 'aws-sdk-sns'

Aws.config.update(http_wire_trace: true)

topic = Aws::SNS::Topic.new(arn: 'arn:aws:sns:ap-northeast-1:9999999999999:some_topic')

topic.publish(message: 'Hello!')

なおloggerオプションを指定するとhttp_wire_traceの出力もつられてloggerの出力先に出るようになっています。 以下の例では標準エラー出力に通信内容が出力されます。

require 'aws-sdk-sns'

Aws.config.update(logger: Logger.new(STDERR), http_wire_trace: true) # loggerオプションに標準エラー出力向きのLoggerを指定している

topic = Aws::SNS::Topic.new(
  arn: 'arn:aws:sns:ap-northeast-1:9999999999999:some_topic'
)

topic.publish(message: 'Hello!')

AWS SDK for Rubyのhttp_wire_traceはどのように実装されているのか?

http_wire_traceオプションによって出力をするかどうか切り替えている箇所はSeahorse::Client::NetHTTP::ConnectionPoolの以下の行です。

aws-sdk-ruby/connection_pool.rb at 2080dae8a525cf87ade12c65d1e06d3ee3c4ad26 · aws/aws-sdk-ruby

 http.set_debug_output(logger) if http_wire_trace?

このコード中でhttpExtendedSessionクラス(RubyのNet::HTTPのデリゲータ)のインスタンスです。 http_wire_traceとはAWS SDK内部でNet::HTTPset_debug_outputloggerを渡すかどうかのフラグであることがわかります。

Net::HTTP#set_debug_outputはリファレンスを参照して下さい。 内部では<<しているようです。

AWS SDKにloggerを設定するとhttp_wire_traceの出力先も変更されるのはこのためです。 ただし<<で出力しているのでRubyのLoggerの実装ではフォーマットはされません。

instance method Net::HTTP#set_debug_output (Ruby 2.5.0)

set_debug_output(io) -> ()

デバッグ出力の出力先を指定します。 このメソッドは深刻なセキュリティホールの原因 になるため、デバッグ以外では決して使わないでください。

io に nil を指定するとデバッグ出力を止めます。

[PARAM] io:

出力先を指定します。このオブジェクトは メソッド « を持っている必要があります。

他の言語のAWS SDKで同様の機能はあるか

Pythonのboto3だとboto3.set_stream_loggerで出力可能でした。 RubyのコードをPythonで書き換えたサンプルコードは以下のとおりです。

Boto3 Reference – Boto 3 Docs 1.9.4 documentation

import boto3

boto3.set_stream_logger(name='')

sns = boto3.resource('sns')

topic = sns.Topic('arn:aws:sns:ap-northeast-1:999999999999:some_topic')

topic.publish(Message='Hello!')

参考