エラーをスタックトレースも含めて構造化ログで取得できる github.com/k1LoW/errors を作った

エラーパッケージを作った話です。

www.m3tech.blog

私は、上記のエントリの「ぼくがかんがえるエラー処理の要件」に完全同意*1で、パフォーマンスをある程度犠牲にしてでもスタックトレースを「カジュアルに」受け取りたいと考えています。

また、

tech.kanmu.co.jp

にもあるように「移行のしやすさ」も欲しいです。

というのも、

methane.hatenablog.jp

にあるように、将来的にGoの標準パッケージにスタックトレースを取得できる機能が登場する可能性があるからです。標準パッケージ最高。

で、

speakerdeck.com

に「独自に実装するのもおすすめ」とあったので、既存のエラーパッケージを参考に独自に実装してみました。

github.com/k1LoW/errors

github.com

特徴としては次のとおりです。

結局、標準パッケージである errors パッケージに追加した機能は

errors.WithStack(err error)スタックトレースを保持して、errors.StackTraces(err error)スタックトレースを取得する

だけです。

それだけのパッケージです。現時点では %+v%#v といったverbにも対応していません*2

シンプルな分、「 github.com/k1LoW/errors の導入」も「 github.com/k1LoW/errors からの移行」も楽だと思っています。

*1:少なくとも現在関わっているプロジェクトにおいては

*2:対応しようとしてみたが errors.Join 対応と併用が難しかったのでやめた

パッケージのgo.modのgoディレクティブのバージョンを最新の1つ前のマイナーバージョン(oldstable)に強制するoldstableを作った

確かに、あまり気にせずgovluncheckに引っ掛かったら即、最新バージョンに上げていたので良くないなあと反省。

というわけで、再発防止ということで作りました*1

github.com

これは何?

指定したgo.modのgoディレクティブのバージョンが最新の1つ前のマイナーバージョンかどうかを確認するツール、もしくはGitHub Actionです。

例えば最新のGoのバージョンが1.22.4だった場合、普通に使用するとgoディレクティブがマイナーバージョン1.21の最新のパッチバージョン(2024年7月1日時点では1.21.11)でないとエラーになります。

$ oldstable
Error: version of go directive in go.mod is not latest oldstable (oldstable: 1.21.11, current: 1.22.4)

1.22.4という最新バージョンでもダメで、1.21.10という最新ではないパッチバージョンでもダメです。govulncheckとの併用を想定しているので、厳しめなルールです*2

ちなみにGitHub Actionとしても提供されていて、次のように書くことでチェックできます。

# .github/workflows/oldstable.yml
[...]
    steps:
      -
        name: Check if version of go directive in go.mod is oldstable
        uses: k1LoW/oldstable@v1
        # with:
        #   go-mod-file: go.mod
        #   lax: false

laxモード

「最新バージョンの1つ前のマイナーバージョンの最新のパッチバージョン」が厳しいという人のためにlaxモードも提供しています。

これは、マイナーバージョンだけチェックする形になっています。

チェックルールとしては次のような感じです。

oldstable go directive lax mode (--lax) check
1.21.11 1.21.11 false ok
1.21.11 1.21.6 false ng
1.21.11 1.22.4 false ng
1.21.11 1.21 false ng
1.21.11 1.21.6 true ok
1.21.11 1.22.4 true ng
1.21.11 1.21 true ok

oldstable って?

actions/setup-go で使われていたaliasです。stable が最新バージョンで、oldstable がその前のマイナーバージョンの最新です。良さげな命名だったので使わせてもらっています。

というわけで

私が管理していて「主にツールではなくライブラリとして使うことを想定しているパッケージ」には随時入れていこうと思います。

こんな感じですね。

github.com

すでにgoディレクティブを1.22に上げているものが多いので、1.23のリリースまでお待ちくださいませ。

*1:というのも気をつけないといけないパッケージが多すぎるので...

*2:どうせgovulncheckでパッチバージョンを上げることを求められる

PHPカンファレンス福岡2024に参加した #phpconfuk

参加してきました。

phpcon.fukuoka.jp

今回は雨ということもあり、ちょっと子供のイベントごとのお手伝いをして、午後から参加しました(晴れだったら朝からベローチェの予定だった)。

とはいえ、いつものFFB。入った途端に一瞬でPHPカンファレンス福岡でした。いやあ最初から参加したかった!

参加者としてのカンファレンス参加

いろいろなプライベートな理由がありカンファレンス参加は、遠方だと難しい時期なのですが、そこは地元福岡、カジュアルに参加できて最高です。

しかも、全国からお話ししたい人、質問したい人が来てくれるわけで、「東京、いつもズルい!」と思うと共に「PHPカンファレンス福岡ありがとう!!!!!!!!!!!」となりました。PHPカンファレンス福岡ありがとう!

