Loggerについての備忘録

## はじめに
Loggerの備忘録です💁
初心者です😅
間違えてる部分多々あると思います。
もし見つけた場合、ツッコミいただけると助かります🙇

それにしてもログは奥が深い笑
また各モジュールに対してのログ作成は別途、備忘録を作成予定。

## 🦁 結論 🦁

:::note info
押さえておくべき点
* Pythonでログを生成することがコンテキストを生成し、エラーの解決などに役立てられる
* 事前にフォーマットを作成（事前にログの目的などを明確にする）
* ログを生成することができる
* ログレベルをカスタマイズできる
* logger.error() メソッドは、エラーレベルのログメッセージを記録するために使用
* ログレベル、カテゴリー別でログ記録することが可能
* ロガーは様々な出力先にログを送ることが可能
* Pythonの標準ライブラリのloggerよりも高度な機能を提供してるロギングライブラリもある（Loguru など）
* 小規模な場合は“logging.basicConfig”を使用（グローバル設定）
* 大規模の場合はloggerを設定用のファイルを作成して、各モジュールに合わせて作成する
:::

:::note warn
使用タイミングは？
* 処理の前後の時間を測りたい時
* 関数の呼び出しの詳細を確認したい時
* アプリケーション起動、終了（セキュリティ観点）
* エラー発生した時（意図的含む）
* システム警告が必要な時
* 外部APIの呼び出し（リクエスト＆レス）
:::

:::note alert
注意点
* 過剰なログ出力しない
* 個人情報、セキュリティ情報はログには残してはダメ（漏洩に繋がる）
* 大規模になる場合は「非同期ロギング」を利用すべき
:::

## ログレベル（低い順）
* DEBUG: 開発中に詳細な情報を出力するために使用
内部変数の値、状態の変化、小さな関数呼び出しの詳細など、詳細なデバッグ情報

* INFO: 通常動作の確認に役立つ情報を出力
正常な動作の確認に使用。例えば、アプリケーションの起動や正常終了、重要な処理の開始や完了など。

* WARNING: 想定される問題を示すために使用
予期しないことが起こったが、アプリケーションは正常に動作し続ける状況。設定の非推奨、推奨されないAPIの使用など。

* ERROR: 重大な問題によるエラーを示すために使用
APIの呼び出しエラー、ファイル読み込みエラーなど。

* CRITICAL: 非常に重大な問題を示すために使用
システムのクラッシュ、重大なデータ損失など。



## 基本構文
```python:sample.py
import logging

logging.basicConfig(level=logging.INFO)

# 処理
logging.info(f”表示させたいコメント”)

# INFO:root:表示させたいコメント
```

### ログ情報をカスタマイズ
```python:sample.py
import logging

# ログの基本設定
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# 何かしらの処理
try:
    # エラーを発生させる可能性のある処理
    # 例: result = 1 / 0
except Exception as e:
    # エラー発生時のログを記録
    logging.error("エラーが発生しました: %s", e)

# 別の通常のログ記録
logging.info("このメッセージは情報ログです。")
```

### ロギングコンテキスト　プレースホルダー　一覧
#### 基本3つの型
* %(asctime)s: ログが記録された日時（例: 2023-03-15 12:34:56,789）

* %(levelname)s: ログレベル（DEBUG,INFO,WARNING…）

* %(message)s: 実際にログ記録時に指定したメッセージ
```python:sample.py
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

logger.info("表示させたいメッセージ")
# ログ出力は”2023-03-15 12:34:56,789 - INFO - 表示させたいメッセージ”
```


* %(name)s: ロガーの名前。ロガーを作成する際に指定した名前
```python:sample.py
import logging
logging.basicConfig(format='%(name)s: %(message)s')
logger = logging.getLogger("MyLogger")  # 名前を定義

logger.info("表示させたいメッセージ")

# ログ出力は”MyLogger: これはテストメッセージです"
```

* %(pathname)s: ログイベントを発行したソースファイルのフルパス
```python:sample.py
import logging
logging.basicConfig(format='%(pathname)s: %(message)s')
logger = logging.getLogger(__name__)
logger.info("パス名のテスト")

# ログ出力は”実行中のスクリプトファイルのフルパス”
```

* %(filename)s: ログイベントを発行したファイルの名前
```python:sample.py
import logging
logging.basicConfig(format='%(filename)s: %(message)s')
logger = logging.getLogger(__name__)
logger.info("ファイル名のテスト")

# ログ出力は”スクリプトファイルの名前”
```

* %(module)s: ログイベントを発行したモジュールの名前
```python:sample.py
import logging
logging.basicConfig(format='%(module)s: %(message)s')
logger = logging.getLogger(__name__)
logger.info("モジュール名のテスト")

# ログ出力は”Pythonスクリプトのモジュール名（ファイル名から拡張子を除いたもの）”
```

* %(funcName)s: ログイベントを発行した関数またはメソッドの名前
```python:sample.py
import logging
logging.basicConfig(format='%(funcName)s: %(message)s')
logger = logging.getLogger(__name__)

def my_function():
    logger.info("関数名スタート")

my_function()

# ログ出力は”my_function: 関数スタート””
```

* %(lineno)d: ログイベントを発行したソースコードの行番号
```python:sample.py
import logging
logging.basicConfig(format='%(lineno)d: %(message)s')

# この行の行番号は4です
logging.info("ログのテスト")

# ログ出力は「4: ログのテスト」
```



## ログをファイルに出力する方法
```python:sample.py
import logging

# ロガーの設定
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

# ファイルハンドラの作成（ログをファイルに出力）
file_handler = logging.FileHandler('myfile.log')
file_handler.setLevel(logging.INFO)

# フォーマッタの設定（ログメッセージのフォーマットを定義）
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)

# ロガーにハンドラを追加
logger.addHandler(file_handler)

# ログの記録
logger.info("ファイルにログを記録")

```


## logger error()　の使い方
* 例外処理
```python:sample.py
try:
    # エラーが発生する可能性のあるコード
except Exception as e:
    logger.error("エラーが発生しました: %s", e)
```

* エラーが発生させる時の記録
```python:sample.py
if not valid_condition:
    logger.error("無効な状態が検出されました")
```