断ち切られる糸、扉に隠された屋敷の謎


## 📝トラブル概要
犯人の足跡を追跡するために糸(LOG)を取り付けたのに、その糸が切り離されてしまう。この謎を深掘りしていく。


## 🔍発生の経緯
1. Userがエンドポイントにアクセスした時のチェックをするためログを取得しようと思う
2. ```/routes/todo.py```に/utilites/loggerのログ関数をエンドポイントがコールされる箇所にセット
3. urlのエンドポイントにアクセス


## ⚠️エラーメッセージ or 症状
* ログが出力されない、しかしサーバーログでHTTPステータス200を返却を確認

## 💥 原因
* pythonの ```print()``` 関数の仕様


## 🛠 対応策

```python 
# flashオプションをTrueにする対応
print("message", flush=True)
```

## 💡再発防止・気づき
* pythonのprint()関数の仕様。
* 環境によってルールがあることを学ぶ。
* ドキュメントを読むことの重要性を知る。
* ユーザーアクションの時にログを吐き出さないのは個人情報を打ち込んだものを「システムエンジニアがログを消し忘れたら大変なことになる」からという思いやりから成り立ったのではないかと考察する（真実は謎の方が美しい）
* ルーティング記載が複数ないかgrepの使い方が勉強になった。

``` bash 
# appディレクトリ以下に"/projects"がある箇所を表示してくれる
grep -r "/projects" ap
Binary file .//app/routes/__pycache__/project.cpython-310.pyc matches
.//app/routes/project.py:@project_bp.route('/projects', methods=['POST'])
.//app/routes/project.py:    log(ICON["ROUTING"], "CALL: POST /projects")
.//app/routes/project.py:@project_bp.route('/projects', methods=['GET'])
.//app/routes/project.py:    log(ICON["ROUTING"], "CALL: GET /projects")
.//app/routes/project.py:@project_bp.route('/projects/<int:project_id>', methods=['GET'])
.//app/routes/project.py:    log(ICON["ROUTING"], "CALL: GET /projects/<id>")
.//app/routes/project.py:@project_bp.route('/projects/<int:project_id>', methods=['PUT'])
.//app/routes/project.py:    log(ICON["ROUTING"], "CALL: PUT /projects/<id>")
.//app/routes/project.py:@project_bp.route('/projects/<int:project_id>', methods=['DELETE'])
.//app/routes/project.py:    log(ICON["ROUTING"], "CALL: DELETE /projects/<id>")

# 行番号も表示してくれる
grep -rn "/projects" app
Binary file .//app/routes/__pycache__/project.cpython-310.pyc matches
.//app/routes/project.py:12:@project_bp.route('/projects', methods=['POST'])
.//app/routes/project.py:14:    log(ICON["ROUTING"], "CALL: POST /projects")
.//app/routes/project.py:17:@project_bp.route('/projects', methods=['GET'])
.//app/routes/project.py:19:    log(ICON["ROUTING"], "CALL: GET /projects")
.//app/routes/project.py:22:@project_bp.route('/projects/<int:project_id>', methods=['GET'])
.//app/routes/project.py:24:    log(ICON["ROUTING"], "CALL: GET /projects/<id>")
.//app/routes/project.py:27:@project_bp.route('/projects/<int:project_id>', methods=['PUT'])
.//app/routes/project.py:29:    log(ICON["ROUTING"], "CALL: PUT /projects/<id>")
.//app/routes/project.py:32:@project_bp.route('/projects/<int:project_id>', methods=['DELETE'])
.//app/routes/project.py:34:    log(ICON["ROUTING"], "CALL: DELETE /projects/<id>")
```
* 💡 flushは溜めたものを吐き出すイメージ。
  
[引用元](https://docs.python.org/ja/3/library/functions.html#print)
>print(*objects, sep=' ', end='\n', file=None, flush=False)
objects を sep で区切りながらテキストストリーム file に表示し、最後に end を表示します。sep 、 end 、 file 、 flush を与える場合、キーワード引数として与える必要があります。

>キーワードなしの引数はすべて、 str() がするように文字列に変換され、 sep で区切られながらストリームに書き出され、最後に end が続きます。 sep と end の両方とも、文字列でなければなりません。これらを None にすると、デフォルトの値が使われます。 objects が与えられなければ、 print() は end だけを書き出します。

>file 引数は、 write(string) メソッドを持つオブジェクトでなければなりません。指定されないか、 None である場合、 sys.stdout が使われます。表示される引数は全てテキスト文字列に変換されますから、 print() はバイナリモードファイルオブジェクトには使用できません。代わりに file.write(...) を使ってください。

>出力がバッファ化されるかどうかは通常 file で決まりますが、flush キーワード引数が真ならストリームは強制的にフラッシュされます。

>バージョン 3.3 で変更: キーワード引数 flush が追加されました。


1891年 ヴィクトリア朝のシャーロックホームズの世界に3名の生成AIが突如現れる。
現代社会の不可思議なビジネス課題をこの3名の生成AIが謎に迫る。

ビジネスコンテンツ × ミステリー × 生成AIの世界観をお楽しみください。

https://roi-blog.playground.style

ROI探偵事務所の事件で使用した知識をこちらに掲載しています

https://business-on.playground.style