@unikvs/debug
読み書きされる操作とデータを @logtape/logtape で記録する @unikvs/debug の使い方を説明します。
概要
@unikvs/debug は、読み書きされるデータをそのまま透過させつつ、操作の種類・対象のキー・データのデバッグ情報を @logtape/logtape で記録する Transformer プラグインです。Transformer
変数の unikvs:action と unikvs:key を参照するため、UniKvs 経由で使うと「どの操作で、どのキーに対するデータが読み書きされたか」がログに残ります。データの変換は行いません。
常にオープン状態です。open・close は不要で、isOpen は常に true、name は常に "Debug" を返します。
インストールは次のとおりです。ログの出力には @logtape/logtape も必要です。
npm install @unikvs/debug @logtape/logtapepnpm add @unikvs/debug @logtape/logtapeyarn add @unikvs/debug @logtape/logtapebun add @unikvs/debug @logtape/logtapenub add @unikvs/debug @logtape/logtapeaube add @unikvs/debug @logtape/logtape使い方
LogTape を設定してから、appendTransformer で登録します。以降に登録するストレージの前段になります。
import { Debug } from "@unikvs/debug";
import { Memory } from "@unikvs/memory";
import { configureSync, getConsoleSink } from "@logtape/logtape";
import { UniKvs, type PlainValue } from "unikvs";
configureSync({
sinks: {
console: getConsoleSink(),
},
loggers: [
{
category: ["unikvs", "@unikvs/debug"],
sinks: ["console"],
lowestLevel: "debug",
},
],
});
const kvs = UniKvs.config<{ greeting: PlainValue<string> }>()
.appendTransformer(new Debug())
.appendStorage(new Memory())
.create();
await kvs.open();
await kvs.set("greeting", "hello");
const greeting = await kvs.get("greeting"); // コンソールに読み書きのログを出力します
await kvs.close();
set は書き込みとして、get は読み込みとして記録します。ストリーム値の set と stream はチャンクごとに記録します。
記録内容
1 件のログには次のプロパティーを記録します。
| プロパティー | 説明 |
|---|---|
action |
変数の unikvs:action です。このトランスフォーマーでは set・get・stream のいずれかになります。 |
key |
変数の unikvs:key です。 |
direction |
"write" または "read" です。"write" はストレージへ書き込むデータ、"read" は読み出したデータです。 |
type |
データ型です。既定のコールバックが type-name の typeName() で判定します。 |
length |
データが文字列のときの文字列長です。 |
byteLength |
データが TypedArray または DataView のときの正確なバイト数です。 |
vars に unikvs:action または unikvs:key がないデータは記録しません。フィルターの指定にかかわらず記録されません。
ロガーカテゴリーは ["unikvs", "@unikvs/debug"]、レベルは debug です。
オプション
コンストラクターの引数は次のとおりです。
| 引数 | 型 | 必須 | 説明 |
|---|---|---|---|
options |
DebugOptions |
いいえ | 省略時は空オブジェクトと同じように動作します。 |
options.keyFilter |
IDebugKeyFilter((key: string) => boolean) |
いいえ | 記録対象のキーを絞り込みます。true を返したキーだけを記録します。 |
options.actionFilter |
IDebugActionFilter((action: string) => boolean) |
いいえ | 記録対象の操作を絞り込みます。true を返した操作だけを記録します。 |
options.getDebugInfo |
IDebugInfoCallback((args: DebugInfoArgs) => Record<string, unknown>) |
いいえ | 追加のデバッグ情報を返します。戻り値はログのプロパティーに展開します。 |
キーフィルター
keyFilter を指定すると、true を返したキーだけを記録します。vars に unikvs:key がないログは記録しません。
import { Debug } from "@unikvs/debug";
const debug = new Debug({
keyFilter: (key) => key.startsWith("user:"),
});
アクションフィルター
actionFilter を指定すると、true を返した操作だけを記録します。vars に unikvs:action がないログは記録しません。
import { Debug } from "@unikvs/debug";
const debug = new Debug({
actionFilter: (action) => action === "get" || action === "stream",
});
追加のデバッグ情報
getDebugInfo を指定すると、戻り値のオブジェクトをログのプロパティーに展開します。引数は DebugInfoArgs 型で、vars・action・key・direction・data を持ちます。data は読み書きされたデータで、ストリームの場合はチャンクです。
既定のコールバックは静的メソッド Debug.getDefaultDebugInfo です。これを呼び出せば、既定の情報に独自の情報を追加できます。
import { Debug } from "@unikvs/debug";
const debug = new Debug({
getDebugInfo: (args) => ({
...Debug.getDefaultDebugInfo(args),
preview: typeof args.data === "string" ? args.data.slice(0, 16) : null,
}),
});
ストリーム
getEncodable・getDecodable は入力をそのまま出力しつつ、チャンクごとにログを記録します。フィルターもチャンクごとに適用します。
注意点
- ログを表示するには LogTape の設定が別途必要です。設定していない場合、ログはどこにも出力されません。
- データは変換しません。ほかのトランスフォーマーと併用しても結果には影響しません。ただし登録位置によって観察できるデータが変わるため、前段の変換後のデータを確認できます。
- 記録レベルは
debugです。LogTape の設定でlowestLevelを"debug"または"trace"にしないと記録されません。 - データの中身は既定では記録しません。
getDebugInfoで中身を返す場合は、機密情報がログに残らないよう注意してください。
使用例
フィルターと追加のデバッグ情報を組み合わせた例です。user: で始まるキーの読み込みだけを記録し、データが文字列なら先頭 16 文字を preview として記録します。
import { Debug } from "@unikvs/debug";
import { Memory } from "@unikvs/memory";
import { configureSync, getConsoleSink } from "@logtape/logtape";
import { UniKvs, type PlainValue } from "unikvs";
configureSync({
sinks: {
console: getConsoleSink(),
},
loggers: [
{
category: ["unikvs", "@unikvs/debug"],
sinks: ["console"],
lowestLevel: "debug",
},
],
});
const debug = new Debug({
actionFilter: (action) => action === "get" || action === "stream",
keyFilter: (key) => key.startsWith("user:"),
getDebugInfo: (args) => ({
...Debug.getDefaultDebugInfo(args),
preview: typeof args.data === "string" ? args.data.slice(0, 16) : null,
}),
});
const kvs = UniKvs.config<{ "user:1": PlainValue<string>; settings: PlainValue<string> }>()
.appendTransformer(debug)
.appendStorage(new Memory())
.create();
await kvs.open();
await kvs.set("user:1", "Alice");
await kvs.set("settings", "dark");
await kvs.get("user:1"); // 記録されます
await kvs.get("settings"); // キーが一致しないため記録しません
await kvs.close();