見かけた知っている人知っている人に(意を決して)話しかけて、近況を聞いたり昔話をしたり最近の技術トピックについて教えてもらったり、なんというか「カンファレンスの廊下」をいつも以上に意識して楽しみました。

とはいえずっと「廊下」ができるほどコミュニケーション能力があるわけではないので、元から聞きたいと思っていた発表を聞かせてもらったり、Ask the Speaker なら話しかけていいだろうと話しかけたり、していました。

「スポンサーブースも回るぞ!」と思っていたのですが結局「コミュニケーション能力の難」を発揮して回れたのは一部でした。いつかちゃんと全部回るという実績を解除したいし、ツアーに参加すればよかった。。。。

🍺

懇親会も2次会もひたすらに話していました。たまたまテーブルとご一緒させていただいた方と面白い話をしたり、話しかけたいと思っていた方( #EM問題集 な方や、 ななうぇぶ な方とか。ファンなんですよね。 )に、(多少失礼もあったかと思いつつ)聞きたいことを聞いたり質問したり、また、たまたま席が一緒だった方といろいろ話したり。

しっかり酔っ払いました。

これ↓もあまり覚えていなんですよね。。。

PHPerKaigiでも同じ体験をしたのですが、「k1LoWさんから聴くP山さんの凄さ・強さ」的なのが2次会で発生し、本当に本当に身が引き締まる思い。 がんばろうがんばろう。

daisuki.nichiyoubi.land

まあ、ここら辺はシラフでも話せる気がするので、大丈夫な範囲で話している気がする。たぶん。GMOペパボに来たらもれなく体感できます。皆さん是非!

2次会を企画運営してくださった cakephper さんこと市川さんいつもありがとうございます!!!!!!!

runn開発者会議

katzchum さんとも本当にわずかな時間でしたが時間をいただいてrunn開発者会議できました。

私が持っていった直近の課題はこれで、ポロポロと相談したら、シュッといい示唆をもらいました。最高!!

他にもいろいろタフな課題が残っていますが、ぼちぼち解決していきます。

それはそれとしてPHPカンファレンス福岡2024内でrunn developers conference 2024があったらしく、さらにキーノートスピーチがあったらしい...

https://k2tzumi.github.io/runn-developers-conference-fukuoka-2024-keynote-speech/1

まとめ

今回もPHPカンファレンス福岡でした。大変によかったです。最初から参加したかったけど、それはそれ、しょうがない。

ずーっと楽しかったです。

ありがとうございました!!

Go Conference 2024に参加した #gocon

Go Conference 2024に参加/登壇してきました。

gocon.jp

前日のUnofficial Pre Partyから参加させていただき、2日間Goの話題に浸かってしました。

moneyforward.connpass.com

2日に渡って理解した range over func

いろいろ楽しかったのですが、印象に残っていることを1つだけを書いておこうかと思います。

Unofficial Pre Party で MakKi さんがrange over funcのエラー処理という具体的なお話をしてもらい、感想戦で大盛り上がりしたあと、Go Conference 2024のトップバッターで tenntenn さんがさらに解像度を上げて紹介してもらえたのことで「range over func完全に理解した」になることができました。

speakerdeck.com

docs.google.com

iterパッケージに並んでいる関数を見て「全くわからん」となっていたところも説明してもらって「!!!!」となりました。

良い体験でした。

MakKi さんといえば、お昼をご一緒させてもらったのですがその時に紹介してもらったゲームサーバのアーキテクチャの話が最高に面白かったです。 依存の逆転というか、発想の転換というか、「すげえ!」と感心しきりでした。

github.com

発表と発音

そして、私も「Cleanup handling in Go」というタイトルで発表をしました。

speakerdeck.com

が、

セッション内でdonegroupというパッケージを紹介したのですが、ずっと発音を間違って「dˈɔːn grúːp」と読んでいたという...

正しくは「dʌn gruːp」です!!!!!!

正しくは「dʌn gruːp」です!!!!!!

正しくは「dʌn gruːp」です!!!!!!

この後、懇親会で散々いじられるわけですが、私はずっと頭を抱えていました...完全にやらかした...

というわけで

最後のアレは置いておいて、他にも多くのイベントが発生して、最高に楽しい2日間でした。 会場で初めて会えた方だったり、いつもカンファレンスで会える方だったり、残念ながらタイミングが会わずに会えなかった(お話できなかった)方だったり、本当に一期一会なカンファレンスにりました。

スタッフの皆さん、Goコミュニティのみなさんありがとうございました!

最近、参照したり共有したりすることが多いURL

soudai.hatenablog.com

gihyo.jp

scrapbox.io

scrapbox.io

よく参照するならまとめておけばいいじゃない。

ラインナップからフェーズ的なものについては察してください。

ガッチガチに「こうあるべき」というような話というよりも、モデリングやテーブル設計においての固定観念*1を崩すためのキッカケに使っていることが多い気がします。

ちなみに私は、十数年、散々失敗した挙句にこのような有益なURLを有益だと理解して参照したりしているわけで、最初から(もしくは短期間に)ここに行き着ける人ってすごいなと尊敬しています。

追記

そーだいさんから有益情報を教えてもらったので並べておきます。

*1:「(Webフレームワークの)モデルとデータベーステーブルを1:1にして終わり」とか

APIテスティングツールに必要なのはテストケースごとのIDなのではないか #cicd_test_night

先日、機会をいただきましてCI/CD Test Night #7でAPIテスティングツール*1を開発している中で考えていることをお話しさせていただきました。

testnight.connpass.com

詳細はスライドをご覧ください。

speakerdeck.com

APIテストはスモールテストと比べて効果は大きいがコストも大きい

私はAPIテストの一番の課題はこれだと思っています。

APIテストは、「APIに対してリクエストを投げてそのままテストする」というわかりやすさがあります。

また、テストあたりにおけるカバレッジの広さというメリットもあります。

なので、できればデメリットであるコストの大きさをなんとかしたいわけです。

この課題の解決には2つの方法があります。

  1. コストを小さくする
  2. 範囲を広げて効果を大きくする

先に、範囲を広げる方法について考えると

  • 作ったテストをそのまま負荷テストに使えるように
  • 作ったテストをそのまま本番環境のリグレッションテストにも使えるように
  • APIテストしていたらAPIスキーマとの合致も検証するように

というような方向性、言ってみれば一石N鳥にすることによって効果を大きくするというものになります。効果が大きければコストが気にならなくなるだろうという寸法です。

では、コストを小さくするにはどのようにするかというと「テスト自体を書きやすくする(実装コストを小さくする)」などがあるのですが、結局は実行コストの大きさ、特に実行時間の長さが際立ってきてこれを解決しないといけなくなります。

まず最初に解決する手段として挙げられるのは「テストの並列実行」だと思います。

しかし、並列実行にも限界があります。

その次に取れる手段は何でしょう?

インテリジェントにテストを実行する

もう全てを愚直に実行するのはあきらめて、効率よく実行していく必要がありそうです。

「効率よく」というのは、例えば、

  • 失敗しやすいテストから先に実行する
  • 失敗しないテストは通常は実行しない
  • 実行時間が平均的になるように分けて並列実行する

などです。

ちなみに、このようなアプローチは私が考えたわけではありません。

私は、Launchable社の方たちの発表やエントリを見て知りました。

そして、APIテストという実行時間の長いテストに向き合うようになって、このアプローチの効果に期待しはじめるようになりました。

APIテスティングツールに必要なのはテストケースごとのIDなのではないか

そして、タイトル回収です。

先述した「インテリジェントなテスト実行」を実現するためにはまず何が必要か?というと、「テストケースの一意な識別」です。

それぞれのテストケースを一意に識別できなければ「どのテストが失敗したのか」がわかりません。 識別できなければ特定のテストだけを実行することもできないし、指定の順番に実行するということもできません。

テストケースに識別子=IDがあれば、特定テストの実行や、任意の順番でのテスト実行も可能になります。

インテリジェントなテストを実現するための第一歩が「ID」だと考えます。

APIテスティングツールに必要なのは(まず)テストケースごとのIDなのではないでしょうか*2

IDによる識別や、IDを使った柔軟なテストの実行ができることで、コストを抑えたインテリジェントなテスト実行への道が開けます。

ちなみに、runnにおけるIDの利用については次のエントリをご覧ください。

zenn.dev

この考えに至るまでの話

実は、きっかけはこのXのポストです。

ここからテスト実行時間について意識して考えるようになり、今に至っています。

今回の発表やこのエントリは @zoncoen さんのポストへの私なりの回答となります。

考えるきっかけをくれた @zoncoen さん、発表する機会をくれた @ponkio_o さんありがとうございました。

*1:ここでいう「API」とはWeb APIやgRPCを指します

*2:多くのテスティングツールにおいては備えているものでもあります。ただ、私が開発しているrunnには最初なかったのです。ちなみに提案してくださったのは同じrunn開発者の @katzchum さんです

PHPerKaigi 2024に参加した #phperkaigi

今年も参加してきました。

phperkaigi.jp

聴講した発表へのフィードバックも終わり、このエントリで私のPHPerKaigi 2024はフィニッシュです。

#runn開発者会議

最近恒例の廊下での会議ですが、テストランナーのシンタックスの改善の方向性についてどうしてもしめじさん( @smeghead さん)から直接フィードバックをもらいたく、3日間「いつか会えるだろう」とフラフラしていました。 気にかけていただいた皆さんありがとうございました。無事邂逅できました!

runnのランブックの一級言語がYAML(?)なのでYAMLシンタックスをうまく使ってかつニーズを満たす構文が思いつけばいいのですが、もう一歩アイデアが降ってこない。。。というところまででした。しめじさんにも言われたのですが「一度作ってしまうとなかなか変えられない」ものなのでどうにか降りてきてほしいっ!!!

あとはカンファレンス駆動で、runnで使っているOpenAPIパーサパッケージの差し替えとか、変数展開に使っているデリミタのエスケープができるようにするなどして、とうとうv0.100.0になりました。

v1...

github.com github.com

キャッシュとCSRF

Day2のお昼は話したい人が目の前にいたので声かけた結果なかなかなさそうなメンツで行くことに。

CSRF対策としてのOriginヘッダの話で、 @hiro_y さんの発表と全く同じことを(おそらく発表を聞いていない上で)言っている @catatsuy さんがいて、「あーこれは古来からのCSRFトークンではない対策もアリだなあ」と思ったのでした。

「そーだいさんのキャッシュ話面白かった」というところからキャッシュ全般の話になり「最近のJSフレームワークやGraphQLクライアントは勝手に(?)キャッシュをしてくるのでムズカシイ(かなり意訳)」と、なるほどと聞いていました。

プロキシキャッシュの話ももう少し聞けば良かった...!

そんな話をしながら「普通に衣上下に縦に食べられない厚さのカツ」を体験できました。おいしかった。@ttabtt3 さんチョイスありがとうございました。

発表

今回出したプロポーザルはCLIツールのデザインについての話でした。発表内容は資料や動画を見ていただくとして、多くの皆さんに質問や反応をしてもらって良かったです。

speakerdeck.com

CLIツール、小さく作れるし、しっかり考えて作ると勉強になるし、Webアプリケーション開発にも通じるものが多いのでおすすめです。

コミュニケーション

時間制限をして思いつく限りを書いてみました

無事きんじょうさん( @o0h_ さん)を拉致(?)して懇親会に行けたのは良かったです。 私はきんじょうさんを知識蓄積型、広範囲学習型とみているのですが、いつも発表の内容が明快でかつ多彩で気になっていた方でした。 今回も「多分何聞いても回答が返ってきそう」と思って、きんじょうさんに色々質問していました。 ただ、すでに私にお酒が入っていたので、質問しきれたかというとそうでもないので、次回はカンペを用意していこうと思います。

@kaz_29 + @keita__Max のお二人の話も面白かったです。どこかのカンファレンスでネタになるかもしれないのであまり話せませんが、良いシナジーだなあと思いました。 あと、これも私からは詳細は書けませんが、みなさん @keita__Max さん見かけたら話しかけてみると良いと思います。めちゃくちゃすごかったし面白かった!

すごいといえば @katzchum さんと @tyamahori さんの「あるあるですが〜」から話していた全然あるあるではない「フィーチャーフラグ Lv100(命名 きんじょうさん)」は驚愕だった。たぶんこれもいつかカンファレンスで出てくると予想しています。

@77web さんと @KentarouTakeda さんに凸って聞いた「SymfonyとLaravel」話もめちゃくちゃ興味深かったです。一部 @77web さんがブログエントリに書かれていたので是非。書けない話もありますよね。

https://77web.hatenablog.com/entry/2024/03/11/200747

そういえば、そーだいさんの近くにいるといつも良い話を聞けるので良いです。ただ、いつもそうなので、良い話をするそーだいさん「以外」がいるのか気になっています。

あと、P山さんには「謎の世界的なオヤマ」推しをされてとても困りました。

ただ、印象に残したのは私のようです。

daisuki.nichiyoubi.land

これまたk1LoWさんとの交流によってもたらされたやつですが、「P山さんの凄さ」について聴いたのがすっっっごい心に残ってます。

こちらの凄い人を体験したい方はこちらへ

PHPerKaigi

会期中のタイムラインでも、廊下でも話題になった話なのですが、どのカンファレンスもいつも楽しいのですが、PHPerKaigiの懐の深さと楽しさは本当に素晴らしいと思います。

「PHPer」と冠していますが、もっとひろくエンジニアの人々に開かれているので、PHPerだったときからPHPerではない?ように感じる今でもとても居心地が良いです。

また来年も1年の集大成をぶつけられれば良いなあと思っています。

スタッフの皆さん、PHPerKaigiコミュニティのみなさんありがとうございました!