Amazon Linux 2にBCCを入れて、Pythonのメソッド実行のトレースをしてみる

今回はBCC(BPF Compiler Collection)のツールを使って Pythonのメソッド実行のトレースをやってみます。

今回の記事の流れは以下のとおりです。

  • Amazon Linux 2を立ててBCCのインストールをする
  • 検証のためのコードを準備する
  • 実際にメソッドの呼び出しをトレースしてみる
  • まとめ

Amazon Linux 2を立ててBCCのインストールをする

Amazon Linux 2でEC2を立てます。 マネージメントコンソールから立てました。

次に、以下のコマンドでBCCを入れます。(※)

sudo amazon-linux-extras install -y BCC

簡単なインストール方法が見つかって最高って気持ちになった。感謝。

ここまでで、EC2のセットアップから、BCCのインストールまでが終わりました。

検証のためのコードを準備する

メソッドの呼び出しをトレースしたいので 以下のようなコードを用意しました。

#!/usr/bin/env python2

import time
i = 0

def log(i):
  print(i)
  time.sleep(1)

def loop(i):
  time.sleep(1)
  log(i)

while True:
  loop(i)
  i+=1

メソッドの呼び出しをトレースした際にツリー表示されるので いくつかメソッドに切り出してsleepするようにしています。

実際にメソッドの呼び出しをトレースしてみる

↑で作ったスクリプトをバックグラウンドで動かして メソッドの呼び出しをトレースしてみます。

今回は pythonflowというツールを使って トレースしてみます。

実際に動かした時のログが以下のものになります。

$ ./test.py > /dev/null &
[2] 18353
$ sudo /usr/share/bcc/tools/pythonflow 18353
Tracing method calls in python process 18353... Ctrl-C to quit.
CPU PID    TID    TIME(us) METHOD
0   18353  18353  0.271    <- ./test.py.log
0   18353  18353  0.272    <- ./test.py.loop
0   18353  18353  0.272    -> ./test.py.loop
0   18353  18353  1.273      -> ./test.py.log
0   18353  18353  2.274      <- ./test.py.log
0   18353  18353  2.274    <- ./test.py.loop
0   18353  18353  2.274    -> ./test.py.loop
0   18353  18353  3.275      -> ./test.py.log
0   18353  18353  4.276      <- ./test.py.log
0   18353  18353  4.277    <- ./test.py.loop
0   18353  18353  4.277    -> ./test.py.loop
0   18353  18353  5.277      -> ./test.py.log
0   18353  18353  6.279      <- ./test.py.log
0   18353  18353  6.279    <- ./test.py.loop
0   18353  18353  6.279    -> ./test.py.loop

なんとなく動いているのが分かります。

BCCには、いくつかのツールが入っており 今回触ったようなPythonなどの高級言語のためのツールとしては ucalls, uflow, ugc, uobjnew, ustatがあります。

今回触ったpythonflowというツールはuflowをベースにしたツールです。

上で紹介したツールの概要としては以下のとおりです。

  • ucalls: メソッドの呼び出しとシステムコールのサマリ可視化
  • uflow: メソッドフローグラフの可視化
  • ugc: GCイベントのトレース
  • ubjnew: オブジェクトの生成イベントのサマリ可視化
  • ustat: 色々なイベントの収集をして、秒間当たりのイベント数を表示してくれる

他にも色々ツールがあったり、ライブラリとして利用も出来るようです。

まとめ

今回は、Pythonの内製ツールで問題があったので、調査できるような手段を用意しておくために インストール方法の検証と動作確認を行ってみました。

今回は簡単なツールの利用に留まりましたが、障害調査などで非常に役立つと感じています。 次はJavaのトレースで試してみようかな?

今回の記事としては以上です。

AWS CDKを使ってAWS LambdaにAPI Gateway経由で呼び出す口を用意する

Lambdaを使ってAPIをホストしたい時、何使いますか? AWS CDK、おすすめです。

実際のコード

Lambda Functionを中心として、Lambda Functionに関連付けを紐付けるだけで API Gatewayなりのリソースが作成される。

#!/usr/bin/env node
import 'source-map-support/register';
import {App, Stack} from '@aws-cdk/core';
import {Runtime, Code, Function} from "@aws-cdk/aws-lambda"
import {ApiEventSource} from "@aws-cdk/aws-lambda-event-sources"

const app = new App();

const stack = new Stack(app, "example-stack")

const f = new Function(stack, "example-lambda", {
    handler: "main",
    code: Code.fromAsset("dist/"),
    runtime: Runtime.GO_1_X,
    role: role,
})

f.addEventSource(new ApiEventSource("POST", "/"))

Lambda中心でHookを追加出来るのは、Serverless FrameworkやAWS SAMと似たような形になっていて良い。 最初、AWS SAMを cdk 経由で使おうと思って調べていたら aws-sam というそのままのモジュールがあったが これは low-level constructs という感じで、CloudformationのSAMそのもの。 使おうとしても、警告出るし、使いづらかった。(Public Betaなので仕方ない気もしますが・・・) そこで、色々調べてたら @aws-cdk/aws-lambda-event-sources というパッケージがあったので 使ってみたらめっちゃ便利だったので、記事を書いた。

現状、@aws-cdk/aws-lambda-event-sources で対応しているリソースについて

現状、ApiEventSource(API Gateway)の他にも下のようなリソースと連携する事ができる。

上記リソースに関しては、ドキュメントが整備されている。 ApiEventSourceだけはドキュメントに記載がないので注意。

まとめ

AWS CDK、便利。VSCodeでTypeScript書くと、import補完もしてくれていいぞ! というわけで、AWS CDK、おすすめです。

Goの型付きnilで死んだ話

これはどういう結果になるか、分かりますか?

package main

import (
    "fmt"
    "bytes"
)

func Buffer() *bytes.Buffer {
    return nil
}

func main() {
    b := Buffer()
    fmt.Printf("%T %v", b, b)
}

こうなります。

f:id:reteria:20190822234013p:plain

型無しnilになって欲しい気持ちだった。 結局、戻り値の型をio.Readerにしました。