イノベーション エンジニアブログ


株式会社イノベーションのエンジニアたちの技術系ブログです。ITトレンド・List Finderの開発をベースに、業務外での技術研究などもブログとして発信していってます!


このエントリーをはてなブックマークに追加

例外のお話

お久しぶりです、SRE チームの syoga です
今年の夏は激アツでしたが皆様いかがお過ごしでしょうか?

ふわふわなかき氷が流行っているという事で、天然氷を使ったかき氷が人気だそうです、天然氷だと知らなければ食べてる人はあまり意識しないと思われますが、こだわりをもった職人さんがいるという話を聞きました。

上記のこだわりについては、今回の話にあまり関係ありませんが、皆様ログ出力していますか?

という訳で今回は運用・保守をする側から見てこんなコードはイヤだ!
というテーマで記事をしたためたいと思います。

ある日の出来事

弊社のサービスではアプリケーションエラーが発生した場合は、メールや Slack で通知が来ますが、通知が来たらまずはアプリケーションサーバでログを確認します。

さしずめ死体(ログ)から犯人(不具合)を特定する法人類学者の某博士のように目を皿にして調査をします、さてログを確認したら犯人(不具合)の特定をすべく 凶器(コード)を調査します。

今回はバッチ処理で例外を投げていたため、どの関数でエラーが発生しているのかは容易に特定ができました。

該当の関数で例外を投げている箇所を確認するとそこには、コメントも何もないコードが…

public function getIdsArray($param)
{
    $count = $param->count();
    if ($count < 1) {
        throw new Exception();
    }
    for ($i=1; $i<=$count; $i++) {
        $param->setCountNumber($i);
        $item = $param->getItems();
        foreach ($item as $val) {
            $idsArray[] = $val['id'];
        }
    }
    return $idsArray
}

パッと見ただけでは一体何が原因で例外が投げられたのか分かりませんでしたが、ちょっと確認したところDBの検索結果をパラメータとして渡し、検索結果が 0 件なら例外を投げている事が分かりました。

関数の呼び元にも、関数内にもコメントがないため何故 0 件だと例外を投げるのかここから読み解くのは個人的に難しく感じます。

例外を投げているという事はプログラムで想定外の出来事が発生した場合なのですが、if文で判定した結果例外を投げているので想定できる範囲内なのかなと思い、個人的には例外を投げるのはちょっと乱暴に見えてしまいます。

しかも、例外の中身は空という男気溢れる例外処理!!

そんな男気例外処理ですが、調査する方はまずは検索結果の件数を判定する理由を 関数の呼び元のクラスから調べました。
0 件は想定外なのか?
あ、どのテーブルを検索しているんだろう…等
モヤモヤしながら調査をします。

調査した結果、パラメータの count が 0 件になる事を想定していない処理であり、該当バッチ処理が複数回実行された場合は、2回目以降必ず count が 0 件になるという事が分かりました。

今回はデータ不整合が発生した事が原因で、バッチ処理が複数回動いていました。

調査には時間がかかる

ただ、ソースを追って調査をするというのはやはり時間がかかるので、パッと見て処理が分かるようになっていると運用・保守をしている者としては嬉しいです、例えば以下のようにコメントやログが入っている場合はどうでしょうか。

public function getIdArray($param)
{
    $count = $param->count();

    // XX テーブルの検索結果を判定
    if ($count < 1) {
        // 検索結果が 0 件となる場合は 1 度実行されている
        // 通常は有り得ないため例外を投げる
        $loging('Err:XXテーブルの検索結果が 0 件でした');
        throw new Exception('エラーコード');
    }
    for ($i=1; $i<=$count; $i++) {
        $param->setCountNumber($i);
        $item = $param->getItems();
        foreach ($item as $val) {
            $idArray[] = $val['id'];
        }
    }
    return $idArray
}

まず、例外の通知が来た時点でエラーコードから大体のエラー内容が特定でき、ログを見ればどのテーブルを検索してエラーとなったのか大まかには判断が付きます。

さらに、この処理では 0 件は想定外という事が分かりますし、1度実行されている事が原因という事もソースを見れば一目瞭然なので、何故複数回実行されたかを調査するだけで済みます。

このように、ちょっとコメントやログを記載するだけで後々調査をする我々のような人間はとても助かります、コーディング中はその後の保守・運用について忘れがちになりますが、そのコードを誰かがメンテをする可能性があるならば、意識してコーディングしていただきたいです。

合わせて読みたい! ログのお話

それでは皆様、残り少ない夏を満喫しましょう。