
この記事は、「#doda BizDevOps Group Advent Calendar 2025」の 25 日目の記事です。
パーソルキャリア株式会社の デジタルテクノロジー統括部でリードエンジニアを務めている井上[^1]です。
バッチ基盤領域の刷新プロジェクトにおいて、リソースのレビュアーとワークフローの整備をしています。
バッチ基盤の運用の過程で、エラーメッセージについて考察したことを共有します。
figure 01 : Apache Airflow[^2] の Web UI でログメッセージを閲覧している画面
前提条件
当記事で取り扱うのは、アプリケーション実行中に想定内の例外が発生した際、出力するメッセージを対象としています。
取り扱わないこと
- ログの解説
- ログの設計
- ユーザーの画面操作に依存するメッセージ設計
- ユーザーの行動分析を行うためのメッセージ設計
- 想定外の例外に対するアプリケーション設計
- インシデント対応のフォレンジック
結論
メッセージを読んだ人が、どのような初動を起こすべきかを指示する内容を設計することで円滑な運用へ繋がります。
想定内の例外と想定外の例外
アプリケーション実行中に起こる例外は、想定内と想定外の 2 種類があります。
想定内の例外
「想定内の例外」は、アプリケーションが安定して動作し続けるために適切に処理されるべき例外です。
開発者が予測し、適切に処理することを計画しているエラーや問題を指します。
例を挙げます。
- ファイルが見つからないこと。
- ユーザーが数値ではない値を入力したこと。
- ネットワーク接続がタイムアウトしたこと。
アプリケーションは、ユーザーフレンドリーであることを保証する努力する必要があります。 例外が発生した場合、適切なメッセージを表示したり、再試行を促したりできます。
今回取り上げるのはこちらです。
想定外の例外
「想定外の例外」は、開発者が予測していなかったエラーや問題を指します。
システムのバグやハードウェアの故障、予期しない外部要因によるものが多いです。
通常の操作中に発生しないと考えられ、アプリケーションに対して重大な問題を引き起こす可能性があります。
例を挙げます。
- メモリ不足。
- ハードウェア障害による入出力エラー。
再試行をしても改善しないので、手立てを考え実行する必要があります。
手立てを考える材料として、ログに何を記録するべきかを検討する必要がありますが、今回取り上げません。
例外に対する画面メッセージ
例外が発生した場合、適切なメッセージを表示したり、再試行を促したりすることができます。

