AWS CodeGuruを使ってみた

AWS re:Invent 2019で発表された機械学習を応用したソースコード解析ツールAWS CodeGuruを使ってみました。 その使用感や解析結果をまとめたいと思います。

参考:使用したのはCodeGuru Reviewer のみでCodeGuru Profilerは使っていません。

1. 結論

利用者は以下のような方かなと。

  • 他の静的解析ツールも使っている
    • (AWS CodeGuru一本化は厳しそう)
  • AWSのAPIの使用方法が合っているかよくわからないので確認したい
  • お金に余裕がある

1.1. 使用感

  • AWS CodeCommitGithubとの連携は簡単
  • 解析結果はプルリクエストに対して、レビューア(AWS CodeGuru Bot)の指摘として表示される

1.2. 解析結果

  • 一般的な静的解析ツール(FindBugsSonarQubeCoverityIDEによる指摘など)で発見されるバグは、ほとんど指摘されない
  • AWSのAPIの使い方に関する指摘は鋭い

2. 前提

Amazon CodeGuru は、「自動化されたコードレビュー」と「アプリケーションパフォーマンスの推奨事項を提供する」機械学習サービスです。(引用元:https://aws.amazon.com/jp/codeguru/)

以下のような静的解析ツールの仲間ですね。

現状(2019/12時点)では、Amazon CodeGuruはJava言語のみ対応。

2.1. 連携できるバージョン管理システム

以下の2つに対応(今回はAWS CodeCommitを使用した)

  • Github
  • AWS CodeCommit

参考URL : https://docs.aws.amazon.com/codeguru/latest/reviewer-ug/integrations.html

2.2. 解析単価

まぁまぁ高いので、使う際は気をつけましょう。。
今後、巨大なMR作って事故る人出るかもしれないですね、、、

コード 100 行あたり 0.75 USD
例:10,000行のコードだったら、75USD(2019/12時点で約8200円)

引用元:https://aws.amazon.com/jp/codeguru/pricing/

2.3. 指摘の観点

  • AWS Best Practices
    • AWS APIの使い方について
  • Concurrency
    • 並行性の実装について(原子性違反を見てくれる)
  • Resource Leak Prevention
    • リソース漏れについて
  • Sensitive Information Leak Prevention
    • 機密情報の漏洩について
  • Common Coding Best Practices
    • 一般的なコーティングについて

引用元:https://docs.aws.amazon.com/codeguru/latest/reviewer-ug/recommendations.html

3. 使用感

3.1. セットアップについて

参考URLに記載の通りであるが、以下の手順で、10分ほどあれば完了するので簡単。

  1. CodeCommit の初期設定(リポジトリ作成画面にAWS CodeGuruとの連携オプションあり。)

  1. Git をインストールする
  2. CodeCommit への HTTPS 接続用の Git 認証情報を作成する
  3. CodeCommit コンソールに接続し、リポジトリを複製する

参考URL : https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/setting-up-gc.html

3.2. 運用性について

マージリクエストに対して、レビュアーのような立場でソースコードに指摘をしてくれるので、運用上指摘を見逃すことがない。

指摘場所は、AWS CodeCommitのアクティビティ画面

4. 指摘結果

4.1. 指摘されなかったコード

下のコードはいずれも他の静的解析ツールで指摘されるのですが、、AWS CodeGuruでは指摘されなかったです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// ひどいコード1
var test1 = "test1";
var test2 = "test2";
var test3 = "test3";
var test4 = "test4";

// ひどいコード2
do{
	//処理
}while(false);

// ひどいコード3
while(true){

}

// ひどいコード4
// リソースのcloseなし
try {
    InputStream in = new FileInputStream(src);

    OutputStream out = new FileOutputStream(dst);
}

// ひどいコード5
// 引用元:https://qiita.com/negi111111/items/510daace637b7c57c2da
public class ClassSample {
    public static void main(String args[]) {
        int proc = 0;
        try {
            if ( proc == 0 ){
                // 正常処理
                try {
                    if ( proc == 1 ){
                        // 正常処理
                        try {
                            if ( proc == 2 ){
                                // 正常処理
                                try {
                                    if ( proc == 3 ){
                                        // 正常処理
                                        try {
                                            if ( proc == 4 ){
                                                // 正常処理
                                                if ( proc == 5 ){
                                                    // 正常処理
                                                    // まだまだ続くよ!
                                                } else {
                                                    // 異常処理
                                                }
                                            } else {
                                                // 異常処理
                                            }
                                        } catch(Exception e) {
                                            // 例外処理
                                        }
                                    } else {
                                        // 異常処理
                                    }
                                } catch(Exception e) {
                                    // 例外処理
                                }
                            } else {
                                // 異常処理
                            }
                        } catch(Exception e) {
                            // 例外処理
                        }
                    } else {
                        // 異常処理
                    }
                } catch(Exception e) {
                    // 例外処理
                }
            } else {
                // 異常処理
            }

        } catch(Exception e) {
        // 握りつぶす
        }
        System.out.println("Hello! World!");
    }
}

4.2. 指摘されたコード

一般的なコーディングに対する指摘ですね。

1
2
3
4
5
6
7
String dateString = "2016/01/01 00:00:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Long epochTime = sdf.parse(dateString).getTime();
System.out.println(epochTime);

// 指摘内容
// 「タイムゾーンの指定がない」

以下はAWSのAPIについての指摘です。結構詳しく記載されていて「流石です」という所感です。

1
2
3
4
new BasicAWSCredentials(EnvProp.getAccesskey(), EnvProp.getSecretkey())));

// 指摘内容
// If possible, use temporary security credentials (IAM roles) instead of long-term access keys. Long-term access keys, such as those associated with IAM users and AWS account root users, remain valid until you manually revoke them. However, temporary security credentials obtained through IAM roles and other features of the AWS Security Token Service expire after a short period of time. Use temporary security credentials to help reduce your risk in case credentials are accidentally exposed. Learn more about best practices for managing AWS access keys.
1
2
3
4
getQueryResultsResult = amazonAthena.getQueryResults(getQueryResultsRequest);

// 指摘内容
// This code might not produce accurate results if the operation returns paginated results instead of all results. Consider adding another call to check for additional results.

5. 余談

某約20KStepのJavaプロジェクトに対して、AWS CodeGuruをかけたのですが、ヒットしたのは「指摘されたコード」に記載のAWSのAPIに関する2種類の指摘のみでした。。

これからユーザからのフィードバックを受けてどんどん賢くなっていくとのことなので、今後に期待しましょう!

「某約20KStepのJavaプロジェクト」は、SonarQubeによるバグ指摘はない状態となっています。