はじめに
こんにちは。なたでです。
今日はシステム障害/バグ/不具合が発生した時に、どのように問題を解決するか、そのテクニックについて紹介します。ここで紹介するテクニックは、本に書いてあったというものではなく経験から来たものですが、大まかな流れは同じなのではないかなとは思います。
再発防止策編も作っているので気になった方は読んでください。
バグ管理システムの利用
問題が発生した時に、その問題ごとにバグ管理システム/バグトラッキングでバグチケットとして管理する必要があります。バグ管理システムで残すことで次のようなメリットがあります。
チケット管理のメリット
- 問題が発生した時の振り返りができる
- 再発防止策を考えることが出来る
- 似たような問題が発生した場合にどのような解析を行えばよいかのヒントになる
- 他の人にも解析情報を展開できる
- バグの解析を手伝う際にどこまで解析したかが分かる
- 修正後の確認をする場合もどういった確認をしたらよいかが伝えやすい
- 対策をした際にどのチケット番号に対する習性なのかも管理できる
- ソースコードの注釈履歴からどの行がどういった理由で変更したか分かる
- 進捗情報が分かる
- バグの問題がいつ報告されて、今どこまで調査、修正を終えているか把握できる
解析情報について
解析した状況は都度都度チケットにコメントとして書き込むとよいですが、長くなって読みづらくなる可能性もあります。大まかな状況はチケットの説明に記載しておきましょう。このようにしておくことで、現在のチケットの状況がすぐに分かるようになります。
バグ管理システムの紹介
オープンソースのバグ管理システムを紹介します。
情報整理
整理内容
問題が起きた際に色々な観点から調べることができますが、どれをするにしても情報整理をするのが先決です。次のような情報を整理しましょう。
- 発生環境情報
- 現場の環境
- ネットワークシステム
- 各機種のバージョン、機器の状態、使用期間
- 使用方法
- 言語情報
- 主観的な部分も含まれる情報
- 発生を目撃した人の報告した言語情報
- いつ発生したとしているか
- ログ情報
- 発生した現象の事実の情報
- ログから分かる情報
- いつ問題が起きるログが現れるか
時系列情報の作成
発生時刻というのがなかなか難しいということがあります。時刻Xで問題が発生したという報告があったとしても、実際にはその前から起きているという場合がありますし、いくつかの手順が複合的に重なることで発生することもあります。
これらを考えて、次のような情報を時系順にまとめていきます。特にまとめる際は、それが主観情報なのか、客観情報なのかも伏せて記載します。言語情報は誤っている可能性もあることを踏まえて、時系列情報を解析に使用していきます。
- XXXというログが記録される
- XXXという報告をXXXがうける
- XXXという操作をしたと証言した操作のログが残っている
情報を整理する場合は、どの機器に残っていたかも時系列に記載しておきましょう。例えば、このネットワーク構成のこの位置にある機器に残っているログなど。
バージョンを変更した場合は、この時刻にバージョンを変更したという情報も残しましょう。もしバージョン変更後に問題が起きた場合は、そのバージョン変更が引き金になっている可能性があるためです。また、直近でリセットした時刻も残しておくと良い場合もあります。例えば、積み重なりによって起きる問題であれば、リセット直後は起こらないという切り分けが可能です。
不具合解析
同様の不具合がないかの調査
発生した事象について、過去に似たような問題が起きていないかを調査するために、バグ管理システムで不具合の内容を調べます。
同様の報告が見つかった場合は、不具合の再発を疑いましょう。何かの修正のデグレかもしれないですし、他の不具合発生パターンの想定が漏れていた可能も考えられます。チケットに記載されている内容を読んで、解析の流れがヒントにしましょう。なお、過去の報告が不具合解決まで終えていない場合であっても無駄ではなく、不具合が解決できていなかったチケットを寄せ集めて、不具合の発生状況の共通点調査など大規模に解析するアプローチもとれます。
再現するかの調査
情報整理の中で、特定のログに基づいた操作を行うことで同様の問題が起きることが確認できた場合は、バージョンの切り分け作業が可能です。例えば、バージョンAの後に、バージョンBをリリースしたとします。ここで、バージョンAでは発生せずに、バージョンBで発生した場合は、バージョンBの修正の変更差分に原因があることが確定します(以下、デグレ)。
二分探索によるデグレのチェック
例えばバージョンを、1, 2, 3, 4, 5, 6, … など複数リリースしている場合は、二分探索によるバージョン特定をすることで、数回の確認でバージョンを特定することが可能です。
例えば、これまで20回リリースして、バージョン20でバージョン7で入れたデグレを発見したとします。その場合、次のように二分探索で確認することで6回の試行で特定ができ、1つのバージョンずつ遡って確認しなくても特定できます。
- バージョン20で試験 → 発生する
- バージョン1で試験 → 発生しない
- バージョン10で試験 → 発生する
- バージョン5で試験 → 発生しない
- バージョン7で試験 → 発生する
- バージョン6で試験 → 発生しない
発生時のログとの照らし合わせた解析
通常、ログが残っていればログと同じ手順を踏めば、現象が発生するはずです。ただ、ログに問題の操作となる手順が全て記録されていることは少なく、ログと同様の手順を実施しても再現性がしない場合も起こりえます。
環境とシナリオを合わせる
例えば、通信のログしかなく、その通信を行う手順まではログに残っていないといった場合に、どのような操作をしたらそこに至るのかが分からないといったことです。こういった場合は、発生したシナリオを想定します。できる限り、発生したシステム環境を合わせたうえで、不具合が発生した時のログから何をしていたかを想定して、その操作を行うのです。
連続動作試験
それでも再現できない場合は、加速劣化試験のように指定した手順を自動で高速に実施することで再現させられる場合があります。試験手順を自動化することで、例えば通常時は1日に10回行うような操作を、1分に10回行うようにして連続稼働させます。これによって、発生確率が低いクロスシーケンスによる問題も引き起こすことが可能になります。
なお、連続稼働を行う際は、各操作にランダムなウェイトを入れて、手順にランダム性を持たせることが大事です。これは全く同一の手順となることを防ぐためです。
他の不具合のログとを組み合わせた解析
現場で取得したログからは解析できなかった場合でも、過去に取得したログとを組み合わせて解析することも可能です。例えば、問題がありそうなログは残っているのに、そのログが残るような手順が分からないといった場合は、そのログを他で採取したログに対して検索をかけることで次のような解析が行えます。
- 他のログでも同様のログが残っているが、問題は起きていない。
- 問題だと思ったログは無関係なログだった
- 他のログでも同様のログが残っており、問題は起きている
- その他のログからは手順の情報も残っており、発生手順を発見できた
統計を使用した解析
問題が起きたときに「操作X」のログが残っていた場合に、「操作X」という操作は過去何年に渡って何万回も行っていたといった場合、その「操作X」な問題ではない可能性が高いです。このように、操作内容だけに着目するのではなく、操作回数や期間に着目をした解析を行います。
過去の発生した時刻をヒストグラムのようにまとめることで、12:00や、13:00といった時間が切り替わったタイミングで起きやすいことが分かり、定期実行処理に問題がある可能性があるということを導くこともできます。
不具合対策
再現する不具合の対策
再現させることが可能であれば、あとは時間さえあれば原因を調べることが可能だと思われます。原因が分かればそれの対策を行い、再現手順を実施して問題が起きないことを確認すればよいだけです。
コードが複雑であれば、デグレの調査も行いましょう。
再現しない不具合の対策
再現しない不具合の場合は、原因が分からないため根本対策は行えないことになります。しかし、何らかの対策を行う必要が求められる場合があります。その場合は、3つの対策が考えれます。
機器の回収
不具合が過去にその機器でしか起きていない場合に、機器で何らかの問題が発生している可能性があります。そういった場合は、回収することでより細かい状況が把握できたり、再現させられる可能性があります。
ログの強化
不具合の原因が、ログが足りないために解析ができない場合はログを強化して、再度不具合が発生するまで待つという方法があります。
フェイルセーフ機能を導入
フェイルセーフというのは、システムに問題が発生しても安全側に倒す動作をするというものです。例えば、メモリリークの問題があったとして、その根本対策が分からない場合は、メモリの状況を監視して状況によって何らかの動作を行うといった機能を導入するといった機能を入れる。通常利用中はその状態は短時間で終わるにもかかわらず、それが長期間その状態に陥った場合に元に戻すという機能を入れるというのも一つの案かと思います。
おわりに
お疲れ様です。最後まで読んでいただきありがとうございました!
今後は、再発防止編と、障害に強い設計編についても記事にできたらいいなと思います。
コメント