figure02: 存在しない検索条件を実行した際に、他の検索条件を行うことを促すメッセージ
ユーザーの入力ミスによる場合は、画面に行動を促すメッセージを出力することで再入力を期待できます。
このパターンは、想定しやすくまた効果も高いアクションとなります。
今回は、アプリケーションの中でも「バッチ」のメッセージについて掘り下げます。
バッチの特長
バッチは、特定の時間や条件に基づいてデータ処理を実行する方式を指します。
システムパフォーマンスを最適化、大量のデータを効率的に処理するために使用します。
バッチ処理の特長を下記にまとめます。
| 特長 | 概要 |
|---|---|
| 非対話型 | ユーザーのリアルタイムの介入を必要とせず、自動的に実行します。夜間やシステムの使用が少ないリソースが余っている時間帯に大量データ処理を実行することができます。 |
| 一括処理 | 複数のデータやタスクを一括で処理します。同じ処理を複数回行う必要がなくなります。 |
| スケジュール可能 | 特定のスケジュールに従って実行します。例えば、毎日深夜に実行されるバックアップ処理などがあります。 |
doda の体験を企業、転職希望者へ提供できるようにバッチ基盤はデータ処理に携わることで支援しています。
企業が提供する求人票、転職希望者の希望条件、企業と転職希望者間の面接の進行状況といったデータを夜間や始業前に実行するようにスケジューリングを組んでいます。
転職希望者側へのサービス体験。
- 転職をサポート
- 豊富な求人数
- あなたに興味のある会社からオファーを受け取れる
転職希望者の入力データを元に、希望条件に合致する求人票の収集や、アシスタントが転職希望者へ提案する求人票候補をまとめたりしています。
企業側へのサービス体験。
- 転職活動している多くの登録者
- 採用ニーズの高い職種/年齢層の登録者が多い
- 採用課題に合わせて採用手法が選べる
企業側の希望条件に合致する転職希望者を割り出してアプローチします。
バッチ基盤は以下のような用途を管理実行しています。全量ではなく一部をまとめています。
| 用途 | 概要 |
|---|---|
| データ移行と変換 | データベース間のデータ移行、データのフォーマット変換、データ集計など |
| バックアップとリストア | システムのバックアップやリストア作業 |
| 定期レポート生成 | 日次、週次、月次のレポートを生成 |
| スケジューリング | ログファイルのローテーション、システム監視の閾値によるトリガーを自動実行 |
多くの求人票と、転職希望者を結びつけるために、データ処理を行ってマッチングの精度を上げるように取り組んでいます。
多くの求人及び面接の進捗などのデータを取り扱っているため、エラーが発生した際、迅速に回復手段を取る必要があります。
そのため、バッチ基盤の運用者としてエラー発生時のメッセージに対して掘り下げていくようになりました。
バッチの深堀
レビューを実施する過程で、エラー時に以下のメッセージを出力する実装がありました。
以下のサンプルは、実際のものを簡略して表現したものです。
XXXで異常発生。入力: YYY
レビューイへヒアリングを実施し、以下の回答を得ました。
- アプリケーション実行時、どの関数を実行しているか出力したいこと。
- アプリケーション実行中、トラブル時に原因特定をする手がかりが欲しいこと。
ヒアリング内容を集約すると上記の 2 点でした。
ヒアリング結果の分析
アプリケーション実行時、どの関数を実行しているか出力したいこと。
アプリケーション実行中、トラブル時に原因特定をする手がかりが欲しいこと。
関数の実装者の視点は、どの関数でトラブルを起こしたかを知るために、メッセージ設計をしています。
その視点を尊重しますが、アプリケーションの運用者という視点でみると欲しい観点が抜けています。
アプリケーションの「回復」をするために何をするべきかという観点です。 メッセージに、アプリケーションの「回復」のための指示を含めないと初動が遅れる要因や、読み手の経験値に依存して後続の動きを期待することになります。
読み手側にメッセージを読むこと自体、気が重い心理的不安を抱える要因になります。
よって、運用側の視点に立ったメッセージ設計する必要があります。
バッチは、ユーザー操作による画面へ即時メッセージ出力という手段を取ることができません。
データベースのテーブルの組み合わせや、ファイルといった他のアプリケーションの出力結果を 2 時間から 3 時間または、半日後に受け取って起動することが大半です。
タイムラグが発生するので、メッセージに含めなければ必要な情報を読み手側へ提供しなければ事象の再現や修正方法を実施できません。
どのような指示を期待しているのかについて掘り下げていきます。
メッセージの深堀
メッセージを設計するということは、想定しているエラーがあります。
その場合、何がエラーの原因なのかも予想がつきます。
しかし、想定している原因をメッセージの読み手側は把握していないことを前提とするべきです。
パターン1: 入力値の不備を想定
入力値の不備を想定している場合、再試行の際、入力のデータソースの整備が必要です。
入力値の不備が未修正だと再試行しても、失敗します。
回復としては、入力値となるデータソースを調査してデータ補正する必要があります。
例。
XXXで異常発生。入力: YYY
→
提案例。
ZZZテーブルの取得へYYYで絞り込み取得した結果に問題あり、検証し修正後再実行してください。入力値: YYY
エラー時に出力しているメッセージです。なので異常が発生していることは自明です。「異常発生」に類する言葉は、記載していません。
ライブラリに依りますが、メタデータとしてエラーレベルを出力しています。
上記のメッセージは、データベースから取得したデータに不備が発生して後続の処理が期待通りになっていない場合を想定しています。
アプリケーションとデータベースは、1 対 1 の関係ではなく、データベースを他のシステムと共有していることが利用シーンとして多いです。
そのため他のシステムによって、意図しないデータを登録している場合があります。
強調しますが、メッセージの読み手が知りたいのは、滞った運用を回復するためのアプローチです。
回復するために必要な行動をメッセージに含めることで、初動までの行動を速くできます。
初動の行動で回復しない場合、エスカレーション時の相談事項のたたき台として使用できます。
上記の提案例は、初動調査のための対象テーブルの提示と入力値の修正が終わってから再実行する旨を指示しています。
回復行動として、対象テーブルを提示し、データ補正が必要な状態ということを伝えています。
データ補正完了後に、再度アプリケーションを実行することで回復できます。
バッチ基盤は、行うべき要件に対してアプリケーションを分割しています。
また、アプリケーションも「Spring Batch」[^3] を採用しており、更に小さいタスクへ処理を分割するようにしています。
実際に採用しているメッセージを簡略化した一例はこちらです。
外部サービスへリクエストを送信した結果のメッセージです。
Long id =
Optional.ofNullable(service.select(item.id()))
.orElseThrow(
() ->
new ApplicationException(
"指定したXXX IDでYYY IDを取得できませんでした。YYY ID: %s"
.formatted(item.id())));
パターン2: 反復処理の複数発生時のエラーの想定
XXXで異常発生。入力: AAA XXXで異常発生。入力: BBB
反復処理の中でメッセージを出力する場合に留意することがあります。
反復処理で複数件のメッセージが出力する場合は、処理を工夫しないと複数行出力することになります。
100 件といった大量の件数を出力することになった場合は、ログファイルのサイズが大きくなったり、出力する行数は多くなり調査が難航することになります。
下記は Zip ファイルの解凍処理の一例です。
警告レベルのメッセージを出力する際に、可変部分を事前に処理をしてメッセージ出力の際に、カンマ区切りなどで出力するようにすれば一行で済むようになります。
try (ZipInputStream input = new ZipInputStream(Files.newInputStream(zipPath), StandardCharsets.UTF_8)) { ZipEntry entry = input.getNextEntry(); StringJoiner unsupportedExtensions = new StringJoiner(","); byte[] buffer = new byte[8192]; while (Objects.nonNull(entry)) { entry( entry, input, buffer, unzipDirectoryPath, zipPath, unsupportedExtensions, photoDetails); entry = input.getNextEntry(); } logUnsupportedExtensions(unsupportedExtensions); return photoDetails; } catch (IOException e) { throw new ApplicationException( "ダウンロードファイルパス:%s ZIPファイルの状態を確認してください。".formatted(zipPath), e); } private void logUnsupportedExtensions(StringJoiner unsupportedExtensions) { if (unsupportedExtensions.length() > 0) { logger.warn("サポートしている拡張子(jpg,jpeg,png)以外のファイル群が検出されました。担当部署へ連絡して確認依頼をしてください。 {}", unsupportedExtensions); } }
出力するメッセージのイメージは以下のような感じです。
XXXで異常発生。入力: AAA, BBB, CCC, ....
上記の工夫により入力値が散らばることなく、切り取ることが簡単になり、担当者への問い合わせやツールへ渡すなどに利用可能です。
まだいくつかありますが、頻出した例を挙げました。
メッセージ出力の内容や実装方法もまだまだ工夫が必要です。
実装者側で必要なメッセージは、必要最小限に留める努力をしなければトラブルが発生した際に、何も指針がない状態やノイズになります。
サービスを円滑に行う上でこの私見や経験をもっと掘り下げていく必要があります。
これが全てではないですし、別のサービスやツールを使い別の視点で検知、回復対応するアプローチも検討しています。
メッセージを読むうえで、読む立場や状況に寄り添っているかどうかを中心に据えて私見を展開しました。
運用してみて良くなった部分もありますし、ニュアンスなどを伝えることができず実装者の負担をかけてしまった部分もありました。
それでも良いサービスを提供するために歩みを止めないように深堀を続けていこうと思っています。
他の取り組みの紹介
バッチ基盤は、多くのバッチアプリケーションを抱えています。
その際に、アプリケーションの概要を把握することが、回復手段の速度へ直結していきます。
プロジェクトに紐づくバッチアプリケーションは、プロジェクトが完了すると、実装者は他のプロジェクトへ移っていきます。
記憶が風化すると最初からソースコードを読むことを強いられます。その際、理解を助けるためにアプリケーションの概要をドキュメント化して管理運用しています。
実装者以外もアプリケーションの概要を把握することができるように、ドキュメントをプロジェクトと一緒に登録しています。
以下が概要資料の抜粋です。

