🤖
TS の using でプリントデバッグを確率的にサンプリングして出力する
スコープ単位でログをサンプリングする。
{
using log = createSampleLog<string>(5);
log("a");
log("b");
// スコープを抜けるときに最大5件サンプリングされて表示される
}
using の使い所
やりたかったこと
Cline が勝手にデバッグログを仕込みまくって膨大なログを食ってトークンを使いまくるので、そもそも出力するログに上限を設定したい。
ロガーは初期化したスコープに依存して、抜ける時に吐き出す。
前提知識: using と Symbol.dispose
スコープから抜けるときの処理を書ける。
function useXXX() {
return {
[Symbol.dispose]() {
console.log("xxx:disposed")
}
}
}
// スコープを作る
{
using xxx = useXXX();
// スコープから抜ける時に using した参照の Symbol.dispose が発火
}
これをつかって、保持するインメモリのログの上限を設定しながら、スコープを抜けるときにログを表示する。
実装例
自分がコピペしやすくするために、かなりショートコーディングしているのに注意
type SampleLog = (<T = any>(t: T) => void) & Disposable;
export function createSampleLog<T = any>(
n: number,
truncateSize = 128,
print = console.log,
): SampleLog {
const samples: Array<[T, number]> = [];
let count = 0;
return Object.assign((item: T) => {
count++;
if (samples.length < n) {
samples.push([item, count]);
} else {
const r = ~~(Math.random() * count);
if (r < n) samples[r] = [item, count];
}
}, {
[Symbol.dispose]() {
samples.sort(([, a], [, b]) => a - b).forEach(([item, order]) => {
print(order, _truncate(item, truncateSize));
});
},
}) as SampleLog;
function _truncate(input: any, len: number): string {
let str: string;
if (input instanceof Object) {
str = JSON.stringify(input, null, 2);
} else {
str = String(input);
}
return str.length > len ? str.slice(0, len) + "..." : str;
}
}
//------ 基本的な使用例-----
function basicExample() {
using log = createSampleLog<number>(5, 20);
// 適当なデータを作成(1~41文字のアスキーらへんのコード)
for (let i = 0; i < 1000; i++) {
const len = ~~(Math.random() * 40) + 1;
log(String.fromCharCode(~~(Math.random() * 50 + 30)).repeat(len));
}
// スコープを抜けると自動的に結果が表示される
}
basicExample();
やってることは samples にためて、 dispose 時に truncate して出力しているだけ。
実行例
$ deno run ../../docs/practice/using-sampler-example.ts
50 ====================...
598 >>>>>>>>>>>>>>>>>>>>...
643 CCCC
823 FFFFFFFFFFFFF
911 66666666666666666666...
プロンプト
デバッグのためにログを設定する時は `createSampleLog(n, truncateSize)` を使います。
情報が足りない時は、件数や出力する文字数を徐々に大きくしてください。
```ts
{
// 最大5件, 128文字
using log = createSampleLog<number>(3, 128);
log("a");
log("b");
log("c");
//...
// スコープを抜けると結果が表示される
// [0] a
// [2] c
}
```
Discussion