Rで解析:処理の流れをツリー図で記録する「logtree」パッケージ
Rスクリプトの処理状況をログで追う際、処理の入れ子構造がそのまま目に見えると、どの段階で何が起きたのかを把握しやすくなります。しかし、階層の深さに応じた字下げ、ステップごとの経過時間、状態に応じた記号の出し分けを自前で組み立てるには手間がかかります。
本パッケージは、入れ子になった処理の実行過程を、コンソール上のツリー図として描画できるパッケージです。ステップの開始と終了を記録するコマンド、情報・成功・警告・エラー・デバッグの5段階で行を書き出すコマンド、実行後に注目すべき出来事だけを抜き出して要約するコマンドが収録されています。
階層の深さはフレーム終了ハンドラで追跡されるため、途中でエラーが発生しても表示の対応関係が崩れません。また、記号と配色のテーマ切り替え、テキストおよびNDJSON形式でのファイル出力、「logger」パッケージからの出力の取り込みも可能です。本パッケージの利用で、処理の進行状況と異常の発生箇所を一目で追えるログ出力ができるのではないかと考えます。
記事最下部に実行例を紹介しましたので、参考にしてみてください。
パッケージバージョンは0.1.0。Windows 11 x64 (build 26200)のR version 4.6.1で確認しています。
パッケージのインストール
下記コマンドを実行してください。
# パッケージのインストール
install.packages("logtree")
# パッケージの読み込み
library("logtree")コマンド例
詳細はコメント、パッケージのヘルプを確認してください。
本パッケージの出力は「ステップ」と「リーフ」の2種類で構成されます。ステップは処理のまとまりを表す枝で、開始行と終了行の対で描かれ、終了行には経過時間が記述されます。リーフはステップの内側に書き出す一行の記録で、情報・成功・警告・エラー・デバッグの5段階が用意されています。行の先頭に付く記号は「グリフ」と呼ばれ、状態ごとに色分けされます。
内部状態のリセット:logtree_resetコマンド
開いたままのステップの一覧と内部の連番カウンタ、要約用の記録をすべて初期化します。前の実行がエラーで中断した後や、同じスクリプトを繰り返し実行する場面で、まっさらな状態から描画を始めたいときに使用します。オプションはありません。
# ログツリーの内部状態を初期化する
logtree_reset()
ステップの開始と自動終了:log_stepコマンド
ステップの開始行、呼び出し元の関数が終了した時点で自動的に終了行をプロットします。関数の内側から呼び出すことを前提としたコマンドで、明示的な終了処理を書かずに済むのが特徴です。コマンド直下やコンソールから呼び出す場合は後述のlog_openコマンドとlog_closeコマンドを使用します。
| オプション | 意味 | 初期値 |
|---|---|---|
| msg | ステップのラベルを文字列で指定 | なし |
| glyph | ステップ先頭のグリフを上書きする文字列を指定 | NULL |
| parent | 入れ子の親とするステップのハンドルを指定 | NULL |
| group | グループ化に用いる長さ1の名前付きベクトルを指定 | NULL |
| close | 開始行のみを描画して即座に閉じるかを指定 | FALSE |
| key | 再実行時の同一性判定に用いる安定IDを指定 | NULL |
# ログツリーの内部状態を初期化する
logtree_reset()
# 貸出データの集計をおこなう関数を定義する
shukei_kashidashi <- function(kensu) {
# ステップを開始する。この関数の終了時に自動で閉じられる
log_step("貸出データの集計")
# 対象件数を情報行として書き出す
log_info(paste0("対象件数:", kensu, "件"))
}
# 128件を指定して関数を実行する
shukei_kashidashi(128)
▶ 貸出データの集計
├─ ℹ 対象件数:128件
└─ ✔ Done 0.02s手動ステップの開始:log_openコマンド
自動終了を伴わないステップを開始し、そのステップのハンドルを返します。得られたハンドルはlog_closeコマンドに渡すことで、任意のタイミングで終了可能です。
| オプション | 意味 | 初期値 |
|---|---|---|
| msg | ステップのラベルを文字列で指定 | なし |
| glyph | ステップ先頭のグリフを上書きする文字列を指定 | NULL |
| parent | 入れ子の親とするステップのハンドルを指定 | NULL |
| group | グループ化に用いる長さ1の名前付きベクトルを指定 | NULL |
| close | 開始行のみを描画して即座に閉じるかを指定 | FALSE |
| key | 再実行時の同一性判定に用いる安定IDを指定 | NULL |
# ログツリーの内部状態を初期化する
logtree_reset()
# 開館前チェックのステップを開始し、ハンドルを受け取る
kaikan <- log_open("開館前チェック")
▶ 開館前チェック
# 開館前チェックを親として、照明・空調のステップを開始する
shokai <- log_open("照明・空調", parent = kaikan)
├─ ▶ 照明・空調
# 点検結果を成功行として書き出す
log_success("点灯および設定温度22度を確認")
├─ ✔ 点灯および設定温度22度を確認
# 照明・空調のステップを閉じる
log_close(shokai)
└─ ✔ Done 2.11s
# 同じく開館前チェックを親として、貸出端末のステップを開始する
tanmatsu <- log_open("貸出端末", parent = kaikan)
├─ ▶ 貸出端末
# 消耗品の残量を警告行として書き出す
log_warn("2番端末のレシート用紙が残りわずか")
├─ ⚠ 2番端末のレシート用紙が残りわずか
# 貸出端末のステップを閉じる
log_close(tanmatsu)
└─ ⚠ Done 2.03s
# 開館前チェックのステップを閉じる
log_close(kaikan)
└─ ✔ Done 8.61scloseオプションをTRUEにすると開始行のみの見出しとして描画され、glyphオプションで先頭の記号を任意の文字に差し替えることが可能です。
# ログツリーの内部状態を初期化する
logtree_reset()
# 子要素を持たない見出しだけのステップを描画する
log_open("本日の受入資料", close = TRUE)
▶ 本日の受入資料
# 先頭のグリフを★に差し替えてステップを開始する
tenji <- log_open("新着展示の入替", glyph = "★")
★ 新着展示の入替
# 配架の内容を情報行として書き出す
log_info("展示棚Aに12冊を配架")
├─ ℹ 展示棚Aに12冊を配架
# 新着展示の入替のステップを閉じる
log_close(tenji)
└─ ✔ Done 18.83s
手動ステップの終了:log_closeコマンド
log_openコマンドで開いたステップを終了します。idオプションを省略すると、開いている最も内側のステップが閉じられます。ステップの状態は警告やエラーの記録によって段階的に引き上げられ、自然に戻ることはありません。復旧した処理を成功として記録し直したい場合は、statusオプションで最終状態を上書きします。
idオプションに渡すのはラベルの文字列ではなく、log_openコマンドが返すハンドルです。文字列を渡してもステップは閉じられませんので、必ず変数に指定してください。
| オプション | 意味 | 初期値 |
|---|---|---|
| id | log_openコマンドが返したステップハンドルを指定 | NULL |
| status | 終了ステータスをsuccess、warning、errorのいずれかで上書き指定 | NULL |
# ログツリーの内部状態を初期化する
logtree_reset()
# 貸出履歴の移行ステップを開始し、ハンドルを受け取る
ikou <- log_open("貸出履歴の移行")
▶ 貸出履歴の移行
# 転送失敗をエラー行として書き出す
log_error("1件目の転送に失敗")
├─ ✖ 1件目の転送に失敗
# 再試行で復旧したため、最終状態を成功に上書きして閉じる
log_close(ikou, status = "success")
└─ ✔ Done 19.06s
# ログツリーの内部状態を初期化する
logtree_reset()
# 定期バックアップのステップを開始し、ハンドルを受け取る
backup <- log_open("定期バックアップ")
▶ 定期バックアップ
# 終了時の状態と経過時間を返り値として受け取る
kekka <- log_close(backup)
└─ ✔ Done 10.75s
# 受け取った最終状態を表示する
cat(kekka$status, "\n")
success情報行の記録:log_infoコマンド
処理の途中経過を伝える情報行を書き出します。囲んでいるステップの状態には影響しません。closeオプションをTRUEにすると、この行が囲みの最終行としてプロットされ、ステップの終了行が省略されます。summaryオプションをTRUEにすると、後述のlogtree_summaryコマンドの要約対象に加えられます。
| オプション | 意味 | 初期値 |
|---|---|---|
| msg | 記録する内容を文字列で指定 | なし |
| close | この行で囲みのセクションを強制的に閉じるかを指定 | FALSE |
| summary | 要約への記録可否を指定。NAは警告とエラーのみ記録 | NA |
# ログツリーの内部状態を初期化する
logtree_reset()
# 会員登録の受付処理をおこなう関数を定義する
hanyu <- function() {
# ステップを開始する
log_step("会員登録の受付")
# 情報行を書き出し、この行を最終行としてステップを閉じる
log_info("本人確認書類を照合", close = TRUE)}
# 関数を実行する
hanyu()
▶ 会員登録の受付
└─ ℹ 本人確認書類を照合成功行の記録:log_successコマンド
処理が正常に完了したことを示す成功行をプロットします。情報行と同じく、囲んでいるステップの状態を変化させません。既定では要約に含まれませんので、あとで振り返りたい成功記録にはsummaryオプションにTRUEを指定します。
| オプション | 意味 | 初期値 |
|---|---|---|
| msg | 記録する内容を文字列で指定 | なし |
| close | この行で囲みのセクションを強制的に閉じるかを指定 | FALSE |
| summary | 要約への記録可否を指定。NAは警告とエラーのみ記録 | NA |
# ログツリーの内部状態を初期化する
logtree_reset()
# 会員情報の更新処理をおこなう関数を定義する
kaiin <- function() {
# ステップを開始する
log_step("会員情報の更新")
# 成功行を書き出し、要約にも記録するよう指定する
log_success("住所変更を1件反映", summary = TRUE)}
# 関数を実行する
kaiin()
▶ 会員情報の更新
├─ ✔ 住所変更を1件反映
└─ ✔ Done 0.02s
# 要約を表示する
logtree_summary()
Summary: 1 pinned
✔ 会員情報の更新 > 住所変更を1件反映警告行の記録:log_warnコマンド
注意を要する事象を警告行としてプロットします。同時に、囲んでいるステップの状態を警告へ引き上げるため、処理そのものが正常終了してもステップの終了行には警告のグリフが表示されます。既定で要約の対象になります。log_errorコマンドのコマンド例を参照してください。
| オプション | 意味 | 初期値 |
|---|---|---|
| msg | 記録する内容を文字列で指定 | なし |
| close | この行で囲みのセクションを強制的に閉じるかを指定 | FALSE |
| summary | 要約への記録可否を指定。NAは警告とエラーのみ記録 | NA |
エラー行の記録:log_errorコマンド
異常の発生をエラー行として書き出します。囲んでいるステップの状態をエラーへ引き上げますが、処理そのものを中断させるわけではありません。警告よりも優先度が高いため、警告で引き上げられた状態はエラーによってさらに上書きされます。
| オプション | 意味 | 初期値 |
|---|---|---|
| msg | 記録する内容を文字列で指定 | なし |
| close | この行で囲みのセクションを強制的に閉じるかを指定 | FALSE |
| summary | 要約への記録可否を指定。NAは警告とエラーのみ記録 | NA |
これまで紹介した、4段階のリーフを並べると、状態の引き上げの様子とグリフの違いを一度に確認できます。
# ログツリーの内部状態を初期化する
logtree_reset()
# 予約処理をおこなう関数を定義する
yoyaku <- function() {
# ステップを開始する
log_step("予約処理")
# 情報行を書き出す
log_info("予約キューを読み込みました")
# 成功行を書き出す
log_success("予約12件の登録が完了")
# 警告行を書き出し、ステップの状態を警告へ引き上げる
log_warn("延滞者3名の予約を保留")
# エラー行を書き出し、ステップの状態をエラーへ引き上げる
log_error("会員番号の重複を検出")}
# 関数を実行する
yoyaku()
▶ 予約処理
├─ ℹ 予約キューを読み込みました
├─ ✔ 予約12件の登録が完了
├─ ⚠ 延滞者3名の予約を保留
├─ ✖ 会員番号の重複を検出
└─ ✖ Done 0.02s
デバッグ行の記録:log_debugコマンド
開発時の詳細な診断情報をデバッグ行として書き出します。パッケージ読み込み直後では表示されません。表示するには、あらかじめlogtree_thresholdコマンドで閾値をdebugへ下げる必要があります。囲んでいるステップの状態は変化しません。
| オプション | 意味 | 初期値 |
|---|---|---|
| msg | 記録する内容を文字列で指定 | なし |
| close | この行で囲みのセクションを強制的に閉じるかを指定 | FALSE |
| summary | 要約への記録可否を指定。NAは警告とエラーのみ記録 | NA |
# ログツリーの内部状態を初期化する
logtree_reset()
# 表示する最小レベルをdebugへ下げる
logtree_threshold("debug")
# デバッグ行を書き出す。閾値がdebugのため表示される
log_debug("蔵書インデックスのキャッシュを再構築")
⚙ 蔵書インデックスのキャッシュを再構築
# 表示する最小レベルをinfoへ戻す
logtree_threshold("info")
# 閾値がinfoのため、このデバッグ行は表示されない
log_debug("この行は表示されません")
# 情報行はinfo以上のため表示される
log_info("集計処理を開始します")
ℹ 集計処理を開始します表示レベルの設定:logtree_thresholdコマンド
プロットするリーフの最小レベルを設定します。パッケージ読み込み時の既定はinfoで、デバッグ行だけが伏せられた状態です。ステップの開始行と終了行はツリーの骨格にあたるため、閾値にかかわらず常にプロットされます。また、閾値によって伏せられた警告行やエラー行も、囲んでいるステップの状態の引き上げは通常どおりおこないます。行の文字が見えなくなるだけで、状態は正しく伝わる仕組みです。
| オプション | 意味 | 初期値 |
|---|---|---|
| level | 描画する最小レベルをdebug、info、warn、errorのいずれかで指定 | “debug” |
# ログツリーの内部状態を初期化する
logtree_reset()
# 表示する最小レベルをwarnへ引き上げる
logtree_threshold("warn")
# 返却処理をおこなう関数を定義する
henkyaku <- function() {
# ステップを開始する
log_step("返却処理")
# 閾値がwarnのため、この情報行は表示されない
log_info("この情報行は表示されません")
# 警告行はwarn以上のため表示され、ステップの状態も引き上げられる
log_warn("破損本を1冊検出")}
# 関数を実行する
henkyaku()
▶ 返却処理
├─ ⚠ 破損本を1冊検出
└─ ⚠ Done 0.00s
# 表示する最小レベルをinfoへ戻す
logtree_threshold("info")グリフとテーマの設定:logtree_themeコマンド
行頭の記号と配色をまとめて切り替えます。プリセットはunicode、ascii、emojiの3種類で、ログをテキストファイルへ転記する場面や、記号が表示できない環境ではasciiが有効です。
overridesオプションでは、step、info、debug、success、warning、error、interrupted、group、branch、corner、pipeといった項目ごとに、記号・表示幅・色を個別に差し替えられます。compactオプションは階層あたりの字下げ幅を詰める設定で、深い入れ子を扱う際に画面の横幅を節約可能です。
| オプション | 意味 | 初期値 |
|---|---|---|
| theme | プリセット名、または上書き用の名前付きリストを指定 | “unicode” |
| overrides | 項目ごとの上書き設定を名前付きリストで指定 | list() |
| compact | 字下げ幅の詰め方をFALSE、”medium”、”tight”のいずれかで指定 | FALSE |
# ログツリーの内部状態を初期化する
logtree_reset()
# 配送準備の処理をおこなう関数を定義する
haisou <- function() {
# ステップを開始する
log_step("配送準備")
# 成功行を書き出す
log_success("配本リストを出力")}
# 記号をascii系に切り替えて実行する
logtree_theme("ascii")
haisou()
|- + 配本リストを出力
|- + Done 0.00s
# unicodeに戻し、字下げ幅を最も詰めた設定で実行する
logtree_theme("unicode", compact = "tight")
haisou()
├✔ 配本リストを出力
└✔ Done 0.00s
# 成功のグリフと色を個別に差し替えて実行する
logtree_theme("unicode", overrides = list(success = list(glyph = "◎", color = "cyan")))
haisou()
▶ 配送準備
├─ ◎ 配本リストを出力
└─ ◎ Done 0.00s
# 既定のunicodeテーマへ戻す
logtree_theme("unicode")注目イベントの要約:logtree_summaryコマンド
直近のlogtree_resetコマンド以降に発生した、注目すべき出来事だけを抜き出して一覧にします。既定では警告行とエラー行、および警告・エラー・中断のいずれかで終了したステップが対象です。
各行には状態のグリフと、発生場所までの経路が「パンくず」として表示されます。長いスクリプトの出力を遡らずに済むため、実行後の確認に便利です。返り値として記録の一覧が不可視となります。
| オプション | 意味 | 初期値 |
|---|---|---|
| filter | 表示対象とするステータスの文字列ベクトルを指定 | NULL |
| depth | 表示するパンくずの末尾ノード数を正の整数で指定 | NULL |
# ログツリーの内部状態を初期化する
logtree_reset()
# 蔵書データの監査をおこなう関数を定義する
kansa <- function() {
# ステップを開始する
log_step("蔵書データ監査")
# 警告行を書き出す
log_warn("ISBN未登録の資料を5件検出")
# エラー行を書き出す
log_error("分類コードの不正値を1件検出")
# 情報行を書き出し、要約にも記録するよう指定する
log_info("監査対象:2480件", summary = TRUE)}
# 関数を実行する
kansa()
▶ 蔵書データ監査
├─ ⚠ ISBN未登録の資料を5件検出
├─ ✖ 分類コードの不正値を1件検出
├─ ℹ 監査対象:2480件
└─ ✖ Done 0.00s
# すべての記録を要約として表示する
logtree_summary()
Summary: 1 error, 1 warning, 1 pinned
⚠ 蔵書データ監査 > ISBN未登録の資料を5件検出
✖ 蔵書データ監査 > 分類コードの不正値を1件検出
ℹ 蔵書データ監査 > 監査対象:2480件
# エラーのみに絞り込んで表示する
logtree_summary(filter = "error")
✖ 蔵書データ監査 > 分類コードの不正値を1件検出
# パンくずを末尾1ノードだけに省略して表示する
logtree_summary(depth = 1)
Summary: 1 error, 1 warning, 1 pinned
⚠ ISBN未登録の資料を5件検出
✖ 分類コードの不正値を1件検出
ℹ 監査対象:2480件
エラー処理付き実行:with_loggingコマンド
指定した処理を、トップレベルのエラー処理と実行時間の要約行つきで実行します。
処理の途中で捕捉されなかったエラーが発生した場合、開いているステップをすべて失敗として記録し、エラー内容をリーフとして書き出したうえで、エラーを再送出します。エラーを握りつぶすことはありません。exprは遅延評価されるため、内側のlog_stepコマンドは、そのブロックを字句的に囲む関数が終了した時点で閉じられます。関数の本体全体をwith_loggingコマンドで包む書き方にすると、対応関係が保たれます。
| オプション | 意味 | 初期値 |
|---|---|---|
| expr | 実行するコードを指定。globalがTRUEの場合は省略 | なし |
| summary | 実行終了の要約行を表示するかを指定 | TRUE |
| global | セッションに常駐するグローバルエラーハンドラを導入するかを指定 | FALSE |
# ログツリーの内部状態を初期化する
logtree_reset()
# 月次レポート生成の処理をおこなう関数を定義する
geppou <- function() {
# 関数の本体全体をwith_loggingで包む
with_logging({
# ステップを開始する
log_step("月次レポート生成")
# 成功行を書き出す
log_success("集計表をPDFに出力")
})}
# 関数を実行する
geppou()
▶ 月次レポート生成
├─ ✔ 集計表をPDFに出力
✔ Run complete in 0.00s
└─ ✔ Done 0.00s処理が異常終了した場合は、要約行がRun failedに変わり、開いていたステップの終了行にエラーのグリフが表示されます。
# ログツリーの内部状態を初期化する
logtree_reset()
# 蔵書CSVの取り込み処理をおこなう関数を定義する
torikomi <- function() {
# 関数の本体全体をwith_loggingで包む
with_logging({
# ステップを開始する
log_step("蔵書CSVの取り込み")
# 意図的にエラーを発生させる
stop("列数が定義と一致しません")
})}
# エラーを捕捉しながら関数を実行する
try(torikomi())
▶ 蔵書CSVの取り込み
├─ ✖ 列数が定義と一致しません
✖ Run failed in 0.00s
└─ ✖ Done 0.00s
Error in withCallingHandlers(expr, error = function(cnd) { :
列数が定義と一致しませんファイル出力先の追加:logtree_sink_fileコマンド
コンソールに加えて、ログをファイルへも書き出す出力先を登録します。
コンソールへの出力は常に有効なため、両方が同時に動作します。formatオプションにtextを指定すると、色情報を含まないASCIIのツリーが書き出され、コンソール側のテーマ設定には影響されません。jsonを指定すると、1イベント1行のNDJSON形式となり、時刻・ID・親ID・深さ・ラベル・経過時間・状態が構造化された形で保存されます。
| オプション | 意味 | 初期値 |
|---|---|---|
| path | 追記先のファイルパスを指定 | なし |
| format | 出力形式を”text”または”json”で指定 | “text” |
# ログツリーの内部状態を初期化する
logtree_reset()
# 出力先となる一時ファイルのパスを作成する
js <- tempfile(fileext = ".ndjson")
# NDJSON形式のファイル出力先を登録する
logtree_sink_file(js, format = "json")
# 書誌データの検証をおこなう関数を定義する
kensho <- function() {
# ステップを開始する
log_step("書誌データ検証")
# 警告行を書き出す
log_warn("重複ISBNを1件検出")}
# 関数を実行する
kensho()
▶ 書誌データ検証
├─ ⚠ 重複ISBNを1件検出
└─ ⚠ Done 0.00s
# 保存されたNDJSONの内容を表示する
cat(readLines(js), sep = "\n")
{"ts":1786863644,"level":"open","id":1,"parent_id":0,"depth":1,"label":"書誌データ検証","elapsed":null,"status":"step"}
{"ts":1786863644,"level":"leaf","id":2,"parent_id":1,"depth":1,"label":"重複ISBNを1件検出","elapsed":null,"status":"warning"}
{"ts":1786863644,"level":"close","id":1,"parent_id":0,"depth":1,"label":"書誌データ検証","elapsed":0,"status":"warning"}loggerパッケージの接続:logtree_loggerコマンド
「logger」パッケージの出力を、本パッケージのツリープロットに利用します。「logger」パッケージが未導入の場合、本コマンドの実行時にインストールの確認が求められます。
スクリプトの冒頭で一度呼び出しておけば、以降のlogger::log_infoコマンドなどの呼び出しが、そのままツリーのリーフとして描画されます。loggerの重大度は、FATALとERRORがエラー行、WARNが警告行、SUCCESSが成功行、INFOが情報行、DEBUGとTRACEがデバッグ行へ対応づけられます。thresholdオプションをTRUEにすると、loggerが自前で持つ閾値をTRACEまで開放するため、表示の制御をlogtree_thresholdコマンドに一本化できます。
エラー処理と要約行が必要な場合は、あわせてwith_loggingコマンドで処理を利用してください。
| オプション | 意味 | 初期値 |
|---|---|---|
| namespace | 経由させるloggerのネームスペースを指定 | “global” |
| threshold | loggerの閾値をTRACEまで開放するかを指定 | TRUE |
# ログツリーの内部状態を初期化する
logtree_reset()
# toshokanネームスペースのlogger出力をlogtree経由に切り替える
logtree_logger(namespace = "toshokan")
# 利用統計の算出をおこなう関数を定義する
sanshutsu <- function() {
# ステップを開始する
log_step("利用統計の算出")
# loggerの情報ログを出力する。logtreeのリーフとして描画される
logger::log_info("月間貸出件数を集計しました", namespace = "toshokan")
# loggerの警告ログを出力する。ステップの状態も引き上げられる
logger::log_warn("欠測日が1日あります", namespace = "toshokan")}
# 関数を実行する
sanshutsu()
▶ 利用統計の算出
├─ ℹ 月間貸出件数を集計しました
├─ ⚠ 欠測日が1日あります
└─ ⚠ Done 0.02sloggerレイアウトの提供:layout_logtreeコマンド
logtree_loggerコマンドの内部で使われている、「logger」パッケージ向けのレイアウト関数です。
loggerの処理はフォーマッタ、レイアウト、アペンダの順で進み、重大度の情報を受け取れるのはレイアウトの段階だけであるため、アペンダではなくレイアウトとして登録します。
あわせてlogger::appender_voidを指定し、loggerからの二重出力を止めます。前述のlogtree_loggerコマンドはこの2つの登録を一度にまとめたものですので、通常はそちらで足ります。ネームスペースごとに設定を細かく分けたい場合に本コマンドを直接使用します。
| オプション | 意味 | 初期値 |
|---|---|---|
| level | loggerのログレベルオブジェクトを指定 | なし |
| msg | loggerが整形済みの文字列を指定 | なし |
| namespace | 未使用。シグネチャ互換のために受け取る | NA_character_ |
| .logcall | 未使用。シグネチャ互換のために受け取る | sys.call() |
| .topcall | 未使用。シグネチャ互換のために受け取る | sys.call(-1) |
| .topenv | 未使用。シグネチャ互換のために受け取る | parent.frame() |
| .timestamp | 未使用。シグネチャ互換のために受け取る | Sys.time() |
# ログツリーの内部状態を初期化する
logtree_reset()
# kensakuネームスペースのレイアウトとしてlayout_logtreeを登録する
logger::log_layout(layout_logtree, namespace = "kensaku")
# 二重出力を避けるため、何もしないアペンダを登録する
logger::log_appender(logger::appender_void, namespace = "kensaku")
# 検索ログの解析をおこなう関数を定義する
kensaku <- function() {
# ステップを開始する
log_step("検索ログの解析")
# loggerの情報ログを出力する。logtreeのリーフとして描画される
logger::log_info("検索キーワード上位20件を抽出", namespace = "kensaku")}
# 関数を実行する
kensaku()
▶ 検索ログの解析
├─ ℹ 検索キーワード上位20件を抽出
└─ ✔ Done 0.00s
実行例
パッケージの機能を組み合わせた、使い方の例です。
支店別集計のグループ表示と要約レポート
複数の館の貸出件数を順に集計する処理です。groupオプションを使うと、隣り合うステップが1つの見出しの下にまとめられ、館ごとの処理が横並びにプロットされます。欠測を検出した館では警告行が出るため、その館のステップと、それを束ねるグループの終了行にも警告のグリフがプロットされます。最後にlogtree_summaryコマンドで、どの館のどの処理で問題が起きたかをパンくず付きで確認します。
# ログツリーの内部状態を初期化する
logtree_reset()
# 3館4か月分の貸出件数データを作成する
kashidashi <- data.frame(
# 館名を4行ずつ繰り返して作成する
shiten = rep(c("中央館", "北分館", "南分館"), each = 4),
# 月名を3回繰り返して作成する
tsuki = rep(c("4月", "5月", "6月", "7月"), times = 3),
# 貸出件数を作成する。南分館の6月は欠測として0を入れる
kensu = c(1820, 1755, 1902, 2044, 640, 612, 588, 701, 933, 1010, 0, 987))
# 1館分の集計をおこなう関数を定義する
shiten_shori <- function(bu) {
# 館名をラベルにしたステップを、支店別集計グループの下に開始する
log_step(bu$shiten[1], group = c(支店別集計 = "shiten"))
# 件数が0の月があれば警告行を書き出す
if (any(bu$kensu == 0)) {
log_warn(paste0(sum(bu$kensu == 0), "件の欠測月を検出"))
}
# 合計と平均を情報行として書き出す
log_info(paste0("合計 ", sum(bu$kensu), " 件 / 平均 ", round(mean(bu$kensu), 1), " 件"))}
# 全館の月次集計をおこなう関数を定義する
getsuji_shukei <- function(dat) {
# 関数の本体全体をwith_loggingで包む
with_logging({
# 全体を束ねるステップを開始する
log_step("月次貸出集計")
# 館ごとに集計処理を呼び出す
for (sh in unique(dat$shiten)) {
shiten_shori(dat[dat$shiten == sh, ])
}
# 全館の完了を成功行として書き出す
log_success(paste0("全", length(unique(dat$shiten)), "館の集計が完了"))
})}
# 集計を実行する
getsuji_shukei(kashidashi)
▶ 月次貸出集計
├─ ▣ 支店別集計
│ ├─ ▶ 中央館
│ │ ├─ ℹ 合計 7521 件 / 平均 1880.2 件
│ │ └─ ✔ Done 0.01s
│ ├─ ▶ 北分館
│ │ ├─ ℹ 合計 2541 件 / 平均 635.2 件
│ │ └─ ✔ Done 0.00s
│ ├─ ▶ 南分館
│ │ ├─ ⚠ 1件の欠測月を検出
│ │ ├─ ℹ 合計 2930 件 / 平均 732.5 件
│ │ └─ ⚠ Done 0.00s
│ └─ ⚠ Done 0.05s
├─ ✔ 全3館の集計が完了
✔ Run complete in 0.05s
└─ ✔ Done 0.05s
# 注目すべき出来事を要約として表示する
logtree_summary()
Summary: 1 warning
⚠ 月次貸出集計 > 支店別集計 > 南分館 > 1件の欠測月を検出異常終了時のツリー保全とファイル記録
検証処理の途中でエラーを発生させ、ツリーのプロットの担保を確認する例です。
閾値をdebugへ下げて診断行もプロットし、テキスト形式のファイル出力先を登録してコンソールとファイルの双方へ記録します。エラーは内側の関数から送出されますが、with_loggingコマンドが開いているステップをすべて失敗として閉じるため、字下げが崩れることなくツリーが完結します。ファイル側はコンソールのテーマ設定に依存せず、常にASCIIで書き出される点も確認できます。
# ログツリーの内部状態を初期化する
logtree_reset()
# 診断行も描画されるよう、表示する最小レベルをdebugへ下げる
logtree_threshold("debug")
# 出力先となる一時ファイルのパスを作成する
rireki_file <- tempfile(fileext = ".log")
# テキスト形式のファイル出力先を登録する
logtree_sink_file(rireki_file, format = "text")
# 検証対象となる資料データを作成する
shiryo <- data.frame(
# 資料の整理番号を作成する
seiri_bango = c("A-001", "A-002", "A-003", "A-004"),
# 分類コードを作成する。4件目は不正な値とする
bunrui = c("913", "289", "007", "XXX"),
# 資料の状態を作成する
jotai = c("配架", "貸出中", "配架", "修理中")
)
# 分類コードの検証をおこなう関数を定義する
kensho <- function(dat) {
# ステップを開始する
log_step("分類コードの検証")
# 読み込み件数をデバッグ行として書き出す
log_debug(paste0("検証対象 ", nrow(dat), " 件を読み込み"))
# 数字3桁でない分類コードを持つ資料の整理番号を抽出する
fusei <- dat$seiri_bango[!grepl("^\\d{3}$", dat$bunrui)]
# 不正な資料があればエラー行を書き出して処理を中断する
if (length(fusei) > 0) {
log_error(paste0("不正な分類コード:", paste(fusei, collapse = ", ")))
stop("分類コードの検証に失敗しました")
}
# 問題がなければ成功行を書き出す
log_success("すべての分類コードが正常")
}
# 蔵書データの取り込みをおこなう関数を定義する
torikomi <- function(dat) {
# 関数の本体全体をwith_loggingで包む
with_logging({
# 全体を束ねるステップを開始する
log_step("蔵書データ取り込み")
# 接続処理をデバッグ行として書き出す
log_debug("データベース接続を確立")
# 検証処理を呼び出す
kensho(dat)
})
}
# エラーメッセージの表示を抑えつつ取り込みを実行する
try(torikomi(shiryo), silent = TRUE)
# パンくずを末尾2ノードに省略して要約を表示する
logtree_summary(depth = 2)
# ファイルへ記録された内容を表示する
cat(readLines(rireki_file), sep = "\n")
# 表示する最小レベルをinfoへ戻す
logtree_threshold("info")実行結果:
# ログツリーの内部状態を初期化する
logtree_reset()
# 診断行も描画されるよう、表示する最小レベルをdebugへ下げる
logtree_threshold("debug")
# 出力先となる一時ファイルのパスを作成する
rireki_file <- tempfile(fileext = ".log")
# テキスト形式のファイル出力先を登録する
logtree_sink_file(rireki_file, format = "text")
# 検証対象となる資料データを作成する
shiryo <- data.frame(
# 資料の整理番号を作成する
seiri_bango = c("A-001", "A-002", "A-003", "A-004"),
# 分類コードを作成する。4件目は不正な値とする
bunrui = c("913", "289", "007", "XXX"),
# 資料の状態を作成する
jotai = c("配架", "貸出中", "配架", "修理中"))
# 分類コードの検証をおこなう関数を定義する
kensho <- function(dat) {
# ステップを開始する
log_step("分類コードの検証")
# 読み込み件数をデバッグ行として書き出す
log_debug(paste0("検証対象 ", nrow(dat), " 件を読み込み"))
# 数字3桁でない分類コードを持つ資料の整理番号を抽出する
fusei <- dat$seiri_bango[!grepl("^\\d{3}$", dat$bunrui)]
# 不正な資料があればエラー行を書き出して処理を中断する
if (length(fusei) > 0) {
log_error(paste0("不正な分類コード:", paste(fusei, collapse = ", ")))
stop("分類コードの検証に失敗しました")
}
# 問題がなければ成功行を書き出す
log_success("すべての分類コードが正常")}
# 蔵書データの取り込みをおこなう関数を定義する
torikomi <- function(dat) {
# 関数の本体全体をwith_loggingで包む
with_logging({
# 全体を束ねるステップを開始する
log_step("蔵書データ取り込み")
# 接続処理をデバッグ行として書き出す
log_debug("データベース接続を確立")
# 検証処理を呼び出す
kensho(dat)
})}
# エラーメッセージの表示を抑え取り込みを実行する
try(torikomi(shiryo), silent = TRUE)
▶ 蔵書データ取り込み
├─ ⚙ データベース接続を確立
├─ ▶ 分類コードの検証
│ ├─ ⚙ 検証対象 4 件を読み込み
│ ├─ ✖ 不正な分類コード:A-004
│ ├─ ✖ 分類コードの検証に失敗しました
│ └─ ✖ Done 0.00s
✖ Run failed in 0.02s
└─ ✖ Done 0.02s
# パンくずを末尾2ノードに省略して要約を表示する
logtree_summary(depth = 2)
Summary: 2 errors
✖ 分類コードの検証 > 不正な分類コード:A-004
✖ 分類コードの検証 > 分類コードの検証に失敗しました
# ファイルへ記録された内容を表示する
cat(readLines(rireki_file), sep = "\n")
|- d データベース接続を確立
|- > 分類コードの検証
| |- d 検証対象 4 件を読み込み
| |- x 不正な分類コード:A-004
| |- x 分類コードの検証に失敗しました
| |- x Done 0.00s
|- x Done 0.02s
# 表示する最小レベルをinfoへ戻す
logtree_threshold("info")
この記事が誰かの役に立ちますように。