メッセージの工夫以外にも、上記のドキュメントを用意して属人化する暗黙知を回避できるように取り組んでいます。
このドキュメントをブラッシュアップして AI へ渡して、別言語への切り替えが容易にできるようになればと思っています。
最後に
タイトルは「チーズはどこへ消えた?」のインスパイアです。
自分のチーズが大事であればあるほどそれにしがみつきたがる[^4]
実装者の視点だけであるなら、どこの関数が期待通りでなかったのかが大きい関心事になります。
しかし、アプリケーションは作るまでがゴールではなく、使うことからスタートラインとなります。
アプリケーションを運用する立場になり、アプリケーションのトラブルが発生する際、メッセージに対して課題を感じるようになりました。
書籍や、OSS、ブログ記事、同僚との討論を通して今回の記事の下地を築きあげました。
自分の考えに固執することなく、恐れず新しい視点の考えを取り込んでいくのが本当に重要です。
作中で、現状に甘んじて、分析を怠り、辛い思いをするシーンがあります。その際にどの登場人物の行動を自分自身が取れるのか。
いつまでもチーズがあると思わず、現状の体制やアプローチを疑いブラッシュアップを行い続けていきたいです。
この記事も道半ばの私見でしかないので、また同僚と討論をしていきながら磨いていきます。
「僕もうあんな大きな暗やみの中だってこわくない。きっとみんなのほんとうのさいわいをさがしに行く。どこまでもどこまでも僕たち一緒に進んで行こう。」[^5]
磨いて築いたサービスやアプリケーションを通して。
自分のキャリアを伸張するため、期待を胸に抱いて doda の扉を叩いた転職希望者の方々、必要な人材を求めて求人票を託してくださった企業の方々はもちろん。
サービスへ真摯に携わっている人達の「さいわい」を得ることができると思って 2025 年を締めくくっていきます。
ここまでお読みいただきありがとうございました。
参考
- 増井 敏克, 実務で役立つ ログの教科書 基礎知識から収集方法・分析手法・トラブルシューティング・パフォーマンス最適化・機械学習での活用まで : 翔泳社, 2025, 288p. 978-4798192123.
- Spencer Johnson, チーズはどこへ消えた? : 扶桑社, 21 刷, 2000, 96p. 978-4594030193.
- Eric Carle, はらぺこあおむし : 偕成社, 1976, 25p. 978-4033280103.
- 宮沢賢治, 銀河鉄道の夜 : 角川春樹事務所, 2011, 120p. 978-4758435482.
URL
- https://airflow.apache.org/
- https://www.ipa.go.jp/security/index.html
- https://doda.jp/intro/
- https://www.saiyo-doda.jp/lp/tm/main/
- https://www.aozora.gr.jp/cards/000081/files/456_15050.html
- https://spring.io/projects/spring-batch
脚注
1. https://techtekt.persol-career.co.jp/entry/member/220317_01
2. https://airflow.apache.org/
3. https://spring.io/projects/spring-batch
4. Spencer Johnson, チーズはどこへ消えた? 扶桑社, 2000, p.30.
5. 宮沢賢治,「新編 銀河鉄道の夜」新潮社, 1994.

井上 剣一 Kenichi Inoue
カスタマープロダクト本部 プロダクト開発統括部 dodaシステムアーキテクト部 dodaシステムアーキテクト第2グループ リードエンジニア
2022年3月にパーソルキャリアへ中途入社。
最近は、地域の児童たちへ「チーズはどこへ消えた?」、「はらぺこあおむし」を読んだり聞かせたりしています。「はらぺこあおむし」のほうが人気がありますね。
※2025年12月現在の情報です。
