bulldogger 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +84 -0
- data/README.ja.md +113 -107
- data/README.md +114 -88
- data/docs/design-decisions.md +172 -0
- data/docs/evidence-schema.md +142 -55
- data/docs/maintenance.md +26 -9
- data/exe/bulldogger +66 -4
- data/lib/bulldogger/application_frames.rb +2 -2
- data/lib/bulldogger/capture.rb +15 -1
- data/lib/bulldogger/code_state.rb +40 -0
- data/lib/bulldogger/collector_environment.rb +16 -0
- data/lib/bulldogger/config.rb +3 -16
- data/lib/bulldogger/evidence.rb +8 -19
- data/lib/bulldogger/exec.rb +86 -0
- data/lib/bulldogger/exec_collector.rb +142 -0
- data/lib/bulldogger/execution_target.rb +112 -0
- data/lib/bulldogger/failure_output.rb +7 -19
- data/lib/bulldogger/flt.rb +54 -0
- data/lib/bulldogger/flt_collector.rb +186 -0
- data/lib/bulldogger/frames.rb +76 -0
- data/lib/bulldogger/frames_collector.rb +166 -0
- data/lib/bulldogger/instance.rb +12 -15
- data/lib/bulldogger/integrations/minitest.rb +43 -24
- data/lib/bulldogger/integrations/rspec.rb +26 -16
- data/lib/bulldogger/preflight.rb +79 -0
- data/lib/bulldogger/probe/bucket.rb +8 -7
- data/lib/bulldogger/probe/comparator.rb +3 -2
- data/lib/bulldogger/probe/method_stats.rb +1 -1
- data/lib/bulldogger/probe/raise_tracker.rb +3 -3
- data/lib/bulldogger/probe/session.rb +7 -5
- data/lib/bulldogger/probe.rb +5 -4
- data/lib/bulldogger/rerun_command.rb +48 -0
- data/lib/bulldogger/version.rb +1 -1
- data/lib/bulldogger.rb +10 -30
- data/skills/bulldogger/SKILL.md +123 -31
- data/skills/bulldogger/references/failure-evidence.md +2 -6
- data/skills/bulldogger/references/reexecution.md +149 -0
- metadata +15 -11
- data/docs/trace-schema.md +0 -123
- data/lib/bulldogger/record/session.rb +0 -343
- data/lib/bulldogger/record/sqlite_converter.rb +0 -86
- data/lib/bulldogger/record/writer.rb +0 -67
- data/lib/bulldogger/record.rb +0 -47
- data/lib/bulldogger/replay.rb +0 -123
- data/skills/bulldogger/references/record.md +0 -28
- data/skills/bulldogger/references/replay.md +0 -88
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 72ea09764a4ece080b0430f55231aa772b451c37174604a2c6352077d36de9e2
|
|
4
|
+
data.tar.gz: d4e01f7ea18e1d7c6e5183dbe8bd7a6e800c4e6c11f0480933db7268d4429eb3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 25cfda27f1f9255f254b581004346847fafd2397099a67b67bb244801ff50125d95e5dfc437a27f78ce4b110d6982a6194b7970f08cfab5be18dbab242e4e787
|
|
7
|
+
data.tar.gz: 22382a54852bd5bd0b0d062d041fb058d3b8a7ccd9da4f77378faf0d27afe4f27efdd8f36e3e3949ad78ac75c7ee4afece7b240958dec617db246dafef556a4f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,89 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.1
|
|
4
|
+
|
|
5
|
+
### The re-run a failure needs is now an explicit verb, not an automatic one
|
|
6
|
+
|
|
7
|
+
`0.2.0` reached the value behind an assertion failure by re-running the one
|
|
8
|
+
failing test automatically, under full recording, in a child process. That
|
|
9
|
+
worked, but it re-ran on every qualifying failure whether or not anyone
|
|
10
|
+
asked, and it paid for a whole-run trace to answer one question. This release
|
|
11
|
+
replaces that automatic replay with re-execution the agent drives, one
|
|
12
|
+
question at a time, and retires the `record` verb along with it.
|
|
13
|
+
|
|
14
|
+
This removes `record`, automatic replay, and their evidence keys, so it is
|
|
15
|
+
a breaking change for a `0.2.0` user who read them. The failure snapshot and
|
|
16
|
+
`probe` are unchanged.
|
|
17
|
+
|
|
18
|
+
`0.3.0` carries the same work, but its release run stopped before publishing
|
|
19
|
+
when a fixture pinned an older minitest than the suite now uses. Its tag
|
|
20
|
+
stands at that commit and no gem was pushed, so `0.3.1` is the first
|
|
21
|
+
published release of the re-execution verbs, with the fixture pinned to the
|
|
22
|
+
minitest the suite loads.
|
|
23
|
+
|
|
24
|
+
- **Four re-execution verbs join `probe`.** `frames` runs a test in a fresh
|
|
25
|
+
process and indexes every call by a stable identifier, `fid`
|
|
26
|
+
(`path:method#k`, where `k` counts calls to that method inside the test
|
|
27
|
+
window). `preflight` runs a test twice in isolation and compares the two
|
|
28
|
+
application-frame sequences, so an agent can trust a `fid` from one run to
|
|
29
|
+
address the same call in the next. `flt` traces one selected frame: its
|
|
30
|
+
entry arguments and locals, each line's changed locals, and its return.
|
|
31
|
+
`exec` evaluates one statement at one addressed line visit inside a
|
|
32
|
+
selected frame, gated behind the `BULLDOGGER_EXEC=1` launch token the
|
|
33
|
+
launcher sets for the child process.
|
|
34
|
+
- **`record` and automatic replay retire.** Whole-run tracing measured 881x
|
|
35
|
+
to 2869x with debug.gem's recorder, and 34x to 51x with the shipped record
|
|
36
|
+
path; `frames` plus `flt` answer the same questions at re-execution cost,
|
|
37
|
+
paid only when invoked. `flt` and `exec` both refuse a target outside the
|
|
38
|
+
project's own source, naming the frames index, the gem source, and `probe`
|
|
39
|
+
as the alternatives.
|
|
40
|
+
- **The failure output's rerun line is the whole handoff.** `bulldogger
|
|
41
|
+
rerun:` prints the complete command for the failing test and seed; an
|
|
42
|
+
agent runs it under `frames` to reach a value whose producing method had
|
|
43
|
+
already returned. A green run still costs nothing extra, and re-execution
|
|
44
|
+
runs only when an agent invokes it.
|
|
45
|
+
|
|
46
|
+
### Running bulldogger over its own suite
|
|
47
|
+
|
|
48
|
+
- **`Bulldogger::Instance`** separates the observing tool from the subject
|
|
49
|
+
under test. A single module singleton could not be both, because a suite's
|
|
50
|
+
own setup resets bulldogger for test isolation and destroyed any outer
|
|
51
|
+
observer. The module now delegates to a default instance, and
|
|
52
|
+
`Bulldogger::Minitest.instance=` and `Bulldogger::RSpec.instance=` accept
|
|
53
|
+
another one.
|
|
54
|
+
- `rake dogfood` covers the unit suite as well as acceptance.
|
|
55
|
+
|
|
56
|
+
### Reaching the skill
|
|
57
|
+
|
|
58
|
+
- **`exe/bulldogger`** launches the re-execution verbs and answers two more
|
|
59
|
+
questions: `skill path` prints the location of the skill shipped with the
|
|
60
|
+
installed gem, and `version` prints the version.
|
|
61
|
+
- Evidence and probe evidence carry a `skill` key holding that path. The key
|
|
62
|
+
is omitted when the file is absent, because a path that does not resolve
|
|
63
|
+
costs a reader more than a missing one.
|
|
64
|
+
- The skill teaches what the files cannot: that an absent local means the run
|
|
65
|
+
could not see it, that a probe reporting zero calls was blind rather than
|
|
66
|
+
idle, and how to walk a trace from a symptom down to the value's origin.
|
|
67
|
+
|
|
68
|
+
### Cost
|
|
69
|
+
|
|
70
|
+
- Redaction matches one union pattern instead of nine separate ones, checked
|
|
71
|
+
against 26 boundary names and 2,000 random names. Every capture path
|
|
72
|
+
shares the same redactor: failure snapshots, `probe`, `flt`, and `exec`.
|
|
73
|
+
- A failure snapshot still costs 44.126 microseconds for each raise-and-rescue
|
|
74
|
+
cycle, and a green test that raises nothing still costs nothing measurable.
|
|
75
|
+
`frames`, `preflight`, `flt`, and `exec` start a new process only when an
|
|
76
|
+
agent runs them; `probe` runs only around a block it selects.
|
|
77
|
+
|
|
78
|
+
### Documentation
|
|
79
|
+
|
|
80
|
+
- `README.ja.md` translates the README. `README.md` stays the source of the
|
|
81
|
+
claims.
|
|
82
|
+
- `docs/design-decisions.md` records the observation limits found while
|
|
83
|
+
building this: `Coverage` cannot see lines under a `TracePoint` callback,
|
|
84
|
+
and neither can a probe, which is why bulldogger cannot probe its own
|
|
85
|
+
serialization path.
|
|
86
|
+
|
|
3
87
|
## 0.2.0
|
|
4
88
|
|
|
5
89
|
### A failing test now leads to the value that caused it
|
data/README.ja.md
CHANGED
|
@@ -6,8 +6,7 @@ bulldogger は Ruby のテスト失敗を、コーディングエージェント
|
|
|
6
6
|
各 JSON ファイルには、例外、バックトレース、取得したフレームの値が含まれます。
|
|
7
7
|
失敗出力には、そのファイルの絶対パスが示されます。
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
bulldogger 0.2.0 では独立したインスタンスを追加し、ドッグフーディングをユニットテストスイートまで拡張しました。
|
|
9
|
+
開発とスナップショットの計測には Ruby 4.0.6 と debug 1.11.1 を使用しました。
|
|
11
10
|
|
|
12
11
|
## インストール
|
|
13
12
|
|
|
@@ -42,6 +41,10 @@ bulldogger skill path
|
|
|
42
41
|
CLI には次のサブコマンドがあります。
|
|
43
42
|
|
|
44
43
|
```text
|
|
44
|
+
bulldogger frames -- command...
|
|
45
|
+
bulldogger preflight -- command...
|
|
46
|
+
bulldogger flt 'path:method#k' [--index path] -- command...
|
|
47
|
+
bulldogger exec 'path:method#k' --line N [--visit K] --statement text [--index path] -- command...
|
|
45
48
|
bulldogger skill path
|
|
46
49
|
bulldogger version
|
|
47
50
|
bulldogger --version
|
|
@@ -77,7 +80,7 @@ observer.start
|
|
|
77
80
|
```
|
|
78
81
|
|
|
79
82
|
各インスタンスは、設定、取得の購読、実行、証拠の状態を所有します。
|
|
80
|
-
|
|
83
|
+
モジュールのファサードが提供する失敗と probe の各メソッドも利用できます。
|
|
81
84
|
|
|
82
85
|
インテグレーションには、デフォルトの代わりに指定したインスタンスを使えます。
|
|
83
86
|
|
|
@@ -89,24 +92,26 @@ Bulldogger::RSpec.instance = observer
|
|
|
89
92
|
テストスイートが始まる前にインスタンスを指定します。
|
|
90
93
|
この分離により、テストのセットアップがデフォルトインスタンスを置き換えても、外側のオブザーバーは動作を続けられます。
|
|
91
94
|
|
|
92
|
-
##
|
|
95
|
+
## コストモデル
|
|
93
96
|
|
|
94
|
-
|
|
97
|
+
常時有効な処理は、失敗スナップショットを取得します。
|
|
98
|
+
例外が発生しない green テストでは処理を行いません。
|
|
99
|
+
監視した例外 1 件には microseconds 単位のコストがかかります。
|
|
95
100
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
スナップショットのベンチマークには Ruby 4.0.6 を使いました。
|
|
102
|
+
raise と rescue の 1 サイクルあたり 44.126 microseconds を計測しました。
|
|
103
|
+
そのうちフレーム取得には 1.288 microseconds がかかりました。
|
|
99
104
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
再実行は明示的です。
|
|
106
|
+
`frames`、`preflight`、`flt`、`exec` は、ユーザーが実行したときだけ新しいプロセスを開始します。
|
|
107
|
+
`probe` も、ユーザーが選んだブロックの周囲でだけ動作します。
|
|
103
108
|
|
|
104
|
-
##
|
|
109
|
+
## 失敗スナップショットから開始
|
|
105
110
|
|
|
106
111
|
次のコマンドから、この出力を得ました。
|
|
107
112
|
|
|
108
113
|
```sh
|
|
109
|
-
bundle exec ruby -Ilib test/fixtures/minitest_red/red_test.rb
|
|
114
|
+
bundle exec ruby -Ilib test/fixtures/minitest_red/red_test.rb --seed 12345
|
|
110
115
|
```
|
|
111
116
|
|
|
112
117
|
```text
|
|
@@ -115,16 +120,14 @@ RedTest#test_deep_raise:
|
|
|
115
120
|
ArgumentError: expected 3 to equal the sum of [1, 2, 3]
|
|
116
121
|
test/fixtures/minitest_red/app.rb:9:in 'Order.total'
|
|
117
122
|
test/fixtures/minitest_red/red_test.rb:20:in 'RedTest#test_deep_raise'
|
|
118
|
-
bulldogger evidence: /home/you/project/tmp/bulldogger/run-
|
|
123
|
+
bulldogger evidence: /home/you/project/tmp/bulldogger/run-20260831-192835-69510/001-RedTest-test_deep_raise.json (raising method is in these frames)
|
|
124
|
+
bulldogger rerun: bundle exec ruby -Itest test/fixtures/minitest_red/red_test.rb -n /\\Atest_deep_raise\\z/ --seed 12345
|
|
119
125
|
```
|
|
120
126
|
|
|
121
127
|
括弧内の案内がある行のパスを開きます。
|
|
122
128
|
このファイルには、1 件の失敗と取得した実行時の値が含まれます。
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
失敗に対してリプレイを実行すると、`bulldogger replay:` 行が表示されます。
|
|
126
|
-
括弧内の説明は、再現した失敗または成功したリプレイを示します。
|
|
127
|
-
規則、設定、副作用については、[失敗したテストのリプレイ](#失敗したテストのリプレイ)を参照してください。
|
|
129
|
+
rerun 行には、そのテストと seed に対する完全なコマンドが含まれます。
|
|
130
|
+
bulldogger は、このコマンドを自動では実行しません。
|
|
128
131
|
|
|
129
132
|
各実行では次の配置を使います。
|
|
130
133
|
|
|
@@ -134,67 +137,106 @@ tmp/bulldogger/
|
|
|
134
137
|
run-20260829-100406-58231/
|
|
135
138
|
001-RedTest-test_deep_raise.json
|
|
136
139
|
002-RedTest-test_assertion_failure.json
|
|
137
|
-
trace-001.jsonl
|
|
138
140
|
index.json
|
|
139
141
|
```
|
|
140
142
|
|
|
141
143
|
[`bulldogger` skill](skills/bulldogger/SKILL.md) は、エージェントがこれらのファイルを調べる方法を説明します。
|
|
142
144
|
[証拠スキーマ](docs/evidence-schema.md)は、すべてのフィールドと取得モードを定義します。
|
|
143
145
|
|
|
144
|
-
##
|
|
146
|
+
## frames による分離実行のインデックス作成
|
|
147
|
+
|
|
148
|
+
rerun コマンドを `frames` の下で実行します。
|
|
149
|
+
|
|
150
|
+
```sh
|
|
151
|
+
bulldogger frames -- bundle exec ruby -Itest test/fixtures/frames/minitest_frames_test.rb --seed 12345
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
コマンドはインデックスのパスと子プロセスの結果を表示します。
|
|
145
155
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
156
|
+
```text
|
|
157
|
+
bulldogger frames: /home/you/project/tmp/bulldogger/frames-69833.jsonl
|
|
158
|
+
bulldogger result: pass (exit 0)
|
|
159
|
+
```
|
|
149
160
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
161
|
+
インデックスは各呼び出しにフレーム識別子 `fid` を付けます。
|
|
162
|
+
形式は `path:method#k` です。
|
|
163
|
+
数値は、テスト区間内にある同じメソッドの呼び出しを数えます。
|
|
164
|
+
インデックスには、アプリケーション、フレームワーク、gem のフレームが含まれます。
|
|
153
165
|
|
|
154
|
-
|
|
155
|
-
そのフレームが 0 件ならリプレイし、1 件以上なら `replay_skipped_reason: "application_frame_available"` を付けて省略します。
|
|
156
|
-
この理由があり `replay` キーがない場合、フレームから答えを得られます。
|
|
166
|
+
## preflight による分離再実行の検証
|
|
157
167
|
|
|
158
|
-
|
|
159
|
-
green の実行ではリプレイを行わないため、green のときにコストがないという特性も保たれます。
|
|
160
|
-
追加コストはアサーション型の失敗後に限って発生し、デフォルトでは分離されたプロセスで 1 回だけ実行します。
|
|
168
|
+
`flt` または `exec` の前に `preflight` を実行します。
|
|
161
169
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
`false` は、その失敗が単独では再現しなかったことを示します。
|
|
166
|
-
通常は、実行順序や別のテストとの共有状態に依存するテストを示唆します。
|
|
170
|
+
```sh
|
|
171
|
+
bulldogger preflight -- bundle exec ruby -Itest test/fixtures/frames/minitest_frames_test.rb --seed 12345
|
|
172
|
+
```
|
|
167
173
|
|
|
168
|
-
|
|
174
|
+
同じコマンドを別々のプロセスで 2 回実行します。
|
|
175
|
+
2 つのアプリケーションフレーム列を比較します。
|
|
169
176
|
|
|
170
177
|
```text
|
|
171
|
-
bulldogger
|
|
172
|
-
bulldogger
|
|
178
|
+
bulldogger preflight: deterministic (app frames: 3)
|
|
179
|
+
bulldogger preflight indexes: /home/you/project/tmp/bulldogger/frames-70427.jsonl /home/you/project/tmp/bulldogger/frames-70432.jsonl
|
|
173
180
|
```
|
|
174
181
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
リプレイが無効な場合、証拠の括弧内には `BULLDOGGER_REPLAY=1` も示されます。
|
|
178
|
-
取得に失敗した場合、スナップショットにフレームがないことを示します。
|
|
182
|
+
preflight が `deterministic` を表示した場合に限って、`flt` または `exec` を使います。
|
|
183
|
+
どちらの動詞もアプリケーションのフレーム識別子だけを受け付けます。
|
|
179
184
|
|
|
180
|
-
|
|
185
|
+
## flt による 1 フレームのトレース
|
|
181
186
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
+
アプリケーションの `fid` と同じ分離コマンドを渡します。
|
|
188
|
+
|
|
189
|
+
```sh
|
|
190
|
+
bulldogger flt 'test/fixtures/flt/minitest_flt_test.rb:branchy#1' -- bundle exec ruby -Itest test/fixtures/flt/minitest_flt_test.rb --seed 12345
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
```text
|
|
194
|
+
bulldogger flt: /home/you/project/tmp/bulldogger/flt-77206.jsonl
|
|
195
|
+
bulldogger result: pass (exit 0)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
トレースには、フレーム開始、行ごとの変更、raise、return が含まれます。
|
|
199
|
+
新しいローカル変数は `new` に、更新は `changed` に記録します。
|
|
200
|
+
スコープを外れたローカル変数は `out_of_scope` に列挙します。
|
|
201
|
+
ループ中間の反復は `skipped_iterations` レコードにまとめます。
|
|
202
|
+
|
|
203
|
+
`--index path` は、インデックスと再実行に同じコード状態マーカーを要求します。
|
|
204
|
+
|
|
205
|
+
## exec による 1 文の評価
|
|
206
|
+
|
|
207
|
+
アプリケーションフレーム内の 1 回の行訪問を指定します。
|
|
208
|
+
|
|
209
|
+
```sh
|
|
210
|
+
bulldogger exec 'test/fixtures/exec/minitest_exec_test.rb:threshold#1' --line 9 --statement 'binding.local_variable_set(:result, 10)' -- bundle exec ruby -Itest test/fixtures/exec/minitest_exec_test.rb --seed 12345 -n test_injection_can_change_the_outcome
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
```text
|
|
214
|
+
bulldogger exec: /home/you/project/tmp/bulldogger/exec-77267.jsonl
|
|
215
|
+
bulldogger value: 10
|
|
216
|
+
bulldogger result: pass (exit 0)
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
`exec` は選択したフレームの binding で文を評価します。
|
|
220
|
+
デフォルトでは、その行の最初の訪問を選びます。
|
|
221
|
+
後の訪問には `--visit K` を使います。
|
|
222
|
+
launcher は必要な `BULLDOGGER_EXEC=1` token を子プロセスへ渡します。
|
|
223
|
+
`--index path` は、同じコード状態マーカーを要求します。
|
|
224
|
+
|
|
225
|
+
文はテストの動作を変え、副作用を発生させる可能性があります。
|
|
226
|
+
変更後の結果を証拠に使う前に、結果ファイルを読みます。
|
|
187
227
|
|
|
188
|
-
|
|
189
|
-
リプレイしたテストは、ファイル書き込み、外部リクエスト、サンドボックスアカウントの変更などの各副作用を再度実行します。
|
|
190
|
-
1 つのプロセスでリプレイを無効にするには `BULLDOGGER_REPLAY=0` を設定します。
|
|
191
|
-
すべての失敗をリプレイするには `BULLDOGGER_REPLAY=always` を設定します。
|
|
192
|
-
アプリケーションで同じ方針を設定するには、`config.replay_on_failure` に `false` または `:always` を指定します。
|
|
193
|
-
`BULLDOGGER_MAX_REPLAYS` は上限を上書きします。
|
|
194
|
-
`BULLDOGGER_DISABLE=1` は、ほかのすべての取得とともにリプレイも無効にします。
|
|
228
|
+
## RSpec の乱数 seed
|
|
195
229
|
|
|
196
|
-
|
|
197
|
-
|
|
230
|
+
RSpec は seed を例の順序に使います。
|
|
231
|
+
RSpec は `Kernel.srand` を呼びません。
|
|
232
|
+
例が `rand` を呼ぶ場合は、`RSpec.configure` 内に次の行を追加します。
|
|
233
|
+
|
|
234
|
+
```ruby
|
|
235
|
+
config.before(:suite) { Kernel.srand config.seed }
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
この行により、表示された rerun seed で乱数値を再現できます。
|
|
239
|
+
bulldogger はアプリケーションに代わって `Kernel.srand` を呼びません。
|
|
198
240
|
|
|
199
241
|
## probe によるメソッドの指定
|
|
200
242
|
|
|
@@ -242,33 +284,6 @@ result.fetch("identical")
|
|
|
242
284
|
}
|
|
243
285
|
```
|
|
244
286
|
|
|
245
|
-
## 呼び出しシーケンスの記録
|
|
246
|
-
|
|
247
|
-
完全な呼び出しシーケンスが必要な場合は、対象を絞った 1 つの処理を囲みます。
|
|
248
|
-
|
|
249
|
-
```ruby
|
|
250
|
-
trace_path = Bulldogger.record do
|
|
251
|
-
run_related_test
|
|
252
|
-
end
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
結果は JSONL ファイルであり、ヘッダーと call、return、raise の各イベントに対応するオブジェクトを含みます。
|
|
256
|
-
次の抜粋は、生成したトレースから得ました。
|
|
257
|
-
|
|
258
|
-
```jsonl
|
|
259
|
-
{"schema_version":1,"kind":"record","events":["call","return","raise"],"limits":{"max_value_length":200}}
|
|
260
|
-
{"event":"call","seq":1,"depth":1,"path":"-e","line":1,"method":"ProseTrace#outer","args":{"value":{"value":"3"}}}
|
|
261
|
-
{"event":"return","seq":4,"depth":1,"path":"-e","line":1,"method":"ProseTrace#outer","return":{"value":"6"}}
|
|
262
|
-
{"event":"raise","seq":7,"depth":2,"path":"-e","line":1,"method":"ProseTrace#inner","exception":{"class":"ArgumentError","message":"negative"}}
|
|
263
|
-
{"event":"return","seq":8,"depth":2,"path":"-e","line":1,"method":"ProseTrace#inner","raised":true}
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
[トレーススキーマ](docs/trace-schema.md)は、イベントフィールドと検証済みの `jq` クエリーを定義します。
|
|
267
|
-
|
|
268
|
-
JSONL が主要な記録形式です。
|
|
269
|
-
`sqlite3` gem が利用できる場合、`Bulldogger.trace_to_sqlite(trace_path, db_path)` は既存のトレースを変換します。
|
|
270
|
-
変換処理は soft require を使うため、bulldogger の実行時依存関係は 0 件のままです。
|
|
271
|
-
|
|
272
287
|
## コスト
|
|
273
288
|
|
|
274
289
|
`TracePoint(:raise)` は、アプリケーションコードが rescue する例外を含む、発生したすべての例外を監視します。
|
|
@@ -298,22 +313,16 @@ green のテストスイートでも例外を発生させて rescue する場合
|
|
|
298
313
|
|
|
299
314
|
### 明示的な動詞のコスト
|
|
300
315
|
|
|
301
|
-
比例関係の計測ハーネスでは、両方の動詞に 1 つのアプリケーションフィクスチャを使いました。
|
|
302
316
|
`probe` では対象メソッドの呼び出し 1 回あたり 1461.5 ns を計測しました。
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
`probe` のコストは対象メソッドの呼び出し数に比例し、計測ハーネスではその数を M と呼びます。
|
|
306
|
-
`record` のコストはトレース対象の全呼び出し数に比例し、計測ハーネスではその数を N と呼びます。
|
|
307
|
-
M/N が 0.25 のとき、このフィクスチャでは `probe` が 8.70x、`record` が 104.93x でした。
|
|
308
|
-
これらの比率はこのアプリケーションフィクスチャに対する値であり、別のアプリケーションでは M/N の値が異なります。
|
|
317
|
+
フレームの gate では、対象外の呼び出し 1 件あたり約 105 ns を計測しました。
|
|
309
318
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
これらの数値は定数ではなく範囲として読んでください。
|
|
319
|
+
`flt` の line event には約 0.5 microseconds の固定コストがあります。
|
|
320
|
+
各ローカル変数の読み取りには、line event 1 件あたり約 0.1 microseconds が加わります。
|
|
321
|
+
20 個のローカル変数と 10,000 件の line event を持つフレームには約 27 ms かかりました。
|
|
314
322
|
|
|
315
|
-
|
|
316
|
-
|
|
323
|
+
これらの計測には Ruby 4.0.6 と rubygems.org のテストスイートを使いました。
|
|
324
|
+
スイートには 4,925 件のテストがあり、seed 12345 と 1 worker を使いました。
|
|
325
|
+
計測日は 2026-08-31 です。
|
|
317
326
|
|
|
318
327
|
## bulldogger の無効化
|
|
319
328
|
|
|
@@ -322,7 +331,6 @@ JSONL への書き込みを含む完全な処理は 54.72x でした。
|
|
|
322
331
|
|
|
323
332
|
どちらかのスイッチを使うと、起動処理は `TracePoint(:raise)` の購読前に戻ります。
|
|
324
333
|
証拠を書かず、実行ディレクトリを作らず、失敗に証拠の行を追加しません。
|
|
325
|
-
リプレイは、このスイッチが省略する証拠処理から始まるため、実行されません。
|
|
326
334
|
テストの終了コードと失敗数は変わりません。
|
|
327
335
|
受け入れテストは、Minitest と RSpec についてこの動作を確認しています。
|
|
328
336
|
|
|
@@ -338,8 +346,6 @@ rescue を多用する green のテストスイートでは、bulldogger を無
|
|
|
338
346
|
| `BULLDOGGER_DISABLED` | `1` | `BULLDOGGER_DISABLE` の別名です。 |
|
|
339
347
|
| `BULLDOGGER_OUTPUT_DIR` | 空でないパス | デフォルトは作業ディレクトリからの相対パス `tmp/bulldogger` です。 |
|
|
340
348
|
| `BULLDOGGER_FRAME_SOURCE` | `capture_frames` または `degraded` | デフォルトでは自動選択します。 |
|
|
341
|
-
| `BULLDOGGER_REPLAY` | `0`、`1`、または `always` | デフォルトは `1` です。フレームから答えを得られない場合にリプレイします。`0` はリプレイを無効にします。`always` はすべての失敗をリプレイします。 |
|
|
342
|
-
| `BULLDOGGER_MAX_REPLAYS` | 整数 | 1 回の実行に対するリプレイ数 `max_replays` を上書きします。デフォルトは `1` です。 |
|
|
343
349
|
|
|
344
350
|
## シークレットと上限
|
|
345
351
|
|
|
@@ -371,11 +377,11 @@ bulldogger は Hash をレンダリングするときにキーも検査します
|
|
|
371
377
|
|
|
372
378
|
## バージョン 0.2 の範囲
|
|
373
379
|
|
|
374
|
-
Version 0.2
|
|
375
|
-
JSON の証拠と JSONL
|
|
376
|
-
|
|
380
|
+
Version 0.2 は、失敗スナップショット、probe、フレームインデックス、決定性検査、フレーム生存期間トレース、文の評価、独立したインスタンスを提供します。
|
|
381
|
+
JSON の証拠と JSONL の成果物を書き出します。
|
|
382
|
+
重い取得は、明示的な動詞からだけ開始します。
|
|
377
383
|
|
|
378
|
-
[設計判断](docs/design-decisions.md)
|
|
384
|
+
[設計判断](docs/design-decisions.md)は、証拠モデルと計測コストを説明します。
|
|
379
385
|
|
|
380
386
|
## ライセンス
|
|
381
387
|
|