nikkie-ftnextの日記

イベントレポートや読書メモを発信

pydantic-settingsで作るCLI、LogfireでPydanticによるパース結果を収集できるじゃん!

はじめに

さいごのソリスト、ううう...😭😭😭(ユーフォ3期一挙放送見た) nikkieです。

むふふ、すごいことに気づいちゃいました〜。
Pydantic社が構想するLogfire、こいつはやべーぞ!

目次

pydantic-settingsでCLIが作れる!

argparseすきすきの民でしたが、オプション引数を環境変数からも指定できるサポートが魅力的すぎて、初手はpydantic-settingsを選びたくなっています

Logfire

Pydantic社がリリースした可観測性(observability)ツール。
SaaSとPythonパッケージの2つがあります。

先日のみんなのPython勉強会でも、PydanticAIとLogfireを簡単に連携できると紹介されました1。

今回pydantic-settingsでCLIを作る中で気づいちゃったんですよね。
PydanticAIと簡単に連携できるなら、pydantic-settingsとも簡単に連携できるのでは、と

pydantic-settingsによるCLIで、Pydanticによるパース結果を収集する

ドキュメントのトップページの内容をやっていきます。

logfire.pydantic.dev

SaaSのLogfireの設定

  • https://logfire.pydantic.dev/login からログイン
    • GitHubアカウントでログインしました
  • プロジェクトを作成(「New project」)2

  • プロジェクトでWrite Tokenを発行(プロジェクト作成後の指示に従えばよいが、プロジェクトの「Settings」を操作している)

ドキュメントにはlogfireパッケージに含まれるCLIを使った例(logfire auth・logfire projects use)がありますが、これは本番向けではないと知ったので、Write Tokenにしました。
https://logfire.pydantic.dev/docs/#__tabbed_2_1
この記事ではlogfireパッケージのCLIは使っていません

プロジェクトのWrite Tokenを環境変数LOGFIRE_TOKENに設定します。
この状態でPython処理系の対話モードを使って動作確認できます。
https://logfire.pydantic.dev/docs/#__tabbed_2_2 の例を対話モードで実行しています。

% uv run --with logfire python
>>> import logfire
>>> logfire.configure()
Logfire project URL: https://logfire.pydantic.dev/ftnext/...
>>> logfire.info("Hello, {name}!", name="world")
15:59:35.328 Hello, world!

プロジェクトのLiveを見ると

上記の動作確認によるspanが確認できました!3

CLIアプリケーションでLogfireを使う設定

  • logfireパッケージを依存に追加
  • Pydanticのパース結果を収集するコードを追加
import logfire

logfire.configure()
logfire.instrument_pydantic()

全体像

CLIを呼び出すだけで、コマンドラインで渡した引数のパース結果が記録されます!

% uv run --quiet cli.py position エミリー 5
01:02:02.731 Pydantic Settings validate_python
エミリーエミリーエミリーエミリーエミリー
Logfire project URL: https://logfire.pydantic.dev/ftnext/...

入力と解析結果がバッチリ記録されています!

{
    'input_data': {
        'position': {
            'string': 'エミリー',
            'number': '5',
        },
        'option': None,
    },
    'result': Settings(
        position=Position(
            string='エミリー',
            number=5,
        ),
        option=None,
    ),
    'schema_name': 'Settings',
    'success': True,
    'validation_method': 'validate_python',
}

動作環境

  • uv 0.4.27 (Homebrew 2024-10-25)
  • Python 3.13.0
  • pydantic-settings 2.7.1
    • Pydantic 2.10.4
  • Logfire 2.11.1

LogfireのIntegration

Integrationという仕組みで実現しています。
https://logfire.pydantic.dev/docs/integrations/#custom-integrations

logfire.pydantic.dev

logfire.instrument_pydantic()の第1引数recordは、以下の値を取りえます。
https://logfire.pydantic.dev/docs/reference/api/logfire/#logfire.Logfire.instrument_pydantic

  • "all"(デフォルト値)
  • "failure"
  • "metrics"
  • "off"

今回はデフォルト値の"all"で試していますが、データのバリデーションに失敗したときだけ記録が残ればいいのであれば"failure"の指定になりますね

他にも記録の指定をクラス単位にしたり、タグを付けたりもできるようでした(宿題事項)

終わりに

pydantic-settingsで作るCLIにLogfireを組み込めました。
CLIに渡した引数とPydanticによるパース結果を記録してみました("all")

2024年5月のUS PyConに行った方から「Pydantic社のブースでLogfire紹介してたよ」と教えてもらった記憶があります。
そのときは「なんでまた?」という感じだったのですが、実際に触って、Pydantic社がLogfireをリリースしたのに納得しています。
pydantic-settingsの例から、Pydanticが使われるあらゆる場面でLogfireの出番があります!4
広い市場を獲りにいったということですね(最良の開発者体験を構築というビジョンを実現するために!)


  1. 5代目LT王子襲名、おめでとうございます!
  2. プロジェクト作成ではスクショ用にプロジェクトを作りました(ログを記録するプロジェクトとは別です)
  3. 動作確認のログだけ示すために絞り込んでいます(PydanticAIが組み込まれてて、日本語でやりたいこと書いたらSQLになったぞ!)
  4. Integrationのドキュメントから、DjangoなどPydanticがデフォルトで入ってなさそうな領域でもLogfireに連携できるようでした。OpenTelemetry互換を謳っているようです。いまは未知の概念、宿題だ...